From 64ea85cfc14f2772bb64ba94144a144ae9ae26f8 Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 14 Jul 2022 18:29:24 -0700 Subject: [PATCH 001/183] Improve search filter on SelectTokenDialog --- .../app/ui/widget/adapter/SelectTokenAdapter.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java index 01efa6769e..8a8a1a51de 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java @@ -79,6 +79,18 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) public void filter(String searchFilter) { List filteredList = new ArrayList<>(); + for (Connection.LToken data : tokens) + { + if (data.name.toLowerCase(Locale.ENGLISH).startsWith(searchFilter.toLowerCase(Locale.ENGLISH))) + { + filteredList.add(data); + } + else if (data.symbol.toLowerCase(Locale.ENGLISH).startsWith(searchFilter.toLowerCase(Locale.ENGLISH))) + { + filteredList.add(data); + } + } + for (Connection.LToken data : tokens) { if (data.name.toLowerCase(Locale.ENGLISH).contains(searchFilter.toLowerCase(Locale.ENGLISH))) @@ -90,6 +102,7 @@ else if (data.symbol.toLowerCase(Locale.ENGLISH).contains(searchFilter.toLowerCa filteredList.add(data); } } + updateList(filteredList); } From b1b60e4fd98c0506e6b086e7aa415fdfd351c5c9 Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 14 Jul 2022 18:41:19 -0700 Subject: [PATCH 002/183] Prevent duplicates --- .../alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java index 8a8a1a51de..a3578468a7 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java @@ -95,11 +95,11 @@ else if (data.symbol.toLowerCase(Locale.ENGLISH).startsWith(searchFilter.toLower { if (data.name.toLowerCase(Locale.ENGLISH).contains(searchFilter.toLowerCase(Locale.ENGLISH))) { - filteredList.add(data); + if (!filteredList.contains(data)) filteredList.add(data); } else if (data.symbol.toLowerCase(Locale.ENGLISH).contains(searchFilter.toLowerCase(Locale.ENGLISH))) { - filteredList.add(data); + if (!filteredList.contains(data)) filteredList.add(data); } } From a5303354deec7c6dbe7632f782613e41e4d6b57b Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Fri, 15 Jul 2022 19:02:22 +0800 Subject: [PATCH 003/183] Add test and refactor --- .../ui/widget/adapter/SelectTokenAdapter.java | 34 +------- .../app/ui/widget/adapter/TokenFilter.java | 45 ++++++++++ .../ui/widget/adapter/TokenFilterTest.java | 84 +++++++++++++++++++ 3 files changed, 133 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java create mode 100644 app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java index a3578468a7..0118a9bc30 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java @@ -18,18 +18,17 @@ import java.util.ArrayList; import java.util.List; -import java.util.Locale; public class SelectTokenAdapter extends RecyclerView.Adapter { - private final List tokens; private final List displayData; private final SelectTokenDialog.SelectTokenDialogEventListener callback; private String selectedTokenAddress; + private final TokenFilter tokenFilter; public SelectTokenAdapter(List tokens, SelectTokenDialog.SelectTokenDialogEventListener callback) { - this.tokens = tokens; + tokenFilter = new TokenFilter(tokens); this.callback = callback; displayData = new ArrayList<>(); displayData.addAll(tokens); @@ -76,34 +75,9 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) } } - public void filter(String searchFilter) + public void filter(String keyword) { - List filteredList = new ArrayList<>(); - for (Connection.LToken data : tokens) - { - if (data.name.toLowerCase(Locale.ENGLISH).startsWith(searchFilter.toLowerCase(Locale.ENGLISH))) - { - filteredList.add(data); - } - else if (data.symbol.toLowerCase(Locale.ENGLISH).startsWith(searchFilter.toLowerCase(Locale.ENGLISH))) - { - filteredList.add(data); - } - } - - for (Connection.LToken data : tokens) - { - if (data.name.toLowerCase(Locale.ENGLISH).contains(searchFilter.toLowerCase(Locale.ENGLISH))) - { - if (!filteredList.contains(data)) filteredList.add(data); - } - else if (data.symbol.toLowerCase(Locale.ENGLISH).contains(searchFilter.toLowerCase(Locale.ENGLISH))) - { - if (!filteredList.contains(data)) filteredList.add(data); - } - } - - updateList(filteredList); + updateList(tokenFilter.filterBy(keyword)); } public void updateList(List filteredList) diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java new file mode 100644 index 0000000000..8dc49a0504 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java @@ -0,0 +1,45 @@ +package com.alphawallet.app.ui.widget.adapter; + +import androidx.annotation.NonNull; + +import com.alphawallet.app.entity.lifi.Connection; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class TokenFilter +{ + private final List tokens; + + public TokenFilter(List tokens) + { + this.tokens = tokens; + } + + public List filterBy(String keyword) + { + String lowerCaseKeyword = lowerCase(keyword); + + List result = new ArrayList<>(); + for (Connection.LToken lToken : this.tokens) + { + String name = lowerCase(lToken.name); + String symbol = lowerCase(lToken.symbol); + + if (name.startsWith(lowerCaseKeyword) || name.contains(lowerCaseKeyword) + || symbol.startsWith(lowerCaseKeyword) || symbol.contains(lowerCaseKeyword)) + { + result.add(lToken); + } + } + return result; + } + + @NonNull + private String lowerCase(String name) + { + return name.toLowerCase(Locale.ENGLISH); + } + +} diff --git a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java new file mode 100644 index 0000000000..7c18434861 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java @@ -0,0 +1,84 @@ +package com.alphawallet.app.ui.widget.adapter; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import androidx.annotation.NonNull; + +import com.alphawallet.app.entity.lifi.Connection; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class TokenFilterTest +{ + private TokenFilter tokenFilter; + + @Before + public void setUp() throws Exception + { + List list = new ArrayList<>(); + list.add(createToken("Ethereum", "ETH", "1")); + list.add(createToken("Solana", "SOL", "2")); + list.add(createToken("Binance", "BNB", "3")); + tokenFilter = new TokenFilter(list); + } + + @Test + public void nameContains() + { + List result = tokenFilter.filterBy("an"); + assertThat(result.size(), equalTo(2)); + assertThat(result.get(0).name, equalTo("Solana")); + assertThat(result.get(1).name, equalTo("Binance")); + } + + @Test + public void nameStartsWith() + { + List result = tokenFilter.filterBy("So"); + assertThat(result.size(), equalTo(1)); + assertThat(result.get(0).name, equalTo("Solana")); + } + + @Test + public void symbolContains() + { + List result = tokenFilter.filterBy("B"); + assertThat(result.size(), equalTo(1)); + assertThat(result.get(0).name, equalTo("Binance")); + } + + @Test + public void symbolStartsWith() + { + List result = tokenFilter.filterBy("S"); + assertThat(result.size(), equalTo(1)); + assertThat(result.get(0).name, equalTo("Solana")); + } + + @Test + public void should_be_case_insensitive() + { + List result = tokenFilter.filterBy("s"); + assertThat(result.size(), equalTo(1)); + assertThat(result.get(0).name, equalTo("Solana")); + + result = tokenFilter.filterBy("b"); + assertThat(result.size(), equalTo(1)); + assertThat(result.get(0).name, equalTo("Binance")); + } + + @NonNull + private Connection.LToken createToken(String name, String symbol, String address) + { + Connection.LToken e = new Connection.LToken(); + e.name = name; + e.symbol = symbol; + e.address = address; + return e; + } +} \ No newline at end of file From 30ed8283c2b201e052ad07aaf63138db7af918ad Mon Sep 17 00:00:00 2001 From: justindg Date: Sun, 17 Jul 2022 15:43:19 -0700 Subject: [PATCH 004/183] Split filters to achieve desired order --- .../app/ui/widget/adapter/TokenFilter.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java index 8dc49a0504..dd57ff6a6d 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java @@ -22,17 +22,32 @@ public List filterBy(String keyword) String lowerCaseKeyword = lowerCase(keyword); List result = new ArrayList<>(); + // First filter: Add all entries that start with the keyword on top of the list. for (Connection.LToken lToken : this.tokens) { String name = lowerCase(lToken.name); String symbol = lowerCase(lToken.symbol); - if (name.startsWith(lowerCaseKeyword) || name.contains(lowerCaseKeyword) - || symbol.startsWith(lowerCaseKeyword) || symbol.contains(lowerCaseKeyword)) + if (name.startsWith(lowerCaseKeyword) || symbol.startsWith(lowerCaseKeyword)) { result.add(lToken); } } + + // Second filter: Add the rest of the entries that contain the keyword on top of the list. + for (Connection.LToken lToken : this.tokens) + { + String name = lowerCase(lToken.name); + String symbol = lowerCase(lToken.symbol); + + if (name.contains(lowerCaseKeyword) || symbol.contains(lowerCaseKeyword)) + { + if (!result.contains(lToken)) + { + result.add(lToken); + } + } + } return result; } From 4dd473bd11a4a85a3a722af118856f261c4ff233 Mon Sep 17 00:00:00 2001 From: justindg Date: Sun, 17 Jul 2022 16:12:46 -0700 Subject: [PATCH 005/183] [Swap] Sort Tokens in Dialog (#2724) * Sort alphabetically, then sort again by balance * Modified sort to ignore case --- .../com/alphawallet/app/widget/SelectTokenDialog.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java b/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java index d567e5b4f4..6737335046 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java @@ -21,10 +21,11 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.lifi.Connection; import com.alphawallet.app.ui.widget.adapter.SelectTokenAdapter; -import com.alphawallet.app.ui.widget.divider.ListDivider; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetDialog; +import java.math.BigDecimal; +import java.util.Collections; import java.util.List; public class SelectTokenDialog extends BottomSheetDialog @@ -65,6 +66,13 @@ public SelectTokenDialog(List tokenItems, Activity activity, noResultsText.setVisibility(tokenItems.size() > 0 ? View.GONE : View.VISIBLE); + Collections.sort(tokenItems, (l, r) -> l.name.compareToIgnoreCase(r.name)); + Collections.sort(tokenItems, (l, r) -> { + BigDecimal lBal = new BigDecimal(l.balance); + BigDecimal rBal = new BigDecimal(r.balance); + return rBal.compareTo(lBal); + }); + adapter = new SelectTokenAdapter(tokenItems, callback); tokenList.setLayoutManager(new LinearLayoutManager(getContext())); From be8140dd9a1c028b5682297091fbfe0a925db6d2 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Mon, 18 Jul 2022 11:37:38 +0800 Subject: [PATCH 006/183] Add test --- .../app/ui/widget/adapter/TokenFilterTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java index 7c18434861..bf5bec3dbf 100644 --- a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java +++ b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java @@ -72,6 +72,21 @@ public void should_be_case_insensitive() assertThat(result.get(0).name, equalTo("Binance")); } + @Test + public void should_sort_starts_with_in_front_of_contains() + { + List list = new ArrayList<>(); + list.add(createToken("Solana", "SOL", "2")); + list.add(createToken("WETH", "WETH", "2")); + list.add(createToken("Ethereum", "ETH", "1")); + tokenFilter = new TokenFilter(list); + + List result = tokenFilter.filterBy("eth"); + assertThat(result.size(), equalTo(2)); + assertThat(result.get(0).name, equalTo("Ethereum")); + assertThat(result.get(1).name, equalTo("WETH")); + } + @NonNull private Connection.LToken createToken(String name, String symbol, String address) { From de522fd200da431614735a6c2890282a3d4bdb69 Mon Sep 17 00:00:00 2001 From: Hwee-Boon Yar Date: Mon, 18 Jul 2022 15:38:36 +0800 Subject: [PATCH 007/183] [DMZ] Tweak message shown https://aw.app/wc is visited (#2729) --- .../java/com/alphawallet/token/web/AppSiteController.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java b/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java index 03567ad6de..0a9b4b8bc9 100644 --- a/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java +++ b/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java @@ -130,6 +130,10 @@ public RedirectView home(RedirectAttributes attributes){ ) throws IOException, SAXException, NoHandlerFoundException { + if (universalLink.equals("wc")) + { + return "If you are using AlphaWallet with WalletConnect, please launch the AlphaWallet app"; + } String domain = request.getServerName(); ParseMagicLink parser = new ParseMagicLink(cryptoFunctions, null); MagicLinkData data; From 3b7a885a2ab45e84ac464c43a1996ebd1b27968e Mon Sep 17 00:00:00 2001 From: Hwee-Boon Yar Date: Mon, 18 Jul 2022 16:49:48 +0800 Subject: [PATCH 008/183] [DMZ] Remove /api/v1/verifyXMLDSig #2678 (#2730) --- .../token/web/AppSiteController.java | 49 ------------------- 1 file changed, 49 deletions(-) diff --git a/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java b/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java index 0a9b4b8bc9..56091278fc 100644 --- a/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java +++ b/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java @@ -552,55 +552,6 @@ private class CachedResult } } - /* usage: (Weiwu documented after Sangalli's implementation) - - 1) for a test file whose root certificate isn't in the trusted CA list: - - $ curl -F 'file=@lib/src/test/ts/EntryToken.tsml' localhost:8080/api/v1/verifyXMLDSig - {"result":"fail","failureReason":"Path does not chain with any of the trust anchors"} - - 2) for a test file which has valid certificates: - - $ curl -F 'file=@lib/src/test/ts/DAI.tsml' localhost:8080/api/v1/verifyXMLDSig - {"result":"pass","subject":"CN=*.aw.app","keyName":"","keyType":"SHA256withRSA","issuer":"CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US"} - - Client be-aware! Please handle return code 404 gracefully. It's content look like this: - - { - "timestamp": "2019-07-04T08:43:32.885+0000", - "status": 404, - "error": "Not Found", - "message": "API v1 is no longer supported. Upgrade your software.", - "path": "/api/v1/verifyXMLDSig" - } - - This message likely signify that version 1 of the api is no longer supported, i.e. the client is too old. - You can simply display the message to the end user (despite it's not multi-lingual). - */ - @PostMapping("/api/v1/verifyXMLDSig") - @ResponseBody - @SuppressWarnings("unchecked") - public ResponseEntity validateSSLCertificate(@RequestParam("file") MultipartFile file) throws IOException { - HttpStatus status = HttpStatus.ACCEPTED; - JsonObject result = new JsonObject(); - XMLDsigVerificationResult XMLDsigVerificationResult = new XMLDSigVerifier().VerifyXMLDSig(file.getInputStream()); - if (XMLDsigVerificationResult.isValid) - { - result.put("result", "pass"); - result.put("issuer", XMLDsigVerificationResult.issuerPrincipal); - result.put("subject", XMLDsigVerificationResult.subjectPrincipal); - result.put("keyName", XMLDsigVerificationResult.keyName); - result.put("keyType", XMLDsigVerificationResult.keyType); - } - else - { - result.put("result", "fail"); - result.put("failureReason", XMLDsigVerificationResult.failureReason); - status = HttpStatus.BAD_REQUEST; - } - return new ResponseEntity(result.toJson(), status); - } - private static void loadInfuraKey() { try (InputStream input = new FileInputStream("../gradle.properties")) { From 9cccea9f024bfec838d8805f948c2003289eb500 Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 18 Jul 2022 11:01:37 +0100 Subject: [PATCH 009/183] Enhance Swap Token Sort (#2727) * Only allow positive balance tokens for source serach * Add tests * Change to compareToIgnoreCase + Update test * Extract Tokens class * Add tests * update sort to match the order DEXes use Co-authored-by: Seaborn Lee --- .../app/entity/lifi/Connection.java | 8 ++ .../com/alphawallet/app/ui/SwapActivity.java | 58 ++++--------- .../app/viewmodel/SwapViewModel.java | 35 ++++++-- .../com/alphawallet/app/viewmodel/Tokens.java | 48 +++++++++++ .../app/widget/SelectTokenDialog.java | 11 --- app/src/main/res/values/strings.xml | 2 +- .../alphawallet/app/viewmodel/TokensTest.java | 82 +++++++++++++++++++ 7 files changed, 183 insertions(+), 61 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/Tokens.java create mode 100644 app/src/test/java/com/alphawallet/app/viewmodel/TokensTest.java diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java index cc1f084bcd..ea4192cab5 100644 --- a/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java @@ -59,6 +59,7 @@ public static class LToken public String logoURI; public String balance; + public double fiatEquivalent; @Override public boolean equals(Object o) @@ -74,5 +75,12 @@ public int hashCode() { return Objects.hash(address, symbol); } + + // Note: In the LIFI API, the native token has either of these two addresses. + public boolean isNativeToken() + { + return address.equalsIgnoreCase("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") || + address.equalsIgnoreCase("0x0000000000000000000000000000000000000000"); + } } } diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index 3ae7faa618..49bfa7c6fb 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -28,6 +28,7 @@ import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.util.BalanceUtils; import com.alphawallet.app.viewmodel.SwapViewModel; +import com.alphawallet.app.viewmodel.Tokens; import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.ActionSheetDialog; @@ -178,7 +179,7 @@ public void onSelectionChanged(Connection.LToken token) @Override public void onMaxClicked() { - String max = viewModel.getBalance(wallet.address, sourceSelector.getToken()); + String max = viewModel.getBalance(sourceSelector.getToken()); if (!max.isEmpty()) { sourceSelector.setAmount(max); @@ -246,7 +247,7 @@ private ActionSheetDialog createConfirmationAction(Quote quote) private void destTokenChanged(Connection.LToken token) { - destSelector.setBalance(viewModel.getBalance(wallet.address, token)); + destSelector.setBalance(viewModel.getBalance(token)); infoLayout.setVisibility(View.GONE); @@ -262,7 +263,7 @@ private void sourceTokenChanged(Connection.LToken token) destSelector.setVisibility(View.VISIBLE); } - sourceSelector.setBalance(viewModel.getBalance(wallet.address, token)); + sourceSelector.setBalance(viewModel.getBalance(token)); infoLayout.setVisibility(View.GONE); @@ -293,42 +294,11 @@ private void initSourceToken(Connection.LToken selectedToken) sourceSelector.reset(); infoLayout.setVisibility(View.GONE); } - - //TODO: Add base 'ETH' to dest tokens in selector - /*long networkId = fromTokens.get(0).chainId; - - String symbol = "eth"; - - for (Chain c : chains) - { - if (c.id == networkId) - { - symbol = c.coin; - } - } - - boolean matchFound = false; - - for (Connection.LToken t : fromTokens) - { - if (t.symbol.equalsIgnoreCase(symbol)) - { - sourceSelector.init(t); - matchFound = true; - break; - } - } - - if (!matchFound) - { - sourceSelector.reset(); - - infoLayout.setVisibility(View.GONE); - }*/ } private void initFromDialog(List fromTokens) { + Tokens.sortValue(fromTokens); sourceTokenDialog = new SelectTokenDialog(fromTokens, this, tokenItem -> { sourceSelector.init(tokenItem); sourceTokenDialog.dismiss(); @@ -337,6 +307,8 @@ private void initFromDialog(List fromTokens) private void initToDialog(List toTokens) { + Tokens.sortName(toTokens); + Tokens.sortValue(toTokens); destTokenDialog = new SelectTokenDialog(toTokens, this, tokenItem -> { destSelector.init(tokenItem); destTokenDialog.dismiss(); @@ -409,12 +381,17 @@ private void onConnections(List connections) { if (!fromTokens.contains(t)) { - t.balance = viewModel.getBalance(wallet.address, t); - fromTokens.add(t); + t.balance = viewModel.getBalance(t); + t.fiatEquivalent = viewModel.getFiatValue(t); - if (t.chainId == token.tokenInfo.chainId && t.address.equalsIgnoreCase(token.getAddress())) + if (t.fiatEquivalent > 0) { - selectedToken = t; + fromTokens.add(t); + + if (t.chainId == token.tokenInfo.chainId && t.address.equalsIgnoreCase(token.getAddress())) + { + selectedToken = t; + } } } } @@ -423,7 +400,8 @@ private void onConnections(List connections) { if (!toTokens.contains(t)) { - t.balance = viewModel.getBalance(wallet.address, t); + t.balance = viewModel.getBalance(t); + t.fiatEquivalent = viewModel.getFiatValue(t); toTokens.add(t); } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java index 73f1eea7f9..f77ba4ae2b 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java @@ -163,7 +163,7 @@ public void getConnections(long from, long to) public void getQuote(Connection.LToken source, Connection.LToken dest, String address, String amount, String slippage) { - if (hasEnoughBalance(address, source, amount)) + if (hasEnoughBalance(source, amount)) { progressInfo.postValue(C.ProgressInfo.FETCHING_QUOTE); progress.postValue(true); @@ -179,9 +179,9 @@ public void getQuote(Connection.LToken source, Connection.LToken dest, String ad } } - public boolean hasEnoughBalance(String address, Connection.LToken source, String amount) + public boolean hasEnoughBalance(Connection.LToken source, String amount) { - BigDecimal bal = new BigDecimal(getBalance(address, source)); + BigDecimal bal = new BigDecimal(getBalance(source)); BigDecimal reqAmount = new BigDecimal(amount); return bal.compareTo(reqAmount) >= 0; } @@ -262,18 +262,21 @@ private boolean isValidQuote(String result) && result.contains("tool"); } - public String getBalance(String walletAddress, Connection.LToken token) + public String getBalance(Connection.LToken token) { - String address = token.address; + Token t; // Note: In the LIFI API, the native token has either of these two addresses. // In AlphaWallet, the wallet address is used. - if (address.equalsIgnoreCase("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") || - address.equalsIgnoreCase("0x0000000000000000000000000000000000000000")) + if (token.isNativeToken()) { - address = walletAddress; + t = tokensService.getServiceToken(token.chainId); } - Token t = tokensService.getToken(token.chainId, address); + else + { + t = tokensService.getToken(token.chainId, token.address); + } + if (t != null) { return BalanceUtils.getShortFormat(t.balance.toString(), t.tokenInfo.decimals); @@ -281,6 +284,20 @@ public String getBalance(String walletAddress, Connection.LToken token) else return "0"; } + public double getFiatValue(Connection.LToken t) + { + try + { + double value = Double.parseDouble(t.balance); + double priceUSD = Double.parseDouble(t.priceUSD); + return value * priceUSD; + } + catch (NumberFormatException|NullPointerException e) + { + return 0.0; + } + } + public void getAuthentication(Activity activity, Wallet wallet, SignAuthenticationCallback callback) { keyService.getAuthenticationForSignature(wallet, activity, callback); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/Tokens.java b/app/src/main/java/com/alphawallet/app/viewmodel/Tokens.java new file mode 100644 index 0000000000..cd4367823d --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/Tokens.java @@ -0,0 +1,48 @@ +package com.alphawallet.app.viewmodel; + +import com.alphawallet.app.entity.lifi.Connection; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; + +public class Tokens +{ + public static void sortValue(List tokenItems) + { + Collections.sort(tokenItems, (l, r) -> { + if (l.isNativeToken()) + { + return -1; + } + else if (r.isNativeToken()) + { + return 1; + } + else + { + BigDecimal lBal = new BigDecimal(l.fiatEquivalent); + BigDecimal rBal = new BigDecimal(r.fiatEquivalent); + return rBal.compareTo(lBal); + } + }); + } + + public static void sortName(List tokenItems) + { + Collections.sort(tokenItems, (l, r) -> { + if (l.isNativeToken()) + { + return -1; + } + else if (r.isNativeToken()) + { + return 1; + } + else + { + return l.name.compareToIgnoreCase(r.name); + } + }); + } +} diff --git a/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java b/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java index 6737335046..c98fb66881 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java @@ -24,8 +24,6 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetDialog; -import java.math.BigDecimal; -import java.util.Collections; import java.util.List; public class SelectTokenDialog extends BottomSheetDialog @@ -33,7 +31,6 @@ public class SelectTokenDialog extends BottomSheetDialog private final Handler handler = new Handler(Looper.getMainLooper()); private RecyclerView tokenList; private SelectTokenAdapter adapter; - private List tokenItems; private LinearLayout searchLayout; private EditText search; private TextView noResultsText; @@ -62,17 +59,9 @@ public SelectTokenDialog(@NonNull Activity activity) public SelectTokenDialog(List tokenItems, Activity activity, SelectTokenDialogEventListener callback) { this(activity); - this.tokenItems = tokenItems; noResultsText.setVisibility(tokenItems.size() > 0 ? View.GONE : View.VISIBLE); - Collections.sort(tokenItems, (l, r) -> l.name.compareToIgnoreCase(r.name)); - Collections.sort(tokenItems, (l, r) -> { - BigDecimal lBal = new BigDecimal(l.balance); - BigDecimal rBal = new BigDecimal(r.balance); - return rBal.compareTo(lBal); - }); - adapter = new SelectTokenAdapter(tokenItems, callback); tokenList.setLayoutManager(new LinearLayoutManager(getContext())); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b98fe13e60..37d9045474 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -565,7 +565,7 @@ Failed to sign redeem message Token Type Reddit - TokenScript Compatibiity + TokenScript Compatibility Version TokenScript debug untrusted diff --git a/app/src/test/java/com/alphawallet/app/viewmodel/TokensTest.java b/app/src/test/java/com/alphawallet/app/viewmodel/TokensTest.java new file mode 100644 index 0000000000..910d45037d --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/viewmodel/TokensTest.java @@ -0,0 +1,82 @@ +package com.alphawallet.app.viewmodel; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import com.alphawallet.app.entity.lifi.Connection; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class TokensTest +{ + @Test + public void sort_token_by_fiat_value_in_DESC() + { + List list = new ArrayList<>(); + list.add(createToken("Ethereum", "ETH", "0x0", 0)); + list.add(createToken("Binance Smart Chain", "BNB", "0x1", 1)); + list.add(createToken("Solana", "SOL", "0x2", 2)); + + Tokens.sortValue(list); + + assertThat(list.get(0).symbol, equalTo("SOL")); + assertThat(list.get(1).symbol, equalTo("BNB")); + assertThat(list.get(2).symbol, equalTo("ETH")); + } + + @Test + public void sort_tokens_by_name_alphabetically() + { + List list = new ArrayList<>(); + list.add(createToken("Ethereum", "ETH", "0x0", 0)); + list.add(createToken("Binance Smart Chain", "BNB", "0x1", 0)); + list.add(createToken("Solana", "SOL", "0x2", 0)); + + Tokens.sortName(list); + + assertThat(list.get(0).symbol, equalTo("BNB")); + assertThat(list.get(1).symbol, equalTo("ETH")); + assertThat(list.get(2).symbol, equalTo("SOL")); + } + + @Test + public void sort_name_should_return_native_token_first() + { + List list = new ArrayList<>(); + list.add(createToken("Solana", "SOL", "0x0", 0)); + list.add(createToken("Stox", "STX", "0x0000000000000000000000000000000000000000", 0)); + list.add(createToken("stETH", "stETH", "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 0)); + + Tokens.sortName(list); + + assertThat(list.get(0).symbol, equalTo("stETH")); + assertThat(list.get(1).symbol, equalTo("STX")); + assertThat(list.get(2).symbol, equalTo("SOL")); + } + + @Test + public void sort_name_should_be_case_insensitive() + { + List list = new ArrayList<>(); + list.add(createToken("Stox", "STX", "0x0", 0)); + list.add(createToken("stETH", "stETH", "0x3", 0)); + + Tokens.sortName(list); + + assertThat(list.get(0).symbol, equalTo("stETH")); + assertThat(list.get(1).symbol, equalTo("STX")); + } + + private Connection.LToken createToken(String name, String symbol, String address, double fiatEquivalent) + { + Connection.LToken lToken = new Connection.LToken(); + lToken.name = name; + lToken.symbol = symbol; + lToken.address = address; + lToken.fiatEquivalent = fiatEquivalent; + return lToken; + } +} \ No newline at end of file From abb42db294221dac28c74d4050b08fc4f8514520 Mon Sep 17 00:00:00 2001 From: justindg Date: Mon, 18 Jul 2022 14:24:30 -0700 Subject: [PATCH 010/183] Display swap provider in confirmation dialog --- .../alphawallet/app/entity/lifi/Quote.java | 19 +++++++++++++++++++ .../com/alphawallet/app/ui/SwapActivity.java | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java index 7d7dd6bbc5..29db3960b5 100644 --- a/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java @@ -20,6 +20,25 @@ public class Quote @Expose public String tool; + @SerializedName("toolDetails") + @Expose + public ToolDetails toolDetails; + + public static class ToolDetails + { + @SerializedName("key") + @Expose + public String key; + + @SerializedName("name") + @Expose + public String name; + + @SerializedName("logoURI") + @Expose + public String logoURI; + } + @SerializedName("action") @Expose public Action action; diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index 49bfa7c6fb..33c82ea818 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -233,7 +233,7 @@ private ActionSheetDialog createConfirmationAction(Quote quote) Web3Transaction w3Tx = viewModel.buildWeb3Transaction(quote); confDialog = new ActionSheetDialog(this, w3Tx, activeToken, "", w3Tx.recipient.toString(), viewModel.getTokensService(), this); - confDialog.setURL("LI.FI Best Quote"); //TODO: Expand swap provider here + confDialog.setURL(quote.toolDetails.name); confDialog.setCanceledOnTouchOutside(false); confDialog.setGasEstimate(Numeric.toBigInt(quote.transactionRequest.gasLimit)); } From d72f4495e02cf4acb626de41d5c99a8160f94ddc Mon Sep 17 00:00:00 2001 From: justindg Date: Mon, 18 Jul 2022 14:37:07 -0700 Subject: [PATCH 011/183] Show swap provider in the quote summary --- app/src/main/java/com/alphawallet/app/ui/SwapActivity.java | 4 ++++ app/src/main/res/layout/activity_swap.xml | 7 +++++++ app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-my/strings.xml | 1 + app/src/main/res/values-vi/strings.xml | 1 + app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 8 files changed, 17 insertions(+) diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index 33c82ea818..60b0d0008e 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -67,6 +67,7 @@ public class SwapActivity extends BaseActivity implements StandardFunctionInterf private RelativeLayout tokenLayout; private LinearLayout infoLayout; + private TokenInfoView provider; private TokenInfoView fees; private TokenInfoView currentPrice; private TokenInfoView minReceived; @@ -127,6 +128,7 @@ private void initViews() destSelector = findViewById(R.id.to_input); tokenLayout = findViewById(R.id.layout_tokens); infoLayout = findViewById(R.id.layout_info); + provider = findViewById(R.id.tiv_provider); fees = findViewById(R.id.tiv_fees); currentPrice = findViewById(R.id.tiv_current_price); minReceived = findViewById(R.id.tiv_min_received); @@ -461,6 +463,8 @@ private void updateInfoSummary(Quote quote) String ethCostStr = BalanceUtils.getScaledValueFixed(new BigDecimal(networkFee), 18, 4); + provider.setValue(quote.toolDetails.name); + fees.setValue(ethCostStr); //TODO: Needs to say 'Eth' after the quote, also should get the Eth price to show the Tx cost in user's Fiat //TODO: To see this done check GasWidget, see comment "Can we display value for gas?" diff --git a/app/src/main/res/layout/activity_swap.xml b/app/src/main/res/layout/activity_swap.xml index 440bc7acf9..8839eed0b0 100644 --- a/app/src/main/res/layout/activity_swap.xml +++ b/app/src/main/res/layout/activity_swap.xml @@ -120,6 +120,13 @@ android:orientation="vertical" android:visibility="gone"> + + This will inform the remote site your wallet address is %s Floor Price Average Price + Provider diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index aed3fecca2..83cafa1f65 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -946,4 +946,5 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Provider diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index accc52cd4f..31c446a908 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -971,4 +971,5 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Provider diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 62a40f251f..5cec7d52cb 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -948,4 +948,5 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Provider diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index b1e6d66468..b95915e2dd 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -929,4 +929,5 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Provider diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 37d9045474..7ce90e8de5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -970,4 +970,5 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Provider From 82d528310f8b5ec428b3b161da771e57c0200114 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 19 Jul 2022 06:13:18 +0800 Subject: [PATCH 012/183] Move getFiatValue and add unit test (#2731) --- .../app/entity/lifi/Connection.java | 14 +++++++ .../com/alphawallet/app/ui/SwapActivity.java | 4 +- .../app/viewmodel/SwapViewModel.java | 14 ------- .../app/entity/lifi/ConnectionTest.java | 40 +++++++++++++++++++ 4 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 app/src/test/java/com/alphawallet/app/entity/lifi/ConnectionTest.java diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java index ea4192cab5..9d5166d1b6 100644 --- a/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java @@ -82,5 +82,19 @@ public boolean isNativeToken() return address.equalsIgnoreCase("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") || address.equalsIgnoreCase("0x0000000000000000000000000000000000000000"); } + + public double getFiatValue() + { + try + { + double value = Double.parseDouble(balance); + double priceUSD = Double.parseDouble(this.priceUSD); + return value * priceUSD; + } + catch (NumberFormatException | NullPointerException e) + { + return 0.0; + } + } } } diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index 49bfa7c6fb..f9a088354d 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -382,7 +382,7 @@ private void onConnections(List connections) if (!fromTokens.contains(t)) { t.balance = viewModel.getBalance(t); - t.fiatEquivalent = viewModel.getFiatValue(t); + t.fiatEquivalent = t.getFiatValue(); if (t.fiatEquivalent > 0) { @@ -401,7 +401,7 @@ private void onConnections(List connections) if (!toTokens.contains(t)) { t.balance = viewModel.getBalance(t); - t.fiatEquivalent = viewModel.getFiatValue(t); + t.fiatEquivalent = t.getFiatValue(); toTokens.add(t); } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java index f77ba4ae2b..4bd199d6e0 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java @@ -284,20 +284,6 @@ public String getBalance(Connection.LToken token) else return "0"; } - public double getFiatValue(Connection.LToken t) - { - try - { - double value = Double.parseDouble(t.balance); - double priceUSD = Double.parseDouble(t.priceUSD); - return value * priceUSD; - } - catch (NumberFormatException|NullPointerException e) - { - return 0.0; - } - } - public void getAuthentication(Activity activity, Wallet wallet, SignAuthenticationCallback callback) { keyService.getAuthenticationForSignature(wallet, activity, callback); diff --git a/app/src/test/java/com/alphawallet/app/entity/lifi/ConnectionTest.java b/app/src/test/java/com/alphawallet/app/entity/lifi/ConnectionTest.java new file mode 100644 index 0000000000..81ccb252ca --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/entity/lifi/ConnectionTest.java @@ -0,0 +1,40 @@ +package com.alphawallet.app.entity.lifi; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import org.junit.Test; + +public class ConnectionTest +{ + @Test + public void getFiatValue() + { + Connection.LToken lToken = new Connection.LToken(); + lToken.priceUSD = "6.72"; + lToken.balance = "1"; + + assertThat(lToken.getFiatValue(), equalTo(6.72)); + } + + @Test + public void getFiatValue_should_handle_exception() + { + Connection.LToken lToken = new Connection.LToken(); + lToken.priceUSD = "6.72"; + lToken.balance = ""; + assertThat(lToken.getFiatValue(), equalTo(0.0)); + + lToken.priceUSD = ""; + lToken.balance = "1"; + assertThat(lToken.getFiatValue(), equalTo(0.0)); + + lToken.priceUSD = null; + lToken.balance = "1"; + assertThat(lToken.getFiatValue(), equalTo(0.0)); + + lToken.priceUSD = "6.72"; + lToken.balance = null; + assertThat(lToken.getFiatValue(), equalTo(0.0)); + } +} \ No newline at end of file From c5ffe3d9a3e0dc94753a4b955f65b5d1a6fe9db8 Mon Sep 17 00:00:00 2001 From: justindg Date: Mon, 18 Jul 2022 19:18:09 -0700 Subject: [PATCH 013/183] Display gas fee symbol --- .../alphawallet/app/entity/lifi/Quote.java | 37 ++++++++++++++++--- .../com/alphawallet/app/ui/SwapActivity.java | 20 +++++----- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java index 29db3960b5..8fdcd90faf 100644 --- a/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java @@ -3,8 +3,7 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; -import org.json.JSONArray; -import org.json.JSONObject; +import java.util.ArrayList; public class Quote { @@ -107,10 +106,36 @@ public static class Estimate // @SerializedName("feeCosts") // @Expose // public JSONArray feeCosts; -// -// @SerializedName("gasCosts") -// @Expose -// public JSONArray gasCosts; + + @SerializedName("gasCosts") + @Expose + public ArrayList gasCosts; + + public static class GasCost + { + @SerializedName("amount") + @Expose + public String amount; + + @SerializedName("amountUSD") + @Expose + public String amountUSD; + + @SerializedName("token") + @Expose + public Token token; + + public static class Token + { + @SerializedName("symbol") + @Expose + public String symbol; + + @SerializedName("decimals") + @Expose + public long decimals; + } + } @SerializedName("data") @Expose diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index 60b0d0008e..7aad302d49 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -41,7 +41,6 @@ import com.google.android.material.button.MaterialButton; import java.math.BigDecimal; -import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -455,18 +454,17 @@ private void updateDestAmount(Quote quote) private void updateInfoSummary(Quote quote) { - //convert gasQuote to Eth cost - BigInteger gasCost = Numeric.toBigInt(quote.transactionRequest.gasPrice); - BigInteger gasLimit = Numeric.toBigInt(quote.transactionRequest.gasLimit); - - BigInteger networkFee = gasCost.multiply(gasLimit); - - String ethCostStr = BalanceUtils.getScaledValueFixed(new BigDecimal(networkFee), 18, 4); - provider.setValue(quote.toolDetails.name); - fees.setValue(ethCostStr); //TODO: Needs to say 'Eth' after the quote, also should get the Eth price to show the Tx cost in user's Fiat - //TODO: To see this done check GasWidget, see comment "Can we display value for gas?" + StringBuilder total = new StringBuilder(); + for (Quote.Estimate.GasCost gc : quote.estimate.gasCosts) + { + BigDecimal amount = new BigDecimal(gc.amount); + long decimals = gc.token.decimals; + String fee = BalanceUtils.getScaledValueFixed(amount, decimals, 4); + total.append(fee).append(" ").append(gc.token.symbol).append("\n"); + } + fees.setValue(total.toString().trim()); BigDecimal s = new BigDecimal(quote.action.fromToken.priceUSD); BigDecimal d = new BigDecimal(quote.action.toToken.priceUSD); From 4be4c9bb4966d4e54a3b3ea7b0fb2d9d1a40f20c Mon Sep 17 00:00:00 2001 From: justindg Date: Mon, 18 Jul 2022 19:29:38 -0700 Subject: [PATCH 014/183] Wrap layout in scrollview --- app/src/main/res/layout/activity_swap.xml | 273 +++++++++++----------- 1 file changed, 142 insertions(+), 131 deletions(-) diff --git a/app/src/main/res/layout/activity_swap.xml b/app/src/main/res/layout/activity_swap.xml index 8839eed0b0..031fbbbc66 100644 --- a/app/src/main/res/layout/activity_swap.xml +++ b/app/src/main/res/layout/activity_swap.xml @@ -13,142 +13,152 @@ style="@style/Aw.Component.Separator" android:layout_below="@id/toolbar" /> - - - - - - - + android:layout_above="@id/btn_continue" + android:layout_below="@id/separator"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fec0bf25e9e1705c93f60cfb7a2eaf6558c9af23 Mon Sep 17 00:00:00 2001 From: justindg Date: Mon, 18 Jul 2022 19:50:07 -0700 Subject: [PATCH 015/183] Clear amount when switching source token --- app/src/main/java/com/alphawallet/app/ui/SwapActivity.java | 4 ++++ .../main/java/com/alphawallet/app/widget/TokenSelector.java | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index 7aad302d49..f5373ea06e 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -264,6 +264,10 @@ private void sourceTokenChanged(Connection.LToken token) destSelector.setVisibility(View.VISIBLE); } + sourceSelector.clearAmount(); + + destSelector.clearAmount(); + sourceSelector.setBalance(viewModel.getBalance(token)); infoLayout.setVisibility(View.GONE); diff --git a/app/src/main/java/com/alphawallet/app/widget/TokenSelector.java b/app/src/main/java/com/alphawallet/app/widget/TokenSelector.java index cf22edfb4b..02768154fe 100644 --- a/app/src/main/java/com/alphawallet/app/widget/TokenSelector.java +++ b/app/src/main/java/com/alphawallet/app/widget/TokenSelector.java @@ -202,6 +202,11 @@ public String getAmount() return editText.getText().toString(); } + public void clearAmount() + { + editText.getText().clear(); + } + public void setAmount(String amount) { editText.setText(amount); From 2f1041c2e2e6f070d52e7584ac6df137d373e958 Mon Sep 17 00:00:00 2001 From: justindg Date: Tue, 19 Jul 2022 17:20:40 -0700 Subject: [PATCH 016/183] Fetch quotes every 30s + Improve error display --- app/src/main/java/com/alphawallet/app/C.java | 5 +- .../com/alphawallet/app/ui/SwapActivity.java | 81 ++++++++++++++----- .../app/viewmodel/SwapViewModel.java | 68 +++++++++++++--- 3 files changed, 124 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 13ce6f931a..30dc4a3d93 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -245,7 +245,10 @@ public interface ErrorCode { // Swap Error Codes int INSUFFICIENT_BALANCE = 5; - int SWAP_API_ERROR = 6; + int SWAP_CHAIN_ERROR = 6; + int SWAP_CONNECTIONS_ERROR = 7; + int SWAP_QUOTE_ERROR = 8; + int SWAP_TIMEOUT_ERROR = 9; } public interface Key { diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index f5373ea06e..dd41f6f0b5 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -2,6 +2,7 @@ import android.content.Intent; import android.os.Bundle; +import android.os.Handler; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; @@ -49,21 +50,16 @@ @AndroidEntryPoint public class SwapActivity extends BaseActivity implements StandardFunctionInterface, ActionSheetCallback { - SwapViewModel viewModel; - - private TextView chainName; - + private static final int GET_QUOTE_INTERVAL_MS = 30000; + private SwapViewModel viewModel; private TokenSelector sourceSelector; private TokenSelector destSelector; - private SelectTokenDialog sourceTokenDialog; private SelectTokenDialog destTokenDialog; - - //private ConfirmSwapDialog confirmSwapDialog; private ActionSheetDialog confirmationDialog; private SwapSettingsDialog settingsDialog; private AWalletAlertDialog progressDialog; - + private AWalletAlertDialog errorDialog; private RelativeLayout tokenLayout; private LinearLayout infoLayout; private TokenInfoView provider; @@ -73,12 +69,25 @@ public class SwapActivity extends BaseActivity implements StandardFunctionInterf private LinearLayout noConnectionsLayout; private MaterialButton continueBtn; private MaterialButton openSettingsBtn; - + private TextView chainName; private Token token; private Wallet wallet; private Connection.LToken sourceToken; - private List chains; + private final Handler getQuoteHandler = new Handler(); + private final Runnable getQuoteRunnable = new Runnable() + { + @Override + public void run() + { + viewModel.getQuote( + sourceSelector.getToken(), + destSelector.getToken(), + wallet.address, + sourceSelector.getAmount(), + settingsDialog.getSlippage()); + } + }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) @@ -89,13 +98,15 @@ protected void onCreate(@Nullable Bundle savedInstanceState) toolbar(); - setTitle("Swap"); + setTitle(getString(R.string.swap)); initViewModel(); getIntentData(); initViews(); + + viewModel.getChains(); } private void initViewModel() @@ -168,7 +179,7 @@ public void onSelectorClicked() @Override public void onAmountChanged(String amount) { - getQuote(); + startQuoteTask(); } @Override @@ -254,7 +265,7 @@ private void destTokenChanged(Connection.LToken token) destTokenDialog.setSelectedToken(token.address); - getQuote(); + startQuoteTask(); } private void sourceTokenChanged(Connection.LToken token) @@ -276,14 +287,13 @@ private void sourceTokenChanged(Connection.LToken token) sourceToken = token; - getQuote(); + startQuoteTask(); } @Override protected void onResume() { super.onResume(); - viewModel.getChains(); } // The source token should default to the token selected in the main wallet dialog (ie the token from the intent). @@ -320,18 +330,25 @@ private void initToDialog(List toTokens) }); } - private void getQuote() + private void startQuoteTask() { + stopQuoteTask(); + continueBtn.setEnabled(false); if (sourceSelector.getToken() != null && destSelector.getToken() != null && !TextUtils.isEmpty(sourceSelector.getAmount())) { - viewModel.getQuote(sourceSelector.getToken(), destSelector.getToken(), wallet.address, sourceSelector.getAmount(), settingsDialog.getSlippage()); + getQuoteHandler.post(getQuoteRunnable); } } + private void stopQuoteTask() + { + getQuoteHandler.removeCallbacks(getQuoteRunnable); + } + private void onChains(List chains) { this.chains = chains; @@ -442,6 +459,8 @@ private void onQuote(Quote quote) } continueBtn.setEnabled(true); + + getQuoteHandler.postDelayed(getQuoteRunnable, GET_QUOTE_INTERVAL_MS); } private void updateDestAmount(Quote quote) @@ -538,8 +557,34 @@ private void onError(ErrorEnvelope errorEnvelope) case C.ErrorCode.INSUFFICIENT_BALANCE: sourceSelector.setError(getString(R.string.error_insufficient_balance, sourceSelector.getToken().symbol)); break; + case C.ErrorCode.SWAP_TIMEOUT_ERROR: + startQuoteTask(); + break; + case C.ErrorCode.SWAP_CONNECTIONS_ERROR: + case C.ErrorCode.SWAP_CHAIN_ERROR: + errorDialog = new AWalletAlertDialog(this); + errorDialog.setTitle(R.string.title_dialog_error); + errorDialog.setMessage(errorEnvelope.message); + errorDialog.setButton(R.string.try_again, v -> { + viewModel.getChains(); + errorDialog.dismiss(); + }); + errorDialog.setSecondaryButton(R.string.action_cancel, v -> errorDialog.dismiss()); + errorDialog.show(); + break; + case C.ErrorCode.SWAP_QUOTE_ERROR: + errorDialog = new AWalletAlertDialog(this); + errorDialog.setTitle(R.string.title_dialog_error); + errorDialog.setMessage(errorEnvelope.message); + errorDialog.setButton(R.string.try_again, v -> { + startQuoteTask(); + errorDialog.dismiss(); + }); + errorDialog.setSecondaryButton(R.string.action_cancel, v -> errorDialog.dismiss()); + errorDialog.show(); + break; default: - AWalletAlertDialog errorDialog = new AWalletAlertDialog(this); + errorDialog = new AWalletAlertDialog(this); errorDialog.setTitle(R.string.title_dialog_error); errorDialog.setMessage(errorEnvelope.message); errorDialog.setButton(R.string.action_cancel, v -> errorDialog.dismiss()); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java index f77ba4ae2b..1e73fca1e0 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java @@ -33,6 +33,8 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.List; +import java.util.Locale; +import java.util.Objects; import javax.inject.Inject; @@ -40,6 +42,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; +import timber.log.Timber; @HiltViewModel public class SwapViewModel extends BaseViewModel @@ -147,7 +150,7 @@ public void getChains() chainsDisposable = swapService.getChains() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onChains, this::onError); + .subscribe(this::onChains, this::onChainsError); } public void getConnections(long from, long to) @@ -158,7 +161,7 @@ public void getConnections(long from, long to) connectionsDisposable = swapService.getConnections(from, to) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onConnections, this::onError); + .subscribe(this::onConnections, this::onConnectionsError); } public void getQuote(Connection.LToken source, Connection.LToken dest, String address, String amount, String slippage) @@ -171,7 +174,7 @@ public void getQuote(Connection.LToken source, Connection.LToken dest, String ad quoteDisposable = swapService.getQuote(source, dest, address, amount, slippage) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onQuote, this::onError); + .subscribe(this::onQuote, this::onQuoteError); } else { @@ -179,6 +182,21 @@ public void getQuote(Connection.LToken source, Connection.LToken dest, String ad } } + private void onChainsError(Throwable t) + { + postError(C.ErrorCode.SWAP_CHAIN_ERROR, Objects.requireNonNull(t.getMessage())); + } + + private void onConnectionsError(Throwable t) + { + postError(C.ErrorCode.SWAP_CONNECTIONS_ERROR, Objects.requireNonNull(t.getMessage())); + } + + private void onQuoteError(Throwable t) + { + postError(C.ErrorCode.SWAP_QUOTE_ERROR, Objects.requireNonNull(t.getMessage())); + } + public boolean hasEnoughBalance(Connection.LToken source, String amount) { BigDecimal bal = new BigDecimal(getBalance(source)); @@ -203,12 +221,12 @@ private void onChains(String result) } else { - error.postValue(new ErrorEnvelope(C.ErrorCode.SWAP_API_ERROR, result)); + postError(C.ErrorCode.SWAP_CHAIN_ERROR, result); } } catch (JSONException e) { - error.postValue(new ErrorEnvelope(C.ErrorCode.SWAP_API_ERROR, e.getMessage())); + postError(C.ErrorCode.SWAP_CHAIN_ERROR, Objects.requireNonNull(e.getMessage())); } } @@ -229,12 +247,12 @@ private void onConnections(String result) } else { - error.postValue(new ErrorEnvelope(C.ErrorCode.SWAP_API_ERROR, result)); + postError(C.ErrorCode.SWAP_CONNECTIONS_ERROR, result); } } catch (JSONException e) { - error.postValue(new ErrorEnvelope(C.ErrorCode.SWAP_API_ERROR, e.getMessage())); + postError(C.ErrorCode.SWAP_CONNECTIONS_ERROR, Objects.requireNonNull(e.getMessage())); } progress.postValue(false); @@ -244,7 +262,7 @@ private void onQuote(String result) { if (!isValidQuote(result)) { - error.postValue(new ErrorEnvelope(C.ErrorCode.SWAP_API_ERROR, result)); + postError(C.ErrorCode.SWAP_QUOTE_ERROR, result); } else { @@ -255,6 +273,37 @@ private void onQuote(String result) progress.postValue(false); } + private void postError(int errorCode, String errorStr) + { + Timber.e(errorStr); + if (errorStr.toLowerCase(Locale.ENGLISH).contains("timeout")) + { + this.error.postValue(new ErrorEnvelope(C.ErrorCode.SWAP_TIMEOUT_ERROR, errorStr)); + } + else + { + this.error.postValue(new ErrorEnvelope(errorCode, checkMessage(errorStr))); + } + } + + private String checkMessage(String errorStr) + { + String message = errorStr; + try + { + JSONObject json = new JSONObject(errorStr); + if (json.has("message")) + { + message = json.getString("message"); + } + } + catch (JSONException e) + { + Timber.e(e); + } + return message; + } + private boolean isValidQuote(String result) { return result.contains("id") @@ -265,9 +314,6 @@ private boolean isValidQuote(String result) public String getBalance(Connection.LToken token) { Token t; - - // Note: In the LIFI API, the native token has either of these two addresses. - // In AlphaWallet, the wallet address is used. if (token.isNativeToken()) { t = tokensService.getServiceToken(token.chainId); From b8e169821cd3ae37b43016e653cfb866fd4dc86e Mon Sep 17 00:00:00 2001 From: justindg Date: Wed, 20 Jul 2022 16:29:06 -0700 Subject: [PATCH 017/183] Prevent fetching new quote when confirmation dialog is showing --- .../com/alphawallet/app/ui/SwapActivity.java | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index dd41f6f0b5..dc773295f4 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -50,7 +50,7 @@ @AndroidEntryPoint public class SwapActivity extends BaseActivity implements StandardFunctionInterface, ActionSheetCallback { - private static final int GET_QUOTE_INTERVAL_MS = 30000; + private static final long GET_QUOTE_INTERVAL_MS = 30000; private SwapViewModel viewModel; private TokenSelector sourceSelector; private TokenSelector destSelector; @@ -80,12 +80,19 @@ public class SwapActivity extends BaseActivity implements StandardFunctionInterf @Override public void run() { - viewModel.getQuote( - sourceSelector.getToken(), - destSelector.getToken(), - wallet.address, - sourceSelector.getAmount(), - settingsDialog.getSlippage()); + if (confirmationDialog == null || !confirmationDialog.isShowing()) + { + viewModel.getQuote( + sourceSelector.getToken(), + destSelector.getToken(), + wallet.address, + sourceSelector.getAmount(), + settingsDialog.getSlippage()); + } + else + { + startQuoteTask(GET_QUOTE_INTERVAL_MS); + } } }; @@ -179,7 +186,7 @@ public void onSelectorClicked() @Override public void onAmountChanged(String amount) { - startQuoteTask(); + startQuoteTask(0); } @Override @@ -265,7 +272,7 @@ private void destTokenChanged(Connection.LToken token) destTokenDialog.setSelectedToken(token.address); - startQuoteTask(); + startQuoteTask(0); } private void sourceTokenChanged(Connection.LToken token) @@ -287,7 +294,7 @@ private void sourceTokenChanged(Connection.LToken token) sourceToken = token; - startQuoteTask(); + startQuoteTask(0); } @Override @@ -330,7 +337,7 @@ private void initToDialog(List toTokens) }); } - private void startQuoteTask() + private void startQuoteTask(long delay) { stopQuoteTask(); @@ -340,7 +347,7 @@ private void startQuoteTask() && destSelector.getToken() != null && !TextUtils.isEmpty(sourceSelector.getAmount())) { - getQuoteHandler.post(getQuoteRunnable); + getQuoteHandler.postDelayed(getQuoteRunnable, delay); } } @@ -558,7 +565,7 @@ private void onError(ErrorEnvelope errorEnvelope) sourceSelector.setError(getString(R.string.error_insufficient_balance, sourceSelector.getToken().symbol)); break; case C.ErrorCode.SWAP_TIMEOUT_ERROR: - startQuoteTask(); + startQuoteTask(0); break; case C.ErrorCode.SWAP_CONNECTIONS_ERROR: case C.ErrorCode.SWAP_CHAIN_ERROR: @@ -577,7 +584,7 @@ private void onError(ErrorEnvelope errorEnvelope) errorDialog.setTitle(R.string.title_dialog_error); errorDialog.setMessage(errorEnvelope.message); errorDialog.setButton(R.string.try_again, v -> { - startQuoteTask(); + startQuoteTask(0); errorDialog.dismiss(); }); errorDialog.setSecondaryButton(R.string.action_cancel, v -> errorDialog.dismiss()); From 26becfa8da1ff4846792b6a392564b3b9d4aa08e Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 21 Jul 2022 19:03:18 -0700 Subject: [PATCH 018/183] Refactor and add unit tests --- .../com/alphawallet/app/ui/SwapActivity.java | 25 +---- .../com/alphawallet/app/util/SwapUtils.java | 51 +++++++++++ .../alphawallet/app/util/SwapUtilsTest.java | 91 +++++++++++++++++++ 3 files changed, 146 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/util/SwapUtils.java create mode 100644 app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index c04a554c9b..f066cee50b 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -28,6 +28,7 @@ import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.util.BalanceUtils; +import com.alphawallet.app.util.SwapUtils; import com.alphawallet.app.viewmodel.SwapViewModel; import com.alphawallet.app.viewmodel.Tokens; import com.alphawallet.app.web3.entity.Web3Transaction; @@ -41,7 +42,6 @@ import com.alphawallet.token.tools.Numeric; import com.google.android.material.button.MaterialButton; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -485,26 +485,9 @@ private void updateDestAmount(Quote quote) private void updateInfoSummary(Quote quote) { provider.setValue(quote.toolDetails.name); - - StringBuilder total = new StringBuilder(); - for (Quote.Estimate.GasCost gc : quote.estimate.gasCosts) - { - BigDecimal amount = new BigDecimal(gc.amount); - long decimals = gc.token.decimals; - String fee = BalanceUtils.getScaledValueFixed(amount, decimals, 4); - total.append(fee).append(" ").append(gc.token.symbol).append("\n"); - } - fees.setValue(total.toString().trim()); - - BigDecimal s = new BigDecimal(quote.action.fromToken.priceUSD); - BigDecimal d = new BigDecimal(quote.action.toToken.priceUSD); - BigDecimal c = s.multiply(d); - String currentPriceTxt = "1 " + quote.action.fromToken.symbol + " ≈ " + c.toString() + " " + quote.action.toToken.symbol; - currentPrice.setValue(currentPriceTxt.trim()); - - String minReceivedVal = BalanceUtils.getShortFormat(quote.estimate.toAmountMin, quote.action.toToken.decimals) + " " + quote.action.toToken.symbol; - minReceived.setValue(minReceivedVal.trim()); - + fees.setValue(SwapUtils.getTotalGasFees(quote.estimate.gasCosts)); + currentPrice.setValue(SwapUtils.getFormattedCurrentPrice(quote).trim()); + minReceived.setValue(SwapUtils.getMinimumAmountReceived(quote)); infoLayout.setVisibility(View.VISIBLE); } diff --git a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java new file mode 100644 index 0000000000..4680661e01 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java @@ -0,0 +1,51 @@ +package com.alphawallet.app.util; + +import com.alphawallet.app.entity.lifi.Quote; + +import java.math.BigDecimal; +import java.util.ArrayList; + +public class SwapUtils +{ + public static final String GAS_PRICE_FORMAT = "%s %s"; + public static final String MINIMUM_RECEIVED_FORMAT = "%s %s"; + public static final String CURRENT_PRICE_FORMAT = "1 %s ≈ %s %s"; + + public static String getTotalGasFees(ArrayList gasCosts) + { + StringBuilder gas = new StringBuilder(); + for (Quote.Estimate.GasCost gc : gasCosts) + { + gas.append(SwapUtils.getGasFee(gc)).append(System.lineSeparator()); + } + return gas.toString().trim(); + } + + public static String getGasFee(Quote.Estimate.GasCost gasCost) + { + return String.format(GAS_PRICE_FORMAT, + BalanceUtils.getScaledValueFixed(new BigDecimal(gasCost.amount), gasCost.token.decimals, 4), + gasCost.token.symbol); + } + + public static String getFormattedCurrentPrice(Quote quote) + { + return String.format(CURRENT_PRICE_FORMAT, + quote.action.fromToken.symbol, + getCurrentPrice(quote), + quote.action.toToken.symbol); + } + + public static String getCurrentPrice(Quote quote) + { + return new BigDecimal(quote.action.fromToken.priceUSD) + .multiply(new BigDecimal(quote.action.toToken.priceUSD)).toString(); + } + + public static String getMinimumAmountReceived(Quote quote) + { + return String.format(MINIMUM_RECEIVED_FORMAT, + BalanceUtils.getShortFormat(quote.estimate.toAmountMin, quote.action.toToken.decimals), + quote.action.toToken.symbol); + } +} diff --git a/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java b/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java new file mode 100644 index 0000000000..57636748cc --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java @@ -0,0 +1,91 @@ +package com.alphawallet.app.util; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Quote; + +import org.junit.Test; + +import java.util.ArrayList; + +public class SwapUtilsTest +{ + @Test + public void should_return_formatted_total_gas_fees() + { + ArrayList gasCostList = new ArrayList<>(); + Quote.Estimate.GasCost gasCost1 = new Quote.Estimate.GasCost(); + gasCost1.amount = "1000000000000000000"; + gasCost1.token = new Quote.Estimate.GasCost.Token(); + gasCost1.token.symbol = "ETH"; + gasCost1.token.decimals = 18; + + Quote.Estimate.GasCost gasCost2 = new Quote.Estimate.GasCost(); + gasCost2.amount = "2000000000000000000"; + gasCost2.token = new Quote.Estimate.GasCost.Token(); + gasCost2.token.symbol = "MATIC"; + gasCost2.token.decimals = 18; + + gasCostList.add(gasCost1); + gasCostList.add(gasCost2); + + assertThat(SwapUtils.getTotalGasFees(gasCostList), equalTo("1.0000 ETH" + System.lineSeparator() + "2.0000 MATIC")); + } + + @Test + public void should_return_formatted_gas_fee() + { + Quote.Estimate.GasCost gasCost = new Quote.Estimate.GasCost(); + gasCost.amount = "1000000000000000000"; + gasCost.token = new Quote.Estimate.GasCost.Token(); + gasCost.token.symbol = "ETH"; + gasCost.token.decimals = 18; + + assertThat(SwapUtils.getGasFee(gasCost), equalTo("1.0000 ETH")); + } + + @Test + public void should_return_current_price() + { + Quote quote = new Quote(); + quote.action = new Quote.Action(); + quote.action.fromToken = new Connection.LToken(); + quote.action.toToken = new Connection.LToken(); + quote.action.fromToken.priceUSD = "5"; + quote.action.toToken.priceUSD = "1000"; + + assertThat(SwapUtils.getCurrentPrice(quote), equalTo("5000")); + } + + @Test + public void should_return_formatted_minimum_received() + { + Quote quote = new Quote(); + quote.action = new Quote.Action(); + quote.action.toToken = new Connection.LToken(); + quote.estimate = new Quote.Estimate(); + quote.estimate.toAmountMin = "1000000"; + quote.action.toToken.decimals = 6; + quote.action.toToken.symbol = "ETH"; + + assertThat(SwapUtils.getMinimumAmountReceived(quote), equalTo("1.000000 ETH")); + } + + @Test + public void should_return_formatted_current_price() + { + Quote quote = new Quote(); + quote.action = new Quote.Action(); + quote.action.fromToken = new Connection.LToken(); + quote.action.toToken = new Connection.LToken(); + quote.action.fromToken.priceUSD = "5"; + quote.action.fromToken.symbol = "ETH"; + quote.action.toToken.priceUSD = "1000"; + quote.action.toToken.symbol = "USDC"; + + String expected = "1 ETH ≈ 5000 USDC"; + assertThat(SwapUtils.getFormattedCurrentPrice(quote), equalTo(expected)); + } +} \ No newline at end of file From 55d4c7b7eb8bc1ee82201c6c9583b7fee3c07433 Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 21 Jul 2022 20:25:10 -0700 Subject: [PATCH 019/183] Convert to private constants --- app/src/main/java/com/alphawallet/app/util/SwapUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java index 4680661e01..b7ccb2d77d 100644 --- a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java +++ b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java @@ -7,9 +7,9 @@ public class SwapUtils { - public static final String GAS_PRICE_FORMAT = "%s %s"; - public static final String MINIMUM_RECEIVED_FORMAT = "%s %s"; - public static final String CURRENT_PRICE_FORMAT = "1 %s ≈ %s %s"; + private static final String GAS_PRICE_FORMAT = "%s %s"; + private static final String MINIMUM_RECEIVED_FORMAT = "%s %s"; + private static final String CURRENT_PRICE_FORMAT = "1 %s ≈ %s %s"; public static String getTotalGasFees(ArrayList gasCosts) { From 2ef04371065fc2a33228b7575bb24147833fb738 Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 21 Jul 2022 20:25:30 -0700 Subject: [PATCH 020/183] Remove instance of variable message --- .../java/com/alphawallet/app/viewmodel/SwapViewModel.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java index 9b3cf2e289..0328a3565f 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java @@ -288,20 +288,19 @@ private void postError(int errorCode, String errorStr) private String checkMessage(String errorStr) { - String message = errorStr; try { JSONObject json = new JSONObject(errorStr); if (json.has("message")) { - message = json.getString("message"); + return json.getString("message"); } } catch (JSONException e) { Timber.e(e); } - return message; + return errorStr; } private boolean isValidQuote(String result) From 5e2b5565da3893c9835cba5f62410600f527a144 Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 21 Jul 2022 20:28:13 -0700 Subject: [PATCH 021/183] Refactor if block --- .../java/com/alphawallet/app/viewmodel/SwapViewModel.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java index 0328a3565f..2bcfcd2812 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java @@ -279,11 +279,9 @@ private void postError(int errorCode, String errorStr) if (errorStr.toLowerCase(Locale.ENGLISH).contains("timeout")) { this.error.postValue(new ErrorEnvelope(C.ErrorCode.SWAP_TIMEOUT_ERROR, errorStr)); + return; } - else - { - this.error.postValue(new ErrorEnvelope(errorCode, checkMessage(errorStr))); - } + this.error.postValue(new ErrorEnvelope(errorCode, checkMessage(errorStr))); } private String checkMessage(String errorStr) From ea47ebfa10f51ccce22b1b8f16ed439adc8e369c Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 21 Jul 2022 20:33:48 -0700 Subject: [PATCH 022/183] Move getCurrentPrice() method to Quote class --- .../alphawallet/app/entity/lifi/Quote.java | 7 ++++++ .../com/alphawallet/app/util/SwapUtils.java | 8 +------ .../app/entity/lifi/QuoteTest.java | 22 +++++++++++++++++++ .../alphawallet/app/util/SwapUtilsTest.java | 13 ----------- 4 files changed, 30 insertions(+), 20 deletions(-) create mode 100644 app/src/test/java/com/alphawallet/app/entity/lifi/QuoteTest.java diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java index 8fdcd90faf..2e0d1cf6d2 100644 --- a/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java @@ -3,6 +3,7 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +import java.math.BigDecimal; import java.util.ArrayList; public class Quote @@ -235,4 +236,10 @@ public static class TransactionRequest @Expose public String gasPrice; } + + public String getCurrentPrice() + { + return new BigDecimal(action.fromToken.priceUSD) + .multiply(new BigDecimal(action.toToken.priceUSD)).toString(); + } } diff --git a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java index b7ccb2d77d..baee0d76b4 100644 --- a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java +++ b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java @@ -32,16 +32,10 @@ public static String getFormattedCurrentPrice(Quote quote) { return String.format(CURRENT_PRICE_FORMAT, quote.action.fromToken.symbol, - getCurrentPrice(quote), + quote.getCurrentPrice(), quote.action.toToken.symbol); } - public static String getCurrentPrice(Quote quote) - { - return new BigDecimal(quote.action.fromToken.priceUSD) - .multiply(new BigDecimal(quote.action.toToken.priceUSD)).toString(); - } - public static String getMinimumAmountReceived(Quote quote) { return String.format(MINIMUM_RECEIVED_FORMAT, diff --git a/app/src/test/java/com/alphawallet/app/entity/lifi/QuoteTest.java b/app/src/test/java/com/alphawallet/app/entity/lifi/QuoteTest.java new file mode 100644 index 0000000000..be6cadd866 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/entity/lifi/QuoteTest.java @@ -0,0 +1,22 @@ +package com.alphawallet.app.entity.lifi; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import org.junit.Test; + +public class QuoteTest +{ + @Test + public void should_return_current_price() + { + Quote quote = new Quote(); + quote.action = new Quote.Action(); + quote.action.fromToken = new Connection.LToken(); + quote.action.toToken = new Connection.LToken(); + quote.action.fromToken.priceUSD = "5"; + quote.action.toToken.priceUSD = "1000"; + + assertThat(quote.getCurrentPrice(), equalTo("5000")); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java b/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java index 57636748cc..470a1f4c66 100644 --- a/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java +++ b/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java @@ -46,19 +46,6 @@ public void should_return_formatted_gas_fee() assertThat(SwapUtils.getGasFee(gasCost), equalTo("1.0000 ETH")); } - @Test - public void should_return_current_price() - { - Quote quote = new Quote(); - quote.action = new Quote.Action(); - quote.action.fromToken = new Connection.LToken(); - quote.action.toToken = new Connection.LToken(); - quote.action.fromToken.priceUSD = "5"; - quote.action.toToken.priceUSD = "1000"; - - assertThat(SwapUtils.getCurrentPrice(quote), equalTo("5000")); - } - @Test public void should_return_formatted_minimum_received() { From b20848432a54d528cee2b5e5b8050b07f9622028 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Sat, 23 Jul 2022 02:04:58 +0800 Subject: [PATCH 023/183] Fix NPE (#2742) --- .../alphawallet/app/widget/SignTransactionDialog.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java b/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java index f984d99b33..fdbb452dbc 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java @@ -174,8 +174,13 @@ private void showAuthenticationScreen(Activity activity, AuthenticationCallback else if (km != null) { Intent intent = km.createConfirmDeviceCredentialIntent(activity.getString(R.string.unlock_private_key), ""); - intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - activity.startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + callBackId.ordinal()); + if (intent == null) + { + authCallback.authenticateFail("Can not unlock", AuthenticationFailType.BIOMETRIC_AUTHENTICATION_NOT_AVAILABLE, callBackId); + } else { + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + activity.startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + callBackId.ordinal()); + } } else { From 1642cf894e6a0ce33700424581f92f25f9ba5dd5 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Sat, 23 Jul 2022 02:05:25 +0800 Subject: [PATCH 024/183] Catch exception (#2739) --- .../java/com/alphawallet/app/ui/WalletFragment.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java index 2fff854596..ba7b772e39 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java @@ -82,6 +82,7 @@ import io.reactivex.schedulers.Schedulers; import io.realm.Realm; import io.realm.RealmResults; +import timber.log.Timber; /** * Created by justindeguzman on 2/28/18. @@ -621,7 +622,14 @@ public void onDestroy() handler.removeCallbacksAndMessages(null); if (realmUpdates != null) { - realmUpdates.removeAllChangeListeners(); + try + { + realmUpdates.removeAllChangeListeners(); + } + catch (Exception e) + { + Timber.e(e); + } } if (realm != null && !realm.isClosed()) realm.close(); if (adapter != null && recyclerView != null) adapter.onDestroy(recyclerView); From f7758aa67047acbae80329a4636d0d6e724b4d4c Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Sat, 23 Jul 2022 02:07:53 +0800 Subject: [PATCH 025/183] Log exception instead of print (#2740) --- .../app/entity/ContractInteract.java | 3 ++- .../app/service/AWHttpService.java | 3 +-- .../app/service/AlphaWalletService.java | 4 ++-- .../alphawallet/app/service/GasService.java | 4 ++-- .../app/service/OpenSeaService.java | 1 - .../alphawallet/app/service/SwapService.java | 1 - .../app/service/TickerService.java | 4 ++-- .../service/TransactionsNetworkClient.java | 21 +------------------ .../app/ui/widget/entity/HistoryChart.java | 3 ++- .../alphawallet/app/util/AWEnsResolver.java | 2 +- .../app/viewmodel/HomeViewModel.java | 10 +-------- 11 files changed, 14 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java b/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java index 36579aed33..679a1b33ef 100644 --- a/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java +++ b/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java @@ -23,6 +23,7 @@ import io.reactivex.schedulers.Schedulers; import okhttp3.OkHttpClient; import okhttp3.Request; +import timber.log.Timber; /** * Created by JB on 7/05/2022. @@ -65,7 +66,7 @@ private String loadMetaData(String tokenURI) } catch (Exception e) { - // + Timber.e(e); } return ""; diff --git a/app/src/main/java/com/alphawallet/app/service/AWHttpService.java b/app/src/main/java/com/alphawallet/app/service/AWHttpService.java index 713d999e97..60009021c8 100644 --- a/app/src/main/java/com/alphawallet/app/service/AWHttpService.java +++ b/app/src/main/java/com/alphawallet/app/service/AWHttpService.java @@ -144,13 +144,12 @@ protected InputStream performIO(String request) throws IOException } else { - Timber.d("performIO: throw SocketTimeoutException"); throw new SocketTimeoutException(); } } //TODO: Also check java.io.InterruptedIOException - if (response.code()/100 == 4) //rate limited + if (response.code() / 100 == 4) //rate limited { return trySecondaryNode(request); } diff --git a/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java b/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java index 82f01c01a9..9d6e84cf41 100644 --- a/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java +++ b/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java @@ -234,7 +234,7 @@ private Single sendFeemasterTransaction( } catch (Exception e) { - e.printStackTrace(); + Timber.e(e); } return result; @@ -324,7 +324,7 @@ public Single checkFeemasterService(String url, long chainId, String ad } catch (Exception e) { - e.printStackTrace(); + Timber.e(e); } return result; diff --git a/app/src/main/java/com/alphawallet/app/service/GasService.java b/app/src/main/java/com/alphawallet/app/service/GasService.java index 5e35c268bb..ac4de27e84 100644 --- a/app/src/main/java/com/alphawallet/app/service/GasService.java +++ b/app/src/main/java/com/alphawallet/app/service/GasService.java @@ -489,11 +489,11 @@ public Single getChainFeeHistory(int blockCount, String lastBlock, S } catch (org.json.JSONException j) { - Timber.d("Note: " + info.getShortName() + " does not appear to have EIP1559 support"); + Timber.e("Note: " + info.getShortName() + " does not appear to have EIP1559 support"); } catch (Exception e) { - Timber.w(e); + Timber.e(e); } return new FeeHistory(); diff --git a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java index 1798d07bad..04aaad1671 100644 --- a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java +++ b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java @@ -94,7 +94,6 @@ private String executeRequest(long networkId, String api) } else { - Timber.d(response.toString()); return JsonUtils.EMPTY_RESULT; } } diff --git a/app/src/main/java/com/alphawallet/app/service/SwapService.java b/app/src/main/java/com/alphawallet/app/service/SwapService.java index c1a623a713..512947c6dd 100644 --- a/app/src/main/java/com/alphawallet/app/service/SwapService.java +++ b/app/src/main/java/com/alphawallet/app/service/SwapService.java @@ -45,7 +45,6 @@ private Request buildRequest(String api) private String executeRequest(String api) { - Timber.d(api); try (okhttp3.Response response = httpClient.newCall(buildRequest(api)).execute()) { if (response.isSuccessful()) diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index fa1c1cbed8..8526533e97 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -210,7 +210,7 @@ private Single fetchCoinGeckoChainPrices() } } } - catch (IOException e) + catch (Exception e) { Timber.e(e); } @@ -548,7 +548,7 @@ public Single convertPair(String currency1, String currency2) } catch (Exception e) { - e.printStackTrace(); + Timber.e(e); rate = 0.0; } diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java index 7e207e2648..5a4aa15f0b 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java @@ -39,7 +39,6 @@ import org.json.JSONException; import org.json.JSONObject; -import java.io.InterruptedIOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; @@ -451,12 +450,6 @@ private EtherscanTransaction[] readTransactions(NetworkInfo networkInfo, TokensS return getEtherscanTransactions(result); } } - catch (InterruptedIOException e) - { - //If user switches account or network during a fetch - //this exception is going to be thrown because we're terminating the API call - //Don't display error - } catch (Exception e) { Timber.e(e); @@ -694,15 +687,9 @@ private String readNextTxBatch(String walletAddress, NetworkInfo networkInfo, lo result = "0"; } } - catch (InterruptedIOException e) - { - //If user switches account or network during a fetch - //this exception is going to be thrown because we're terminating the API call - //Don't display error - } catch (Exception e) { - if (networkInfo.chainId != ARTIS_TAU1_ID && BuildConfig.DEBUG) e.printStackTrace(); + if (networkInfo.chainId != ARTIS_TAU1_ID && BuildConfig.DEBUG) Timber.e(e); } return result; @@ -756,12 +743,6 @@ private EtherscanTransaction[] readCovalentTransactions(TokensService svs, Strin return new EtherscanTransaction[0]; } } - catch (InterruptedIOException e) - { - //If user switches account or network during a fetch - //this exception is going to be thrown because we're terminating the API call - //Don't display error - } catch (Exception e) { Timber.e(e); diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/HistoryChart.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/HistoryChart.java index 4604622b59..69b99723e7 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/HistoryChart.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/HistoryChart.java @@ -34,6 +34,7 @@ import io.reactivex.schedulers.Schedulers; import okhttp3.OkHttpClient; import okhttp3.Request; +import timber.log.Timber; public class HistoryChart extends View { @@ -141,7 +142,7 @@ static Single fetchHistory(Range range, String tokenId) } catch (Exception e) { - e.printStackTrace(); + Timber.e(e); } return null; }); diff --git a/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java b/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java index 031c2e800b..19772ff72f 100644 --- a/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java +++ b/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java @@ -336,7 +336,7 @@ private String resolveDAS(String ensName) } catch (Exception e) { - Timber.tag("ENS").d(e.getMessage()); + Timber.tag("ENS").e(e); } return ""; diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java index e73da539cb..0db4032bc3 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java @@ -4,7 +4,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import android.app.Activity; -import android.app.ActivityManager; import android.app.DownloadManager; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -40,7 +39,6 @@ import com.alphawallet.app.entity.Transaction; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletConnectActions; -import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; import com.alphawallet.app.interact.FetchWalletsInteract; import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.repository.CurrencyRepositoryType; @@ -70,8 +68,6 @@ import com.alphawallet.app.util.RateApp; import com.alphawallet.app.util.Utils; import com.alphawallet.app.walletconnect.WCClient; -import com.alphawallet.app.walletconnect.WCSession; -import com.alphawallet.app.walletconnect.entity.WCPeerMeta; import com.alphawallet.app.walletconnect.entity.WCUtils; import com.alphawallet.app.widget.EmailPromptView; import com.alphawallet.app.widget.QRCodeActionsView; @@ -88,12 +84,8 @@ import java.io.FileOutputStream; import java.io.InputStream; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.UUID; import javax.inject.Inject; @@ -662,7 +654,7 @@ public void tryToShowWhatsNewDialog(Context context) { }).isDisposed(); } } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); + Timber.e(e); } } From b44b65edb339ec91e3e733854014fca84bd4ba63 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Sat, 23 Jul 2022 16:03:16 +0800 Subject: [PATCH 026/183] Scroll to default wallet (#2737) --- .../alphawallet/app/ui/WalletsActivity.java | 17 ++++- .../widget/adapter/WalletsSummaryAdapter.java | 9 +++ .../alphawallet/app/entity/WalletFactory.java | 11 +++ .../adapter/WalletsSummaryAdapterTest.java | 76 +++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 app/src/test/java/com/alphawallet/app/entity/WalletFactory.java create mode 100644 app/src/test/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapterTest.java diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java index d8e0d3c8a1..1cc542358e 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java @@ -104,6 +104,15 @@ protected void onResume() initViews(); } + private void scrollToDefaultWallet() + { + int position = adapter.getDefaultWalletIndex(); + if (position != -1) + { + list.smoothScrollToPosition(position); + } + } + private void initViewModel() { if (viewModel == null) @@ -337,6 +346,7 @@ private void onChangeDefaultWallet(Wallet wallet) } adapter.setDefaultWallet(wallet); + scrollToDefaultWallet(); if (requiresHomeRefresh) { viewModel.stopUpdates(); @@ -355,7 +365,12 @@ private void onChangeDefaultWallet(Wallet wallet) private void onFetchWallets(Wallet[] wallets) { enableDisplayHomeAsUp(); - if (adapter != null) adapter.setWallets(wallets); + if (adapter != null) + { + adapter.setWallets(wallets); + scrollToDefaultWallet(); + } + invalidateOptionsMenu(); } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapter.java index ebde1bdf52..e3438e578c 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapter.java @@ -315,6 +315,15 @@ public void onDestroy() realm.close(); } + public int getDefaultWalletIndex() + { + if (defaultWallet != null) + { + return getWalletIndex(defaultWallet.address); + } + return -1; + } + public interface OnSetWalletDefaultListener { void onSetDefault(Wallet wallet); } diff --git a/app/src/test/java/com/alphawallet/app/entity/WalletFactory.java b/app/src/test/java/com/alphawallet/app/entity/WalletFactory.java new file mode 100644 index 0000000000..1f575e9195 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/entity/WalletFactory.java @@ -0,0 +1,11 @@ +package com.alphawallet.app.entity; + +public class WalletFactory +{ + public static Wallet createHDKeyWallet(String address) + { + Wallet wallet = new Wallet(address); + wallet.type = WalletType.HDKEY; + return wallet; + } +} diff --git a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapterTest.java b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapterTest.java new file mode 100644 index 0000000000..32471143aa --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapterTest.java @@ -0,0 +1,76 @@ +package com.alphawallet.app.ui.widget.adapter; + +import static com.alphawallet.app.entity.WalletFactory.createHDKeyWallet; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doNothing; +import static org.powermock.api.mockito.PowerMockito.doReturn; + +import android.content.Context; + +import androidx.recyclerview.widget.RecyclerView; + +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.interact.GenericWalletInteract; +import com.alphawallet.app.repository.WalletRepository; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.Arrays; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(RecyclerView.Adapter.class) +public class WalletsSummaryAdapterTest +{ + @Mock + private WalletRepository walletRepository; + + @Mock + private Context context; + + @InjectMocks + private GenericWalletInteract genericWalletInteract; + + private WalletsSummaryAdapter adapter; + + @Before + public void setUp() throws Exception + { + doReturn("Summary").when(context).getString(anyInt()); + WalletsSummaryAdapter raw = new WalletsSummaryAdapter(context, null, genericWalletInteract, false); + adapter = PowerMockito.spy(raw); + doNothing().when(adapter).notifyDataSetChanged(); + } + + @Test + public void should_get_default_wallet_index() + { + Wallet[] wallets = Arrays.asList(createHDKeyWallet("0x1"), createHDKeyWallet("0x2")).toArray(new Wallet[] {}); + adapter.setWallets(wallets); + adapter.setDefaultWallet(createHDKeyWallet("0x2")); + + int index = adapter.getDefaultWalletIndex() - 3; // There are 3 title labels added as Wallet + + assertThat(index, equalTo(1)); + } + + @Test + public void test_getDefaultWalletIndex_should_get_negative_one_when_no_default_wallet() + { + Wallet[] wallets = Arrays.asList(createHDKeyWallet("0x1"), createHDKeyWallet("0x2")).toArray(new Wallet[] {}); + adapter.setWallets(wallets); + + int index = adapter.getDefaultWalletIndex(); + + assertThat(index, equalTo(-1)); + } + +} \ No newline at end of file From 3a63adb93ccf731cdeba0137743ba490439f8660 Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 23 Jul 2022 09:04:15 +0100 Subject: [PATCH 027/183] Fix for gas in chains where gas cost is very small (#2744) --- .../app/entity/EIP1559FeeOracleResult.java | 24 ++++++- .../app/ui/GasSettingsActivity.java | 15 +++- .../alphawallet/app/util/BalanceUtils.java | 69 +++++++++++++++++++ .../com/alphawallet/app/widget/GasWidget.java | 2 +- .../alphawallet/app/widget/GasWidget2.java | 2 +- 5 files changed, 105 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/EIP1559FeeOracleResult.java b/app/src/main/java/com/alphawallet/app/entity/EIP1559FeeOracleResult.java index 4d1f894c04..ba1a442fd6 100644 --- a/app/src/main/java/com/alphawallet/app/entity/EIP1559FeeOracleResult.java +++ b/app/src/main/java/com/alphawallet/app/entity/EIP1559FeeOracleResult.java @@ -8,6 +8,8 @@ import java.math.BigDecimal; import java.math.BigInteger; +import timber.log.Timber; + /** * Created by JB on 20/01/2022. */ @@ -19,8 +21,8 @@ public class EIP1559FeeOracleResult implements Parcelable public EIP1559FeeOracleResult(BigInteger maxFee, BigInteger maxPriority, BigInteger base) { - maxFeePerGas = minOneGwei(maxFee); - maxPriorityFeePerGas = minOneGwei(maxPriority); + maxFeePerGas = fixGasPriceReturn(maxFee); // Some chains (eg Phi) have a gas price lower than 1Gwei. + maxPriorityFeePerGas = fixGasPriceReturn(maxPriority); baseFee = base; } @@ -69,4 +71,22 @@ private BigInteger minOneGwei(BigInteger input) { return input.max(BalanceUtils.gweiToWei(BigDecimal.ONE)); } + + //returns 1 gwei if null + private BigInteger fixGasPriceReturn(BigInteger input) + { + if (input == null) + { + return BalanceUtils.gweiToWei(BigDecimal.ONE); + } + else if (input.equals(BigInteger.ZERO)) + { + Timber.w("Zero gas price detected"); + return input; + } + else + { + return input; + } + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/GasSettingsActivity.java b/app/src/main/java/com/alphawallet/app/ui/GasSettingsActivity.java index 6c2d9f1df4..6b1374f927 100644 --- a/app/src/main/java/com/alphawallet/app/ui/GasSettingsActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/GasSettingsActivity.java @@ -44,6 +44,7 @@ import com.alphawallet.app.util.Utils; import com.alphawallet.app.viewmodel.GasSettingsViewModel; import com.alphawallet.app.widget.GasSliderView; +import com.alphawallet.token.tools.Convert; import com.google.android.material.radiobutton.MaterialRadioButton; import java.math.BigDecimal; @@ -59,7 +60,7 @@ @AndroidEntryPoint public class GasSettingsActivity extends BaseActivity implements GasSettingsCallback { - private static final int GAS_PRECISION = 5; //5 dp for gas + public static final int GAS_PRECISION = 5; //5 dp for gas GasSettingsViewModel viewModel; @@ -376,7 +377,15 @@ else if (position != TXSpeed.CUSTOM && currentGasSpeedIndex == TXSpeed.CUSTOM) BigDecimal maxGas = BalanceUtils.weiToGweiBI(gs.gasPrice.maxFeePerGas); String speedGwei; - if (maxGas.compareTo(BigDecimal.valueOf(2)) < 0) + BigDecimal ethAmount = Convert.fromWei(new BigDecimal(gs.gasPrice.maxFeePerGas), Convert.Unit.ETHER); + + if (BalanceUtils.requiresSmallGweiValueSuffix(ethAmount)) + { + speedGwei = context.getString(R.string.token_balance, + BalanceUtils.getSlidingBaseValue(new BigDecimal(gs.gasPrice.maxFeePerGas), 18, GAS_PRECISION), + baseCurrency.getSymbol()); + } + else if (maxGas.compareTo(BigDecimal.valueOf(2)) < 0) { speedGwei = BalanceUtils.weiToGwei(new BigDecimal(gs.gasPrice.maxFeePerGas), 2); } @@ -426,7 +435,7 @@ else if (position != TXSpeed.CUSTOM && currentGasSpeedIndex == TXSpeed.CUSTOM) BigDecimal gasFee = new BigDecimal(gs.gasPrice.maxFeePerGas).multiply(useGasLimit); - String gasAmountInBase = BalanceUtils.getScaledValueScientific(gasFee, baseCurrency.tokenInfo.decimals, GAS_PRECISION); + String gasAmountInBase = BalanceUtils.getSlidingBaseValue(gasFee, baseCurrency.tokenInfo.decimals, GAS_PRECISION); if (gasAmountInBase.equals("0")) gasAmountInBase = "0.00001"; //NB no need to allow for zero gas chains; this activity wouldn't appear String displayStr = context.getString(R.string.gas_amount, gasAmountInBase, baseCurrency.getSymbol()); diff --git a/app/src/main/java/com/alphawallet/app/util/BalanceUtils.java b/app/src/main/java/com/alphawallet/app/util/BalanceUtils.java index aa000b8d1d..6c03800372 100644 --- a/app/src/main/java/com/alphawallet/app/util/BalanceUtils.java +++ b/app/src/main/java/com/alphawallet/app/util/BalanceUtils.java @@ -15,6 +15,9 @@ public class BalanceUtils { private static final String weiInEth = "1000000000000000000"; private static final int showDecimalPlaces = 5; + private static final int slidingDecimalPlaces = 2; + private static final BigDecimal displayThresholdMillis = BigDecimal.ONE.divide(BigDecimal.valueOf(1000000), 18, RoundingMode.DOWN); + private static final BigDecimal oneGwei = BigDecimal.ONE.divide(Convert.Unit.GWEI.getWeiFactor(), 18, RoundingMode.DOWN); //BigDecimal.valueOf(0.000000001); public static final String MACRO_PATTERN = "###,###,###,###,##0"; public static final String CURRENCY_PATTERN = MACRO_PATTERN + ".00"; @@ -192,6 +195,16 @@ else if (requiresSuffix(correctedValue, dPlaces)) return returnValue; } + public static boolean requiresSmallValueSuffix(BigDecimal correctedValue) + { + return correctedValue.compareTo(displayThresholdMillis) < 0; + } + + public static boolean requiresSmallGweiValueSuffix(BigDecimal ethAmount) + { + return ethAmount.compareTo(oneGwei) < 0; + } + private static boolean requiresSuffix(BigDecimal correctedValue, int dPlaces) { final BigDecimal displayThreshold = BigDecimal.ONE.divide(BigDecimal.valueOf(Math.pow(10, dPlaces)), 18, RoundingMode.DOWN); @@ -330,4 +343,60 @@ public static String getRawFormat(String amount, long decimals) BigDecimal a = new BigDecimal(amount); return a.movePointRight((int) decimals).toString(); } + + public static String getSlidingBaseValue(final BigDecimal value, int decimals, int dPlaces) + { + String returnValue; + BigDecimal correctedValue = value.divide(BigDecimal.valueOf(Math.pow(10, decimals)), 18, RoundingMode.DOWN); + + if (value.equals(BigDecimal.ZERO)) //zero balance + { + returnValue = "0"; + } + else if (requiresSmallValueSuffix(correctedValue)) + { + return smallSuffixValue(correctedValue); + } + else if (correctedValue.compareTo(displayThresholdMillis) < 0) + { + returnValue = correctedValue.divide(displayThresholdMillis, slidingDecimalPlaces, RoundingMode.DOWN) + " m"; + } + else if (requiresSuffix(correctedValue, dPlaces)) + { + returnValue = getSuffixedValue(correctedValue, dPlaces); + } + else //otherwise display in standard pattern to dPlaces dp + { + DecimalFormat df = getFormat(getDigitalPattern(dPlaces)); + //DecimalFormat df = new DecimalFormat(getDigitalPattern(dPlaces)); + df.setRoundingMode(RoundingMode.DOWN); + returnValue = convertToLocale(df.format(correctedValue)); + } + + return returnValue; + } + + private static String smallSuffixValue(BigDecimal correctedValue) + { + final BigDecimal displayThresholdMicro = BigDecimal.ONE.divide(BigDecimal.valueOf(1000000000), 18, RoundingMode.DOWN); + final BigDecimal displayThresholdNano = BigDecimal.ONE.divide(BigDecimal.valueOf(1000000000000L), 18, RoundingMode.DOWN); + + BigDecimal weiAmount = Convert.toWei(correctedValue, Convert.Unit.ETHER); + + DecimalFormat df = getFormat("###,###.##"); + df.setRoundingMode(RoundingMode.DOWN); + + if (correctedValue.compareTo(displayThresholdNano) < 0) + { + return weiAmount.longValue() + " wei"; + } + else if (correctedValue.compareTo(displayThresholdMicro) < 0) + { + return df.format(weiAmount.divide(BigDecimal.valueOf(1000), 2, RoundingMode.DOWN)) + "K wei"; + } + else + { + return df.format(weiAmount.divide(BigDecimal.valueOf(1000000), 2, RoundingMode.DOWN)) + "M wei"; + } + } } diff --git a/app/src/main/java/com/alphawallet/app/widget/GasWidget.java b/app/src/main/java/com/alphawallet/app/widget/GasWidget.java index 17397680c4..49cd808292 100644 --- a/app/src/main/java/com/alphawallet/app/widget/GasWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/GasWidget.java @@ -320,7 +320,7 @@ public void run() Token baseCurrency = tokensService.getTokenOrBase(token.tokenInfo.chainId, token.getWallet()); BigInteger networkFee = gs.gasPrice.maxFeePerGas.multiply(getUseGasLimit()); - String gasAmountInBase = BalanceUtils.getScaledValueScientific(new BigDecimal(networkFee), baseCurrency.tokenInfo.decimals); + String gasAmountInBase = BalanceUtils.getSlidingBaseValue(new BigDecimal(networkFee), baseCurrency.tokenInfo.decimals, GasSettingsActivity.GAS_PRECISION); if (gasAmountInBase.equals("0")) gasAmountInBase = "0.0001"; String displayStr = getContext().getString(R.string.gas_amount, gasAmountInBase, baseCurrency.getSymbol()); diff --git a/app/src/main/java/com/alphawallet/app/widget/GasWidget2.java b/app/src/main/java/com/alphawallet/app/widget/GasWidget2.java index df0fa94fba..fc8329e408 100644 --- a/app/src/main/java/com/alphawallet/app/widget/GasWidget2.java +++ b/app/src/main/java/com/alphawallet/app/widget/GasWidget2.java @@ -293,7 +293,7 @@ public void run() Token baseCurrency = tokensService.getTokenOrBase(token.tokenInfo.chainId, token.getWallet()); BigInteger networkFee = gs.gasPrice.maxFeePerGas.multiply(getUseGasLimit()); - String gasAmountInBase = BalanceUtils.getScaledValueScientific(new BigDecimal(networkFee), baseCurrency.tokenInfo.decimals); + String gasAmountInBase = BalanceUtils.getSlidingBaseValue(new BigDecimal(networkFee), baseCurrency.tokenInfo.decimals, GasSettingsActivity.GAS_PRECISION); if (gasAmountInBase.equals("0")) gasAmountInBase = "0.0001"; String displayStr = context.getString(R.string.gas_amount, gasAmountInBase, baseCurrency.getSymbol()); From a68d9a99f6adc03478e4343dc421bb8a81a1f1d7 Mon Sep 17 00:00:00 2001 From: Asif Ghanchi <92773051+asif-finimble@users.noreply.github.com> Date: Sat, 23 Jul 2022 15:14:28 +0530 Subject: [PATCH 028/183] Added options to delete WalletConnect history (#2726) --- .../app/entity/GenericCallback.java | 9 ++ .../app/ui/WalletConnectSessionActivity.java | 41 +++++++- .../app/viewmodel/WalletConnectViewModel.java | 93 ++++++++++++++++++- app/src/main/res/drawable/ic_delete.xml | 5 + app/src/main/res/menu/menu_wc_sessions.xml | 18 ++++ .../main/res/menu/menu_wc_sessions_delete.xml | 14 +++ app/src/main/res/values-es/strings.xml | 2 + app/src/main/res/values-fr/strings.xml | 2 + app/src/main/res/values-my/strings.xml | 2 + app/src/main/res/values-vi/strings.xml | 2 + app/src/main/res/values-zh/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 12 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/entity/GenericCallback.java create mode 100644 app/src/main/res/drawable/ic_delete.xml create mode 100644 app/src/main/res/menu/menu_wc_sessions.xml create mode 100644 app/src/main/res/menu/menu_wc_sessions_delete.xml diff --git a/app/src/main/java/com/alphawallet/app/entity/GenericCallback.java b/app/src/main/java/com/alphawallet/app/entity/GenericCallback.java new file mode 100644 index 0000000000..1511aacf79 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/GenericCallback.java @@ -0,0 +1,9 @@ +package com.alphawallet.app.entity; + +/** A generic functional interface to supply a result of an async operation + * @param Result required by caller + */ +public interface GenericCallback +{ + void call(T t); +} diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java index 20d42d484d..f38c533eaa 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java @@ -21,6 +21,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.widget.PopupMenu; import androidx.lifecycle.ViewModelProvider; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.recyclerview.widget.LinearLayoutManager; @@ -39,6 +40,7 @@ import java.util.List; import dagger.hilt.android.AndroidEntryPoint; +import timber.log.Timber; /** @@ -131,6 +133,15 @@ private void setupList() if (wcSessions.isEmpty()) { layoutNoActiveSessions.setVisibility(View.VISIBLE); + // remove ghosting when all items deleted + if (recyclerView != null) + { + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter != null) + { + adapter.notifyDataSetChanged(); + } + } } else { @@ -157,7 +168,7 @@ public void onResume() @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_scan_wc, menu); + getMenuInflater().inflate(R.menu.menu_wc_sessions, menu); return super.onCreateOptionsMenu(menu); } @@ -172,6 +183,11 @@ else if (item.getItemId() == R.id.action_scan) { openQrScanner(); } + else if (item.getItemId() == R.id.action_delete) + { + View v = findViewById(R.id.action_delete); + openDeleteMenu(v); + } return super.onOptionsItemSelected(item); } @@ -184,6 +200,29 @@ private void openQrScanner() startActivity(intent); } + private void openDeleteMenu(View v) + { + Timber.d("openDeleteMenu: view: %s", v); + PopupMenu popupMenu = new PopupMenu(this, v); + popupMenu.getMenuInflater().inflate(R.menu.menu_wc_sessions_delete, popupMenu.getMenu()); + popupMenu.setOnMenuItemClickListener(item -> { + if (item.getItemId() == R.id.action_delete_empty) + { + // delete empty + viewModel.removeEmptySessions(this, this::setupList); + return true; + } + else if (item.getItemId() == R.id.action_delete_all) + { + Timber.d("openDeleteMenu: deleteAll: "); + viewModel.removeAllSessions(this, this::setupList); + return true; + } + return false; + }); + popupMenu.show(); + } + private void setupClient(final String sessionId, final CustomAdapter.CustomViewHolder holder) { viewModel.getClient(this, sessionId, client -> handler.post(() -> { diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java index 9d2a037cd1..d8bfff3d0e 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java @@ -3,6 +3,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import android.app.Activity; +import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -16,6 +17,7 @@ import com.alphawallet.app.C; import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.DAppFunction; +import com.alphawallet.app.entity.GenericCallback; import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.entity.SendTransactionInterface; import com.alphawallet.app.entity.SignAuthenticationCallback; @@ -401,6 +403,7 @@ public void updateSession(String sessionId, long sessionChainId) public void deleteSession(String sessionId) { + Timber.d("deleteSession: %s", sessionId); try (Realm realm = realmManager.getRealmInstance(WC_SESSION_DB)) { realm.executeTransactionAsync(r -> { @@ -672,7 +675,8 @@ public boolean isChainAdded(long chainId) return ethereumNetworkRepository.getNetworkByChain(chainId) != null; } - public TokensService getTokenService() { + public TokensService getTokenService() + { return tokensService; } @@ -693,4 +697,91 @@ public void endSession(String sessionId) }); } } + + // remove wallet connect sessions with no transaction history + public void removeEmptySessions(Context context, Runnable onComplete) + { + // create list of sessions which are inactive and has zero txn/sign + // delete them from realm + getInactiveSessionIds(context, sessions -> { + ArrayList sessionIdsToRemove = new ArrayList<>(); + for (String sessionId : sessions) + { + // if no txn/sign history found + if (getSignRecords(sessionId).isEmpty()) + { + // add this sessionId to the list of removable + sessionIdsToRemove.add(sessionId); + } + } + deleteSessionsFromRealm(sessionIdsToRemove, onComplete); + }); + } + + // remove all inactive wallet connect sessions + public void removeAllSessions(Context context, Runnable onSuccess) + { + getInactiveSessionIds(context, list -> { + Timber.d("removeAllSessions: sessionsToRemove: %d", list.size()); + deleteSessionsFromRealm(list, onSuccess); + }); + } + + // connects to service to check session state and gives inactive sessions + private void getInactiveSessionIds(Context context, GenericCallback> callback) + { + List sessionItems = getSessions(); // all sessions in DB + ArrayList inactiveSessions = new ArrayList<>(); + ServiceConnection connection = new ServiceConnection() + { + @Override + public void onServiceConnected(ComponentName name, IBinder service) + { + WalletConnectService walletConnectService = ((WalletConnectService.LocalBinder) service).getService(); + // loop & populate sessions which are inactive + for (WalletConnectSessionItem item : sessionItems) + { + WCClient wcClient = walletConnectService.getClient(item.sessionId); + // if client is not connected ie: session inactive + if (wcClient == null || !wcClient.isConnected()) + { + inactiveSessions.add(item.sessionId); + } + } + callback.call(inactiveSessions); // return inactive sessions to caller + } + + @Override + public void onServiceDisconnected(ComponentName name) + { + //walletConnectService = null; + Timber.tag(TAG).d("Service disconnected"); + } + }; + Intent i = new Intent(context, WalletConnectService.class); // not specifying action as no need. we just need to bind to service + context.startService(i); + context.bindService(i, connection, Service.BIND_ABOVE_CLIENT); + } + + // deletes the RealmWCSession objects with the given sessionIds present in the list + private void deleteSessionsFromRealm(List sessionIds, Runnable onSuccess) + { + Timber.d("deleteSessionsFromRealm: sessions: %s", sessionIds); + if (sessionIds.isEmpty()) + return; + try (Realm realm = realmManager.getRealmInstance(WC_SESSION_DB)) + { + realm.executeTransactionAsync(r -> { + boolean isDeleted = r.where(RealmWCSession.class) + .in("sessionId", sessionIds.toArray(new String[]{})) + .findAll() + .deleteAllFromRealm(); + Timber.d("deleteSessions: Success: %s\nList: %s", isDeleted, sessionIds); + }, onSuccess::run); + } + catch (Exception e) + { + Timber.e(e); + } + } } diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml new file mode 100644 index 0000000000..53ba4d7726 --- /dev/null +++ b/app/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/menu/menu_wc_sessions.xml b/app/src/main/res/menu/menu_wc_sessions.xml new file mode 100644 index 0000000000..f679effe46 --- /dev/null +++ b/app/src/main/res/menu/menu_wc_sessions.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_wc_sessions_delete.xml b/app/src/main/res/menu/menu_wc_sessions_delete.xml new file mode 100644 index 0000000000..13557210db --- /dev/null +++ b/app/src/main/res/menu/menu_wc_sessions_delete.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index d0d2eae647..74c278e5e6 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -929,4 +929,6 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Delete Empty + Delete All diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index aed3fecca2..fdf41d9142 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -946,4 +946,6 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Delete Empty + Delete All diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index accc52cd4f..34a4509def 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -971,4 +971,6 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Delete Empty + Delete All diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 62a40f251f..98bb8aa311 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -948,4 +948,6 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Delete Empty + Delete All diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index b1e6d66468..786edd5ac3 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -929,4 +929,6 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Delete Empty + Delete All diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 37d9045474..aebece962a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -970,4 +970,6 @@ This will inform the remote site your wallet address is %s Floor Price Average Price + Delete Empty + Delete All From 55b426560e0eea3e6805e724af8c9151b0a33248 Mon Sep 17 00:00:00 2001 From: justindg Date: Sun, 24 Jul 2022 23:38:56 -0700 Subject: [PATCH 029/183] Exclude unsupported chains from swap settings list (#2746) --- .../app/ui/widget/adapter/ChainFilter.java | 30 ++++++++++++ .../app/widget/SwapSettingsDialog.java | 7 ++- .../ui/widget/adapter/ChainFilterTest.java | 46 +++++++++++++++++++ 3 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainFilter.java create mode 100644 app/src/test/java/com/alphawallet/app/ui/widget/adapter/ChainFilterTest.java diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainFilter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainFilter.java new file mode 100644 index 0000000000..e6af0be5d3 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainFilter.java @@ -0,0 +1,30 @@ +package com.alphawallet.app.ui.widget.adapter; + +import com.alphawallet.app.entity.lifi.Chain; +import com.alphawallet.ethereum.EthereumNetworkBase; + +import java.util.ArrayList; +import java.util.List; + +public class ChainFilter +{ + private final List chains; + + public ChainFilter(List chains) + { + this.chains = chains; + } + + public List getSupportedChains() + { + List filteredChains = new ArrayList<>(); + for (Chain c : chains) + { + if (EthereumNetworkBase.getNetworkByChain(c.id) != null) + { + filteredChains.add(c); + } + } + return filteredChains; + } +} diff --git a/app/src/main/java/com/alphawallet/app/widget/SwapSettingsDialog.java b/app/src/main/java/com/alphawallet/app/widget/SwapSettingsDialog.java index f47edf97f0..0f17a299f6 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SwapSettingsDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/SwapSettingsDialog.java @@ -3,7 +3,6 @@ import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED; import android.app.Activity; -import android.content.DialogInterface; import android.content.res.Resources; import android.view.View; import android.widget.ImageView; @@ -14,8 +13,8 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.lifi.Chain; +import com.alphawallet.app.ui.widget.adapter.ChainFilter; import com.alphawallet.app.ui.widget.adapter.SelectChainAdapter; -import com.alphawallet.app.ui.widget.divider.ListDivider; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetDialog; @@ -51,8 +50,8 @@ public SwapSettingsDialog(@NonNull Activity activity) public SwapSettingsDialog(Activity activity, List chains, SwapSettingsInterface swapSettingsInterface) { this(activity); - - adapter = new SelectChainAdapter(activity, chains, swapSettingsInterface); + ChainFilter filter = new ChainFilter(chains); + adapter = new SelectChainAdapter(activity, filter.getSupportedChains(), swapSettingsInterface); chainList.setLayoutManager(new LinearLayoutManager(getContext())); chainList.setAdapter(adapter); } diff --git a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/ChainFilterTest.java b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/ChainFilterTest.java new file mode 100644 index 0000000000..058a583b17 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/ChainFilterTest.java @@ -0,0 +1,46 @@ +package com.alphawallet.app.ui.widget.adapter; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import androidx.annotation.NonNull; + +import com.alphawallet.app.entity.lifi.Chain; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class ChainFilterTest +{ + private ChainFilter chainFilter; + + @Before + public void setUp() throws Exception + { + List list = new ArrayList<>(); + list.add(createChain(1285, "Moonriver")); + list.add(createChain(1, "Ethereum")); + list.add(createChain(137, "Matic")); + chainFilter = new ChainFilter(list); + } + + @Test + public void should_not_contain_unsupported_chain() + { + List result = chainFilter.getSupportedChains(); + assertThat(result.get(0).name, equalTo("Ethereum")); + assertThat(result.get(1).name, equalTo("Matic")); + } + + @NonNull + private Chain createChain(long id, String name) + { + Chain c = new Chain(); + c.id = id; + c.name = name; + return c; + } +} \ No newline at end of file From e41cc2eb93448f3a9b258c031697c2221f49c3a9 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Mon, 25 Jul 2022 17:19:56 +0800 Subject: [PATCH 030/183] 2718 remove auto update feature (#2738) * Remove auto update code --- app/src/main/AndroidManifest.xml | 1 - app/src/main/java/com/alphawallet/app/C.java | 2 - .../app/entity/HomeCommsInterface.java | 1 - .../alphawallet/app/entity/HomeReceiver.java | 5 - .../repository/PreferenceRepositoryType.java | 3 - .../SharedPreferenceRepository.java | 12 -- .../com/alphawallet/app/ui/HomeActivity.java | 109 +----------------- .../app/viewmodel/HomeViewModel.java | 82 +------------ .../app/viewmodel/SplashViewModel.java | 15 --- 9 files changed, 7 insertions(+), 223 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2dccb5f50c..4d03b063d3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,7 +7,6 @@ - diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 30dc4a3d93..affa0f39ed 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -173,8 +173,6 @@ public abstract class C { "com.stormbird.wallet.ADDED"; public static final String CHANGED_LOCALE = "com.stormbird.wallet.CHANGED_LOCALE"; - public static final String DOWNLOAD_READY = - "com.stormbird.wallet.DOWNLOAD_READY"; public static final String PAGE_LOADED = "com.stormbird.wallet.PAGE_LOADED"; public static final String RESET_TOOLBAR = diff --git a/app/src/main/java/com/alphawallet/app/entity/HomeCommsInterface.java b/app/src/main/java/com/alphawallet/app/entity/HomeCommsInterface.java index 2de9a623d9..af9233bf60 100644 --- a/app/src/main/java/com/alphawallet/app/entity/HomeCommsInterface.java +++ b/app/src/main/java/com/alphawallet/app/entity/HomeCommsInterface.java @@ -2,7 +2,6 @@ public interface HomeCommsInterface { - void downloadReady(String ready); void requestNotificationPermission(); void backupSuccess(String keyAddress); void resetTokens(); diff --git a/app/src/main/java/com/alphawallet/app/entity/HomeReceiver.java b/app/src/main/java/com/alphawallet/app/entity/HomeReceiver.java index 2fedbaa754..fa06a12fbf 100644 --- a/app/src/main/java/com/alphawallet/app/entity/HomeReceiver.java +++ b/app/src/main/java/com/alphawallet/app/entity/HomeReceiver.java @@ -27,10 +27,6 @@ public void onReceive(Context context, Intent intent) Bundle bundle = intent.getExtras(); switch (intent.getAction()) { - case C.DOWNLOAD_READY: - String message = bundle.getString("Version"); - homeCommsInterface.downloadReady(message); - break; case C.REQUEST_NOTIFICATION_ACCESS: homeCommsInterface.requestNotificationPermission(); break; @@ -49,7 +45,6 @@ public void onReceive(Context context, Intent intent) public void register() { IntentFilter filter = new IntentFilter(); - filter.addAction(C.DOWNLOAD_READY); filter.addAction(C.REQUEST_NOTIFICATION_ACCESS); filter.addAction(C.BACKUP_WALLET_SUCCESS); filter.addAction(C.WALLET_CONNECT_REQUEST); diff --git a/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java index cd1bdfe879..0c9e44b5bd 100644 --- a/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java +++ b/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java @@ -76,9 +76,6 @@ public interface PreferenceRepositoryType { int getUpdateWarningCount(); void setUpdateWarningCount(int count); - int getUpdateAsksCount(); - void setUpdateAsksCount(int count); - long getInstallTime(); void setInstallTime(long time); diff --git a/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java b/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java index 08ff7af6a0..8be1bc9bd9 100644 --- a/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java @@ -8,7 +8,6 @@ import com.alphawallet.app.C; import com.alphawallet.app.entity.CurrencyItem; -import com.alphawallet.app.entity.WalletPage; import java.util.Locale; @@ -35,7 +34,6 @@ public class SharedPreferenceRepository implements PreferenceRepositoryType { private static final String SET_NETWORK_FILTERS = "set_filters"; private static final String SHOULD_SHOW_ROOT_WARNING = "should_show_root_warning"; private static final String UPDATE_WARNINGS = "update_warns"; - private static final String UPDATE_ASKS = "update_asks"; private static final String INSTALL_TIME = "install_time"; public static final String DEVICE_LOCALE = "device_locale"; public static final String DEVICE_COUNTRY = "device_country"; @@ -297,16 +295,6 @@ public void setUpdateWarningCount(int count) { pref.edit().putInt(UPDATE_WARNINGS, count).apply(); } - @Override - public int getUpdateAsksCount() { - return pref.getInt(UPDATE_ASKS, 0); - } - - @Override - public void setUpdateAsksCount(int count) { - pref.edit().putInt(UPDATE_ASKS, count).apply(); - } - @Override public void setInstallTime(long time) { pref.edit().putLong(INSTALL_TIME, time).apply(); diff --git a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java index 63e5dc9306..384d1206ed 100644 --- a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java @@ -106,7 +106,6 @@ public class HomeActivity extends BaseNavigationActivity implements View.OnClick private ImageView successImage; private final Handler handler = new Handler(Looper.getMainLooper()); private HomeReceiver homeReceiver; - private String buildVersion; private Fragment settingsFragment; private Fragment dappBrowserFragment; private Fragment walletFragment; @@ -117,14 +116,11 @@ public class HomeActivity extends BaseNavigationActivity implements View.OnClick private boolean isForeground; private volatile boolean tokenClicked = false; private String openLink; - private boolean inWalletConnect; - public static final int RC_DOWNLOAD_EXTERNAL_WRITE_PERM = 222; public static final int RC_ASSET_EXTERNAL_WRITE_PERM = 223; public static final int RC_ASSET_NOTIFICATION_PERM = 224; public static final int DAPP_BARCODE_READER_REQUEST_CODE = 1; - public static final int DAPP_TRANSACTION_SEND_REQUEST = 2; public static final String STORED_PAGE = "currentPage"; public static final String RESET_TOKEN_SERVICE = "HOME_reset_ts"; public static final String AW_MAGICLINK = "aw.app/"; @@ -203,7 +199,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) viewModel = new ViewModelProvider(this) .get(HomeViewModel.class); - viewModel.identify(this); + viewModel.identify(); viewModel.setWalletStartup(); viewModel.setCurrencyAndLocale(this); viewModel.tryToShowWhatsNewDialog(this); @@ -893,46 +889,6 @@ private BaseFragment getFragment(WalletPage page) else return (BaseFragment) getSupportFragmentManager().getFragments().get(page.ordinal()); } - @Override - public void downloadReady(String build) - { - hideDialog(); - buildVersion = build; - //display download ready popup - //Possibly only show this once per day otherwise too annoying! - int asks = viewModel.getUpdateAsks() + 1; - AWalletConfirmationDialog dialog = new AWalletConfirmationDialog(this); - dialog.setTitle(R.string.new_version_title); - dialog.setSmallText(R.string.new_version); - String newBuild = "New version: " + build; - dialog.setMediumText(newBuild); - dialog.setPrimaryButtonText(R.string.confirm_update); - dialog.setPrimaryButtonListener(v -> - { - if (checkWritePermission(RC_DOWNLOAD_EXTERNAL_WRITE_PERM)) - { - viewModel.downloadAndInstall(build, this); - } - dialog.dismiss(); - }); - if (asks > 1) - { - dialog.setSecondaryButtonText(R.string.dialog_not_again); - } - else - { - dialog.setSecondaryButtonText(R.string.dialog_later); - } - dialog.setSecondaryButtonListener(v -> - { - //only dismiss twice before we stop warning. - viewModel.setUpdateAsksCount(asks); - dialog.dismiss(); - }); - this.dialog = dialog; - dialog.show(); - } - @Override public void requestNotificationPermission() { @@ -978,30 +934,6 @@ private void hideDialog() } } - private boolean checkWritePermission(int permissionTag) - { - if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) - == PackageManager.PERMISSION_GRANTED) - { - return true; - } - else - { - final String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; - if (!ActivityCompat.shouldShowRequestPermissionRationale(this, - Manifest.permission.WRITE_EXTERNAL_STORAGE)) - { - Timber.tag("HomeActivity").w("Folder write permission is not granted. Requesting permission"); - ActivityCompat.requestPermissions(this, permissions, permissionTag); - return false; - } - else - { - return true; - } - } - } - private boolean checkNotificationPermission(int permissionTag) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NOTIFICATION_POLICY) @@ -1041,51 +973,12 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in case DappBrowserFragment.REQUEST_FINE_LOCATION: ((DappBrowserFragment) getFragment(DAPP_BROWSER)).gotGeoAccess(permissions, grantResults); break; - case RC_DOWNLOAD_EXTERNAL_WRITE_PERM: - if (hasPermission(permissions, grantResults)) - { - viewModel.downloadAndInstall(buildVersion, this); - } - else - { - showRequirePermissionError(); - } - break; case RC_ASSET_EXTERNAL_WRITE_PERM: //Can't get here break; } } - private boolean hasPermission(String[] permissions, int[] grantResults) - { - boolean hasPermission = true; - for (int i = 0; i < permissions.length; i++) - { - if (grantResults[i] == -1) - { - hasPermission = false; - break; - } - } - - return hasPermission; - } - - private void showRequirePermissionError() - { - AWalletAlertDialog aDialog = new AWalletAlertDialog(this); - aDialog.setIcon(AWalletAlertDialog.ERROR); - aDialog.setTitle(R.string.install_error); - aDialog.setMessage(R.string.require_write_permission); - aDialog.setButtonText(R.string.action_cancel); - aDialog.setButtonListener(v -> - { - aDialog.dismiss(); - }); - aDialog.show(); - } - private void onInstallIntent(File installFile) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java index 0db4032bc3..6610cb26af 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java @@ -10,7 +10,6 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -26,7 +25,6 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.alphawallet.app.C; import com.alphawallet.app.R; @@ -55,7 +53,6 @@ import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.RealmManager; -import com.alphawallet.app.service.TickerService; import com.alphawallet.app.service.TokensService; import com.alphawallet.app.service.TransactionsService; import com.alphawallet.app.service.WalletConnectService; @@ -105,7 +102,6 @@ public class HomeViewModel extends BaseViewModel { private final String TAG = "HVM"; public static final String ALPHAWALLET_DIR = "AlphaWallet"; - public static final String ALPHAWALLET_FILE_URL = "https://1x.alphawallet.com/dl/latest.apk"; private final MutableLiveData defaultNetwork = new MutableLiveData<>(); private final MutableLiveData transactions = new MutableLiveData<>(); @@ -120,7 +116,6 @@ public class HomeViewModel extends BaseViewModel { private final CurrencyRepositoryType currencyRepository; private final EthereumNetworkRepositoryType ethereumNetworkRepository; private final TransactionsService transactionsService; - private final TickerService tickerService; private final MyAddressRouter myAddressRouter; private final AnalyticsServiceType analyticsService; private final ExternalBrowserRouter externalBrowserRouter; @@ -148,7 +143,6 @@ public class HomeViewModel extends BaseViewModel { EthereumNetworkRepositoryType ethereumNetworkRepository, MyAddressRouter myAddressRouter, TransactionsService transactionsService, - TickerService tickerService, AnalyticsServiceType analyticsService, ExternalBrowserRouter externalBrowserRouter, OkHttpClient httpClient, @@ -163,7 +157,6 @@ public class HomeViewModel extends BaseViewModel { this.ethereumNetworkRepository = ethereumNetworkRepository; this.myAddressRouter = myAddressRouter; this.transactionsService = transactionsService; - this.tickerService = tickerService; this.analyticsService = analyticsService; this.externalBrowserRouter = externalBrowserRouter; this.httpClient = httpClient; @@ -220,7 +213,7 @@ public void showImportLink(Activity activity, String importData) { .filter(wallet -> checkWalletNotEqual(wallet, importData)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(wallet -> importLink(wallet, activity, importData), this::onError); + .subscribe(wallet -> importLink(activity, importData), this::onError); } private boolean checkWalletNotEqual(Wallet wallet, String importData) { @@ -247,7 +240,7 @@ private boolean checkWalletNotEqual(Wallet wallet, String importData) { return filterPass; } - private void importLink(Wallet wallet, Activity activity, String importData) { + private void importLink(Activity activity, String importData) { importTokenRouter.open(activity, importData); } @@ -259,50 +252,6 @@ public void restartHomeActivity(Context context) context.startActivity(intent); } - public void downloadAndInstall(String build, Context ctx) { - createDirectory(); - downloadAPK(build, ctx); - } - - private void createDirectory() { - //create XML repository directory - File directory = new File( - Environment.getExternalStorageDirectory() - + File.separator + ALPHAWALLET_DIR); - - if (!directory.exists()) { - directory.mkdir(); - } - } - - private void downloadAPK(String version, Context ctx) { - String destination = Environment.getExternalStorageDirectory() - + File.separator + ALPHAWALLET_DIR; - - File testFile = new File(destination, "AlphaWallet-" + version + ".apk"); - if (testFile.exists()) { - testFile.delete(); - } - final Uri uri = Uri.parse("file://" + testFile.getPath()); - - DownloadManager.Request request = new DownloadManager.Request(Uri.parse(ALPHAWALLET_FILE_URL)); - request.setDescription(ctx.getString(R.string.alphawallet_update) + " " + version); - request.setTitle(ctx.getString(R.string.app_name)); - request.setDestinationUri(uri); - final DownloadManager manager = (DownloadManager) ctx.getSystemService(Context.DOWNLOAD_SERVICE); - long downloadId = manager.enqueue(request); - - //set BroadcastReceiver to install app when .apk is downloaded - BroadcastReceiver onComplete = new BroadcastReceiver() { - public void onReceive(Context ctxt, Intent intent) { - installIntent.postValue(testFile); - LocalBroadcastManager.getInstance(ctxt).unregisterReceiver(this); - } - }; - - LocalBroadcastManager.getInstance(ctx).registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); - } - public void getWalletName(Context context) { disposable = fetchWalletsInteract .getWallet(preferenceRepository.getCurrentWalletAddress()) @@ -363,15 +312,6 @@ public void setFindWalletAddressDialogShown(boolean isShown) { preferenceRepository.setFindWalletAddressDialogShown(isShown); } - public String getDefaultCurrency(){ - return currencyRepository.getDefaultCurrency(); - } - - public void updateTickers() - { - tickerService.updateTickers(); - } - private void onENSError(Throwable throwable) { Timber.tag(TAG).e(throwable); @@ -399,8 +339,6 @@ public void handleQRCode(Activity activity, String qrCode) showActionSheet(activity, qrResult); break; case PAYMENT: - showSend(activity, qrResult); - break; case TRANSFER: showSend(activity, qrResult); break; @@ -485,7 +423,7 @@ else if (v.getId() == R.id.close_action) dialog.setContentView(contentView); dialog.setCancelable(true); dialog.setCanceledOnTouchOutside(true); - BottomSheetBehavior behavior = BottomSheetBehavior.from((View) contentView.getParent()); + BottomSheetBehavior behavior = BottomSheetBehavior.from((View) contentView.getParent()); dialog.setOnShowListener(dialog -> behavior.setPeekHeight(contentView.getHeight())); dialog.show(); } @@ -517,7 +455,7 @@ public void showMyAddress(Activity activity) * This method will uniquely identify the device by creating an ID and store in preference. * This will be changed if user reinstall application or clear the storage explicitly. **/ - public void identify(Context ctx) + public void identify() { String uuid = preferenceRepository.getUniqueId(); @@ -571,14 +509,6 @@ public void setUpdateWarningCount(int warns) { preferenceRepository.setUpdateWarningCount(warns); } - public int getUpdateAsks() { - return preferenceRepository.getUpdateAsksCount(); - } - - public void setUpdateAsksCount(int asks) { - preferenceRepository.setUpdateAsksCount(asks); - } - public void setInstallTime(int time) { preferenceRepository.setInstallTime(time); } @@ -606,7 +536,7 @@ public void tryToShowEmailPrompt(Context context, View successOverlay, Handler h emailPromptDialog.setCancelable(true); emailPromptDialog.setCanceledOnTouchOutside(true); emailPromptView.setParentDialog(emailPromptDialog); - BottomSheetBehavior behavior = BottomSheetBehavior.from((View) emailPromptView.getParent()); + BottomSheetBehavior behavior = BottomSheetBehavior.from((View) emailPromptView.getParent()); emailPromptDialog.setOnShowListener(dialog -> behavior.setPeekHeight(emailPromptView.getHeight())); emailPromptDialog.show(); } @@ -645,7 +575,7 @@ public void tryToShowWhatsNewDialog(Context context) { dialog.setContentView(view); dialog.setCancelable(true); dialog.setCanceledOnTouchOutside(true); - BottomSheetBehavior behavior = BottomSheetBehavior.from((View) view.getParent()); + BottomSheetBehavior behavior = BottomSheetBehavior.from((View) view.getParent()); dialog.setOnShowListener(d -> behavior.setPeekHeight(view.getHeight())); dialog.show(); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java index af79377672..2deefeb9c3 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java @@ -81,21 +81,6 @@ public void createNewWallet(Activity ctx, CreateWalletCallbackInterface createCa .isDisposed(); } - private String stripFilename(String name) - { - int index = name.lastIndexOf(".apk"); - if (index > 0) - { - name = name.substring(0, index); - } - index = name.lastIndexOf("-"); - if (index > 0) - { - name = name.substring(index+1); - } - return name; - } - public void StoreHDKey(String address, KeyService.AuthenticationLevel authLevel) { if (!address.equals(ZERO_ADDRESS)) From bf8f7ffa67705cc1dced27a51a7ddb41bf6761cf Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 25 Jul 2022 10:36:49 +0100 Subject: [PATCH 031/183] Bump gradle build number --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7d6f05a0a8..43ac51266d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,8 +56,8 @@ android { } } defaultConfig { - versionCode 199 - versionName "3.58.0" + versionCode 200 + versionName "3.58.1" applicationId "io.stormbird.wallet" minSdkVersion 23 From 3d0c78e03690ce9dbcffa173eac735a4e1912ee9 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 28 Jul 2022 20:04:18 +0800 Subject: [PATCH 032/183] 2248 ci no coverage report found (#2748) * Test upload coverage report to Codecov * Fix workflow syntax * Config Jacoco report, ignore slow test * Run specific flavor * Split e2e test out of CI job * Modify job name * Enable test * Update Codecov badge --- .github/workflows/ci.yml | 28 ++++++-------------------- .github/workflows/e2e.yml | 41 +++++++++++++++++++++++++++++++++++++++ README.md | 2 +- app/build.gradle | 16 +++++++++++++++ build.sh | 2 +- 5 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/e2e.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7040a3c6b..75f4dcba93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Test +name: Unit test on: push: branches: @@ -9,10 +9,6 @@ on: jobs: test: runs-on: macos-latest - strategy: - matrix: - api-level: [31] - target: [default] steps: - name: checkout uses: actions/checkout@v2 @@ -25,20 +21,8 @@ jobs: - name: Build the app run: sh ./build.sh - - name: Run e2e tests - uses: reactivecircus/android-emulator-runner@v2 - with: - api-level: ${{ matrix.api-level }} - target: ${{ matrix.target }} - arch: x86_64 - profile: Nexus 6 - ram-size: 4096M - sdcard-path-or-size: 4096M - script: ./e2e.sh --CI - - - name: Collect E2E tests results - if: ${{ failure() }} - uses: actions/upload-artifact@v1 - with: - name: e2e-tests-results - path: output/ \ No newline at end of file + - name: Upload coverage reports to Codecov + run: | + curl -Os https://uploader.codecov.io/latest/macos/codecov + chmod +x codecov + ./codecov \ No newline at end of file diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 0000000000..8cfb3449c2 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,41 @@ +name: E2e Test +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + test: + runs-on: macos-latest + strategy: + matrix: + api-level: [31] + target: [default] + steps: + - name: checkout + uses: actions/checkout@v2 + + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + + - name: Run tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + target: ${{ matrix.target }} + arch: x86_64 + profile: Nexus 6 + ram-size: 4096M + sdcard-path-or-size: 4096M + script: ./e2e.sh --CI + + - name: Collect tests results + if: ${{ failure() }} + uses: actions/upload-artifact@v1 + with: + name: e2e-tests-results + path: output/ \ No newline at end of file diff --git a/README.md b/README.md index 4b0811bb8f..ae8e2dccd8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg )](https://github.com/AlphaWallet/alpha-wallet-android/graphs/commit-activity) ![GitHub contributors](https://img.shields.io/github/contributors/AlphaWallet/alpha-wallet-android.svg) [![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/AlphaWallet/alpha-wallet-android/blob/master/LICENSE) -[![codecov](https://codecov.io/gh/AlphaWallet/alpha-wallet-android/branch/master/graph/badge.svg)](https://codecov.io/gh/AlphaWallet/alpha-wallet-android) +[![codecov](https://codecov.io/gh/AlphaWallet/alpha-wallet-android/branch/master/graph/badge.svg?token=IkoEb30CXq)](https://codecov.io/gh/AlphaWallet/alpha-wallet-android) AlphaWallet is an open source programmable blockchain apps platform. It's compatible with tokenisation framework TokenScript, offering businesses and their users in-depth token interaction, a clean white label user experience and advanced security options. Supports all Ethereum based networks. diff --git a/app/build.gradle b/app/build.gradle index 43ac51266d..40e912e40b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,6 +13,7 @@ buildscript { dependencies { classpath "gradle.plugin.com.worker8.android_lint_reporter:android_lint_reporter:2.1.0" classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.20.0-RC1" + classpath "com.dicedmelon.gradle:jacoco-android:0.1.5" } } @@ -25,6 +26,21 @@ apply plugin: 'kotlin-android' apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'com.worker8.android_lint_reporter' apply plugin: 'io.gitlab.arturbosch.detekt' +apply plugin: 'com.dicedmelon.gradle.jacoco-android' + +jacocoAndroidUnitTestReport { + csv.enabled false + html.enabled true + xml.enabled true +} + +jacocoAndroidUnitTestReport { + excludes += [ + '**/*Realm*.*', + '**/Generated*.*', + '**/*_*.*' + ] +} detekt { toolVersion = "1.20.0-RC1" diff --git a/build.sh b/build.sh index 28aedd2bdb..1311f9f95e 100644 --- a/build.sh +++ b/build.sh @@ -3,4 +3,4 @@ cd dmz && ../gradlew -i build && ../gradlew -i test && cd .. cd lib && ../gradlew -i build && ../gradlew -i test && cd .. cd util && ../gradlew -i build && ../gradlew -i test && cd .. -./gradlew build -x lint -x detekt \ No newline at end of file +./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt \ No newline at end of file From 61e48a9c81020181e2f53fe079c6d9c12cb2f22e Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 28 Jul 2022 20:04:55 +0800 Subject: [PATCH 033/183] Enable transfer test on API level 32 (#2677) * Enable transfer test on API level 32 * API 32 not supported by GitHub actions --- app/src/androidTest/java/com/alphawallet/app/TransferTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java index fd72e69fd4..2ab85376d7 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java @@ -30,7 +30,6 @@ public class TransferTest extends BaseE2ETest { }}; @Test - @Ignore public void should_transfer_from_an_account_to_another() { int apiLevel = Build.VERSION.SDK_INT; String[] array = WALLETS.get(String.valueOf(apiLevel)); From 34f9c6bcf55a44ec6c3b32755a514545b3218d90 Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 29 Jul 2022 11:20:54 +0100 Subject: [PATCH 034/183] Ignore failing test again --- app/src/androidTest/java/com/alphawallet/app/TransferTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java index 2ab85376d7..fd72e69fd4 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java @@ -30,6 +30,7 @@ public class TransferTest extends BaseE2ETest { }}; @Test + @Ignore public void should_transfer_from_an_account_to_another() { int apiLevel = Build.VERSION.SDK_INT; String[] array = WALLETS.get(String.valueOf(apiLevel)); From 137ad488de3e11523ebf5412d2f55e4c6771d3c8 Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 29 Jul 2022 13:42:41 +0100 Subject: [PATCH 035/183] Update EIP712 signing code (#2752) Add signing unit tests --- .../app/web3j/StructuredDataEncoder.java | 33 +- .../alphawallet/app/crypto/SigningTest.java | 494 ++++++++++++++++++ .../resources/0xProtocolControlSample.json | 43 ++ .../InvalidIdentifierStructuredData.json | 37 ++ ...tPerfectArrayButDeclaredArrayInSchema.json | 46 ++ .../InvalidMessageInvalidABIType.json | 37 ++ ...equalArrayLengthsBetweenSchemaAndData.json | 37 ++ ...nvalidMessageValidABITypeInvalidValue.json | 37 ++ .../InvalidMessageValueTypeMismatch.json | 37 ++ .../resources/InvalidTypeStructuredData.json | 37 ++ .../crypto/resources/ValidOpenSeaData.json | 162 ++++++ .../resources/ValidStructuredArrayData.json | 99 ++++ .../crypto/resources/ValidStructuredData.json | 37 ++ .../ValidStructuredDataWithArrays.json | 88 ++++ .../ValidStructuredDataWithBytesTypes.json | 43 ++ .../ValidStructuredDataWithSalt.json | 39 ++ .../ValidStructuredDataWithValues.json | 95 ++++ .../resources/ValidStructuredGnosisData.json | 68 +++ 18 files changed, 1464 insertions(+), 5 deletions(-) create mode 100644 app/src/test/java/com/alphawallet/app/crypto/SigningTest.java create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/0xProtocolControlSample.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/InvalidIdentifierStructuredData.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageDataNotPerfectArrayButDeclaredArrayInSchema.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageInvalidABIType.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageUnequalArrayLengthsBetweenSchemaAndData.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageValidABITypeInvalidValue.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageValueTypeMismatch.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/InvalidTypeStructuredData.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/ValidOpenSeaData.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredArrayData.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredData.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithArrays.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithBytesTypes.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithSalt.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithValues.json create mode 100644 app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredGnosisData.json diff --git a/app/src/main/java/com/alphawallet/app/web3j/StructuredDataEncoder.java b/app/src/main/java/com/alphawallet/app/web3j/StructuredDataEncoder.java index 1ea36ddbd5..3c6148f2f8 100644 --- a/app/src/main/java/com/alphawallet/app/web3j/StructuredDataEncoder.java +++ b/app/src/main/java/com/alphawallet/app/web3j/StructuredDataEncoder.java @@ -37,6 +37,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.web3j.abi.datatypes.Type.MAX_BYTE_LENGTH; import static org.web3j.crypto.Hash.sha3; import static org.web3j.crypto.Hash.sha3String; @@ -93,14 +94,20 @@ public Set getDependencies(String primaryType) { remainingTypes.remove(remainingTypes.size() - 1); deps.add(structName); - for (StructuredData.Entry entry : types.get(primaryType)) { - if (!types.containsKey(entry.getType())) { + for (StructuredData.Entry entry : types.get(structName)) { + String declarationFieldTypeName = entry.getType(); + String baseDeclarationTypeName = + arrayTypePattern.matcher(declarationFieldTypeName).find() + ? declarationFieldTypeName.substring( + 0, declarationFieldTypeName.indexOf('[')) + : declarationFieldTypeName; + if (!types.containsKey(baseDeclarationTypeName)) { // Don't expand on non-user defined types - } else if (deps.contains(entry.getType())) { + } else if (deps.contains(baseDeclarationTypeName)) { // Skip types which are already expanded } else { // Encountered a user defined type - remainingTypes.add(entry.getType()); + remainingTypes.add(baseDeclarationTypeName); } } } @@ -233,7 +240,23 @@ private byte[] convertToEncodedItem(String baseType, Object data) { try { if (baseType.toLowerCase().startsWith("uint") || baseType.toLowerCase().startsWith("int")) { - hashBytes = convertToBigInt(data).toByteArray(); + BigInteger value = convertToBigInt(data); + if (value.signum() >= 0) { + hashBytes = Numeric.toBytesPadded(convertToBigInt(data), MAX_BYTE_LENGTH); + } else { + byte signPadding = (byte) 0xff; + byte[] rawValue = convertToBigInt(data).toByteArray(); + hashBytes = new byte[MAX_BYTE_LENGTH]; + for (int i = 0; i < hashBytes.length; i++) { + hashBytes[i] = signPadding; + } + System.arraycopy( + rawValue, + 0, + hashBytes, + MAX_BYTE_LENGTH - rawValue.length, + rawValue.length); + } } else if (baseType.equals("string")) { hashBytes = ((String) data).getBytes(); } else if (baseType.equals("bytes")) { diff --git a/app/src/test/java/com/alphawallet/app/crypto/SigningTest.java b/app/src/test/java/com/alphawallet/app/crypto/SigningTest.java new file mode 100644 index 0000000000..86ee2c1278 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/SigningTest.java @@ -0,0 +1,494 @@ +package com.alphawallet.app.crypto; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import com.alphawallet.app.web3j.StructuredDataEncoder; +import com.alphawallet.token.tools.Numeric; + +import org.junit.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class SigningTest +{ + private static String jsonMessageString; + private static final String filePath = "src/test/java/com/alphawallet/app/crypto/resources/"; + + public SigningTest() + { + String validStructuredDataJSONFilePath = filePath + + "ValidStructuredData.json"; + try + { + jsonMessageString = getResource(validStructuredDataJSONFilePath); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + private String getResource(String jsonFile) throws IOException { + return new String( + Files.readAllBytes(Paths.get(jsonFile).toAbsolutePath()), StandardCharsets.UTF_8); + } + + @Test + public void testInvalidIdentifierMessageCaughtByRegex() throws RuntimeException { + String invalidStructuredDataJSONFilePath = + filePath + + "InvalidIdentifierStructuredData.json"; + assertThrows( + RuntimeException.class, + () -> new StructuredDataEncoder(getResource(invalidStructuredDataJSONFilePath))); + } + + @Test + public void testInvalidTypeMessageCaughtByRegex() throws RuntimeException { + String invalidStructuredDataJSONFilePath = + filePath + + "InvalidTypeStructuredData.json"; + assertThrows( + RuntimeException.class, + () -> new StructuredDataEncoder(getResource(invalidStructuredDataJSONFilePath))); + } + + @Test + public void testGetDependencies() throws IOException, RuntimeException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + Set deps = + dataEncoder.getDependencies(dataEncoder.jsonMessageObject.getPrimaryType()); + + Set depsExpected = new HashSet<>(); + depsExpected.add("Mail"); + depsExpected.add("Person"); + + assertEquals(deps, depsExpected); + } + + @Test + public void testEncodeType() throws IOException, RuntimeException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + String expectedTypeEncoding = + "Mail(Person from,Person to,string contents)" + + "Person(string name,address wallet)"; + + assertEquals( + dataEncoder.encodeType(dataEncoder.jsonMessageObject.getPrimaryType()), + expectedTypeEncoding); + } + + @Test + public void testTypeHash() throws IOException, RuntimeException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + String expectedTypeHashHex = + "0xa0cedeb2dc280ba39b857546d74f5549c" + "3a1d7bdc2dd96bf881f76108e23dac2"; + + assertEquals( + Numeric.toHexString( + dataEncoder.typeHash(dataEncoder.jsonMessageObject.getPrimaryType())), + expectedTypeHashHex); + } + + @SuppressWarnings("unchecked") + @Test + public void testEncodeData() throws RuntimeException, IOException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + byte[] encodedData = + dataEncoder.encodeData( + dataEncoder.jsonMessageObject.getPrimaryType(), + (HashMap) dataEncoder.jsonMessageObject.getMessage()); + String expectedDataEncodingHex = + "0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bd" + + "c2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6" + + "604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8" + + "ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae57027" + + "01d05cd2305f7c52a2fc8"; + + assertEquals(Numeric.toHexString(encodedData), expectedDataEncodingHex); + } + + @SuppressWarnings("unchecked") + @Test + public void testHashData() throws RuntimeException, IOException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + byte[] dataHash = + dataEncoder.hashMessage( + dataEncoder.jsonMessageObject.getPrimaryType(), + (HashMap) dataEncoder.jsonMessageObject.getMessage()); + String expectedMessageStructHash = + "0xc52c0ee5d84264471806290a3f2c4cecf" + "c5490626bf912d01f240d7a274b371e"; + + assertEquals(Numeric.toHexString(dataHash), expectedMessageStructHash); + } + + @Test + public void testHashDomain() throws RuntimeException, IOException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + byte[] structHashDomain = dataEncoder.hashDomain(); + String expectedDomainStructHash = + "0xf2cee375fa42b42143804025fc449deafd" + "50cc031ca257e0b194a650a912090f"; + + assertEquals(Numeric.toHexString(structHashDomain), expectedDomainStructHash); + } + + @Test + public void testHashStructuredMessage() throws RuntimeException, IOException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + byte[] hashStructuredMessage = dataEncoder.hashStructuredData(); + String expectedDomainStructHash = + "0xbe609aee343fb3c4b28e1df9e632fca64fcfaede20" + "f02e86244efddf30957bd2"; + + assertEquals(Numeric.toHexString(hashStructuredMessage), expectedDomainStructHash); + } + + @Test + public void testBytesAndBytes32Encoding() throws IOException { + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder( + getResource( + filePath + + "ValidStructuredDataWithBytesTypes.json")); + dataEncoder.hashStructuredData(); + } + + @Test + public void test0xProtocolControlSample() throws IOException { + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder( + getResource( + filePath + + "0xProtocolControlSample.json")); + assertEquals( + "0xccb29124860915763e8cd9257da1260abc7df668fde282272587d84b594f37f6", + Numeric.toHexString(dataEncoder.hashStructuredData())); + } + + @Test + public void testInvalidMessageValueTypeMismatch() throws RuntimeException, IOException { + String invalidStructuredDataJSONFilePath = + filePath + + "InvalidMessageValueTypeMismatch.json"; + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder(getResource(invalidStructuredDataJSONFilePath)); + assertThrows(ClassCastException.class, dataEncoder::hashStructuredData); + } + + @Test + public void testInvalidMessageInvalidABIType() throws RuntimeException, IOException { + String invalidStructuredDataJSONFilePath = + filePath + + "InvalidMessageInvalidABIType.json"; + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder(getResource(invalidStructuredDataJSONFilePath)); + assertThrows(UnsupportedOperationException.class, dataEncoder::hashStructuredData); + } + + @Test + public void testInvalidMessageValidABITypeInvalidValue() throws RuntimeException, IOException { + String invalidStructuredDataJSONFilePath = + filePath + + "InvalidMessageValidABITypeInvalidValue.json"; + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder(getResource(invalidStructuredDataJSONFilePath)); + assertThrows(RuntimeException.class, dataEncoder::hashStructuredData); + } + + // EIP712 v3 + @Test + public void testValidStructureWithValues() throws IOException { + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder( + getResource( + filePath + + "ValidStructuredDataWithValues.json")); + + assertEquals( + "0x9a321bee2df12b3b43bc4caf71d19839f05d82264b780b48f1f529bf916b5d30", + Numeric.toHexString(dataEncoder.hashStructuredData())); + } + + // EIP712 v4 + @Test + public void testEncodeTypeWithArrays() throws IOException { + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder( + getResource( + filePath + + "ValidStructuredDataWithArrays.json")); // taken from https://danfinlay.github.io/js-eth-personal-sign-examples/ and updated to int,uint arrays + String expectedMailType = + "Mail(Person from,Group[] to,string contents)" + + "Group(string name,Person[] members)" + + "Person(string name,address[] wallets)"; + + assertEquals(dataEncoder.encodeType("Mail"), expectedMailType); + + String expectedGroupType = + "Group(string name,Person[] members)" + "Person(string name,address[] wallets)"; + + assertEquals(dataEncoder.encodeType("Group"), expectedGroupType); + } + + // EIP712 v4 + @Test + public void testValidStructureWithArrays() throws IOException { + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder( + getResource( + filePath + + "ValidStructuredArrayData.json")); // taken from https://danfinlay.github.io/js-eth-personal-sign-examples/ and updated to int,uint arrays + + byte[] dataHash = + dataEncoder.hashMessage( + dataEncoder.jsonMessageObject.getPrimaryType(), + (HashMap) dataEncoder.jsonMessageObject.getMessage()); + + String expectedMessageStructHash = + "0xc1c7d7b7dab9a65b30a6e951923b2d54536778329712e2239ed8a3f2f5f2329f"; + + assertEquals(expectedMessageStructHash, Numeric.toHexString(dataHash)); + + assertEquals( + "0x935426a6009a3798ee87cd16ebeb9cea26b29d2d3762ac0951166d032f55d522", + Numeric.toHexString(dataEncoder.hashStructuredData())); + } + + // EIP712 v3 Gnosis format; Multisig Structured message with addresses blanked + @Test + public void testValidGnosisStructure() throws IOException { + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder( + getResource( + filePath + + "ValidStructuredGnosisData.json")); // typical Gnosis safe EIP712 data + + assertEquals( + "0xb3ffe0073b0c3aecb00b19a636e4b3820cfc9692189f874312c906f70edf10bd", + Numeric.toHexString(dataEncoder.hashStructuredData())); + } + + @Test + public void testGetArrayDimensionsFromData() throws RuntimeException, IOException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + // [[1, 2, 3], [4, 5, 6]] + List testArrayData1 = new ArrayList<>(); + testArrayData1.add(new ArrayList<>(Arrays.asList("1", "2", "3"))); + testArrayData1.add(new ArrayList<>(Arrays.asList("4", "5", "6"))); + List expectedDimensions1 = + new ArrayList() { + { + add(2); + add(3); + } + }; + assertEquals(dataEncoder.getArrayDimensionsFromData(testArrayData1), expectedDimensions1); + + // [[1, 2, 3]] + List testArrayData2 = new ArrayList<>(); + testArrayData2.add(new ArrayList<>(Arrays.asList("1", "2", "3"))); + List expectedDimensions2 = + new ArrayList() { + { + add(1); + add(3); + } + }; + assertEquals(dataEncoder.getArrayDimensionsFromData(testArrayData2), expectedDimensions2); + + // [1, 2, 3] + List testArrayData3 = + new ArrayList() { + { + add("1"); + add("2"); + add("3"); + } + }; + List expectedDimensions3 = + new ArrayList() { + { + add(3); + } + }; + assertEquals(dataEncoder.getArrayDimensionsFromData(testArrayData3), expectedDimensions3); + + // [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]] + List testArrayData4 = new ArrayList<>(); + testArrayData4.add( + new ArrayList() { + { + add(new ArrayList<>(Arrays.asList("1", "2"))); + add(new ArrayList<>(Arrays.asList("3", "4"))); + add(new ArrayList<>(Arrays.asList("5", "6"))); + } + }); + testArrayData4.add( + new ArrayList() { + { + add(new ArrayList<>(Arrays.asList("7", "8"))); + add(new ArrayList<>(Arrays.asList("9", "10"))); + add(new ArrayList<>(Arrays.asList("11", "12"))); + } + }); + List expectedDimensions4 = + new ArrayList() { + { + add(2); + add(3); + add(2); + } + }; + assertEquals(dataEncoder.getArrayDimensionsFromData(testArrayData4), expectedDimensions4); + } + + @Test + public void testFlattenMultidimensionalArray() throws IOException, RuntimeException { + StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); + // [[1, 2, 3], [4, 5, 6]] + List testArrayData1 = new ArrayList<>(); + testArrayData1.add(new ArrayList<>(Arrays.asList(1, 2, 3))); + testArrayData1.add(new ArrayList<>(Arrays.asList(4, 5, 6))); + List expectedFlatArray1 = + new ArrayList() { + { + add(1); + add(2); + add(3); + add(4); + add(5); + add(6); + } + }; + assertEquals(dataEncoder.flattenMultidimensionalArray(testArrayData1), expectedFlatArray1); + + // [[1, 2, 3]] + List testArrayData2 = new ArrayList<>(); + testArrayData2.add(new ArrayList<>(Arrays.asList(1, 2, 3))); + List expectedFlatArray2 = + new ArrayList() { + { + add(1); + add(2); + add(3); + } + }; + assertEquals(dataEncoder.flattenMultidimensionalArray(testArrayData2), expectedFlatArray2); + + // [1, 2, 3] + List testArrayData3 = + new ArrayList() { + { + add(1); + add(2); + add(3); + } + }; + List expectedFlatArray3 = + new ArrayList() { + { + add(1); + add(2); + add(3); + } + }; + assertEquals(dataEncoder.flattenMultidimensionalArray(testArrayData3), expectedFlatArray3); + + // [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]] + List testArrayData4 = new ArrayList<>(); + testArrayData4.add( + new ArrayList() { + { + add(new ArrayList<>(Arrays.asList(1, 2))); + add(new ArrayList<>(Arrays.asList(3, 4))); + add(new ArrayList<>(Arrays.asList(5, 6))); + } + }); + testArrayData4.add( + new ArrayList() { + { + add(new ArrayList<>(Arrays.asList(7, 8))); + add(new ArrayList<>(Arrays.asList(9, 10))); + add(new ArrayList<>(Arrays.asList(11, 12))); + } + }); + List expectedFlatArray4 = + new ArrayList() { + { + add(1); + add(2); + add(3); + add(4); + add(5); + add(6); + add(7); + add(8); + add(9); + add(10); + add(11); + add(12); + } + }; + assertEquals(dataEncoder.flattenMultidimensionalArray(testArrayData4), expectedFlatArray4); + } + + @Test + public void testUnequalArrayLengthsBetweenSchemaAndData() throws RuntimeException, IOException { + String invalidStructuredDataJSONFilePath = + filePath + + "" + + "InvalidMessageUnequalArrayLengthsBetweenSchemaAndData.json"; + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder(getResource(invalidStructuredDataJSONFilePath)); + assertThrows(RuntimeException.class, dataEncoder::hashStructuredData); + } + + @Test + public void testDataNotPerfectArrayButDeclaredArrayInSchema() + throws RuntimeException, IOException { + String invalidStructuredDataJSONFilePath = + filePath + + "" + + "InvalidMessageDataNotPerfectArrayButDeclaredArrayInSchema.json"; + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder(getResource(invalidStructuredDataJSONFilePath)); + assertThrows(RuntimeException.class, dataEncoder::hashStructuredData); + } + + @Test + public void testHashDomainWithSalt() throws RuntimeException, IOException { + String validStructuredDataWithSaltJSONFilePath = + filePath + + "" + + "ValidStructuredDataWithSalt.json"; + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder(getResource(validStructuredDataWithSaltJSONFilePath)); + byte[] structHashDomain = dataEncoder.hashDomain(); + String expectedDomainStructHash = + "0xbae4f6f7b9bfdfda060692099b0e1ccecd25d62b7c92cc9f3b907f33178b81e3"; + + assertEquals(Numeric.toHexString(structHashDomain), expectedDomainStructHash); + } + + @Test + public void testValidOpenSeaStructure() throws IOException { + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder( + getResource( + filePath + + "ValidOpenSeaData.json")); // typical Opensea EIP712 + + assertEquals( + "0x29b841e181acce185370a929f69f61d7f2accba3c5579c020b0e8584e2ccd314", + Numeric.toHexString(dataEncoder.hashStructuredData())); + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/0xProtocolControlSample.json b/app/src/test/java/com/alphawallet/app/crypto/resources/0xProtocolControlSample.json new file mode 100644 index 0000000000..ef3dac1165 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/0xProtocolControlSample.json @@ -0,0 +1,43 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "verifyingContract", "type": "address"} + ], + "Order": [ + { "name": "makerAddress", "type": "address" }, + { "name": "takerAddress", "type": "address" }, + { "name": "feeRecipientAddress", "type": "address" }, + { "name": "senderAddress", "type": "address" }, + { "name": "makerAssetAmount", "type": "uint256" }, + { "name": "takerAssetAmount", "type": "uint256" }, + { "name": "makerFee", "type": "uint256" }, + { "name": "takerFee", "type": "uint256" }, + { "name": "expirationTimeSeconds", "type": "uint256" }, + { "name": "salt", "type": "uint256" }, + { "name": "makerAssetData", "type": "bytes" }, + { "name": "takerAssetData", "type": "bytes" } + ] + }, + "primaryType": "Order", + "domain": { + "name": "0x Protocol", + "version": "2", + "verifyingContract": "0x12459c951127e0c374ff9105dda097662a027093" + }, + "message": { + "makerAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b", + "takerAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32", + "feeRecipientAddress": "0xb046140686d052fff581f63f8136cce132e857da", + "senderAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32", + "makerAssetAmount": 10000000000000000, + "takerAssetAmount": 20000000000000000, + "makerFee": 100000000000000, + "takerFee": 200000000000000, + "expirationTimeSeconds": 1532560590, + "salt": 1532559225, + "makerAssetData": "0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498", + "takerAssetData": "0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063" + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidIdentifierStructuredData.json b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidIdentifierStructuredData.json new file mode 100644 index 0000000000..04807153f0 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidIdentifierStructuredData.json @@ -0,0 +1,37 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "hello wallet", "type": "address"} + ], + "Mail": [ + {"name": "from", "type": "Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageDataNotPerfectArrayButDeclaredArrayInSchema.json b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageDataNotPerfectArrayButDeclaredArrayInSchema.json new file mode 100644 index 0000000000..53a984b986 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageDataNotPerfectArrayButDeclaredArrayInSchema.json @@ -0,0 +1,46 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "person": [ + {"name": "name", "type": "string"}, + {"name": "wallet", "type": "address"} + ], + "Mail": [ + {"name": "from", "type": "person"}, + {"name": "to", "type": "person[2][3]"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": [{ + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, [ + { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + } + ]], + "contents": "Hello, Bob!" + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageInvalidABIType.json b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageInvalidABIType.json new file mode 100644 index 0000000000..d7df106d6c --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageInvalidABIType.json @@ -0,0 +1,37 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "balance", "type": "uint25689"} + ], + "Mail": [ + {"name": "from", "type": "Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "balance": 123 + }, + "to": { + "name": "Bob", + "balance": 1234 + }, + "contents": "Hello Bob!" + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageUnequalArrayLengthsBetweenSchemaAndData.json b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageUnequalArrayLengthsBetweenSchemaAndData.json new file mode 100644 index 0000000000..51b968df46 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageUnequalArrayLengthsBetweenSchemaAndData.json @@ -0,0 +1,37 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "person": [ + {"name": "name", "type": "string"}, + {"name": "wallet", "type": "address"} + ], + "Mail": [ + {"name": "from", "type": "person"}, + {"name": "to", "type": "person[2]"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": [{ + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }], + "contents": "Hello, Bob!" + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageValidABITypeInvalidValue.json b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageValidABITypeInvalidValue.json new file mode 100644 index 0000000000..e265185611 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageValidABITypeInvalidValue.json @@ -0,0 +1,37 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "balance", "type": "uint256"} + ], + "Mail": [ + {"name": "from", "type": "Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "balance": 1234 + }, + "to": { + "name": "Bob", + "balance": "how do you do?" + }, + "contents": "Hello Bob!" + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageValueTypeMismatch.json b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageValueTypeMismatch.json new file mode 100644 index 0000000000..e260bb565d --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidMessageValueTypeMismatch.json @@ -0,0 +1,37 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "wallet", "type": "address"} + ], + "Mail": [ + {"name": "from", "type": "Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": 12345 + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidTypeStructuredData.json b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidTypeStructuredData.json new file mode 100644 index 0000000000..023d6c9b58 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/InvalidTypeStructuredData.json @@ -0,0 +1,37 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "wallet", "type": "address"} + ], + "Mail": [ + {"name": "from", "type": "Hello Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/ValidOpenSeaData.json b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidOpenSeaData.json new file mode 100644 index 0000000000..e6015946fa --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidOpenSeaData.json @@ -0,0 +1,162 @@ +{ + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "OrderComponents": [ + { + "name": "offerer", + "type": "address" + }, + { + "name": "zone", + "type": "address" + }, + { + "name": "offer", + "type": "OfferItem[]" + }, + { + "name": "consideration", + "type": "ConsiderationItem[]" + }, + { + "name": "orderType", + "type": "uint8" + }, + { + "name": "startTime", + "type": "uint256" + }, + { + "name": "endTime", + "type": "uint256" + }, + { + "name": "zoneHash", + "type": "bytes32" + }, + { + "name": "salt", + "type": "uint256" + }, + { + "name": "conduitKey", + "type": "bytes32" + }, + { + "name": "counter", + "type": "uint256" + } + ], + "OfferItem": [ + { + "name": "itemType", + "type": "uint8" + }, + { + "name": "token", + "type": "address" + }, + { + "name": "identifierOrCriteria", + "type": "uint256" + }, + { + "name": "startAmount", + "type": "uint256" + }, + { + "name": "endAmount", + "type": "uint256" + } + ], + "ConsiderationItem": [ + { + "name": "itemType", + "type": "uint8" + }, + { + "name": "token", + "type": "address" + }, + { + "name": "identifierOrCriteria", + "type": "uint256" + }, + { + "name": "startAmount", + "type": "uint256" + }, + { + "name": "endAmount", + "type": "uint256" + }, + { + "name": "recipient", + "type": "address" + } + ] + }, + "primaryType": "OrderComponents", + "domain": { + "name": "Seaport", + "version": "1.1", + "chainId": "4", + "verifyingContract": "0x00000000006c3852cbEf3e08E8dF289169EdE581" + }, + "message": { + "offerer": "0xA20efc4B9537d27acfD052003e311f762620642D", + "offer": [ + { + "itemType": "3", + "token": "0xA604060890923Ff400e8c6f5290461A83AEDACec", + "identifierOrCriteria": "73301158607185938929634570134102981044984305286916549900884904068322431074305", + "startAmount": "1", + "endAmount": "1" + } + ], + "consideration": [ + { + "itemType": "0", + "token": "0x0000000000000000000000000000000000000000", + "identifierOrCriteria": "0", + "startAmount": "185250000000000000", + "endAmount": "185250000000000000", + "recipient": "0xA20efc4B9537d27acfD052003e311f762620642D" + }, + { + "itemType": "0", + "token": "0x0000000000000000000000000000000000000000", + "identifierOrCriteria": "0", + "startAmount": "4750000000000000", + "endAmount": "4750000000000000", + "recipient": "0x8De9C5A032463C561423387a9648c5C7BCC5BC90" + } + ], + "startTime": "1659082330", + "endTime": "1661760730", + "orderType": "3", + "zone": "0x00000000E88FE2628EbC5DA81d2b3CeaD633E89e", + "zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "salt": "41661045164664183", + "conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000", + "totalOriginalConsiderationItems": "2", + "counter": "0" + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredArrayData.json b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredArrayData.json new file mode 100644 index 0000000000..9a26e79ad4 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredArrayData.json @@ -0,0 +1,99 @@ +{ + "domain": { + "chainId": 1, + "name": "Ether Mail", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + "version": "1" + }, + "message": { + "contents": "Hello, Bob!", + "from": { + "name": "Cow", + "wallets": [ + "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF" + ], + "balances": [ + 195, + -25 + ], + "ids": [ + 1, + 2 + ] + }, + "to": [ + { + "name": "Bob", + "wallets": [ + "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", + "0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57", + "0xB0B0b0b0b0b0B000000000000000000000000000" + ], + "balances": [ + 200, + 150000, + -300 + ], + "ids": [ + 0, + 3, + 7 + ] + } + ] + }, + "primaryType": "Mail", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Mail": [ + { + "name": "from", + "type": "Person" + }, + { + "name": "to", + "type": "Person[]" + }, + { + "name": "contents", + "type": "string" + } + ], + "Person": [ + { + "name": "name", + "type": "string" + }, + { + "name": "wallets", + "type": "address[]" + }, + { + "name": "balances", + "type": "int256[]" + }, + { + "name": "ids", + "type": "uint16[]" + } + ] + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredData.json b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredData.json new file mode 100644 index 0000000000..84fecddfa5 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredData.json @@ -0,0 +1,37 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "wallet", "type": "address"} + ], + "Mail": [ + {"name": "from", "type": "Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithArrays.json b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithArrays.json new file mode 100644 index 0000000000..a1a921ef2a --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithArrays.json @@ -0,0 +1,88 @@ +{ + "domain": { + "chainId": 1, + "name": "Ether Mail", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + "version": "1" + }, + "message": { + "contents": "Hello, Bob!", + "from": { + "name": "Cow", + "wallets": [ + "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF" + ] + }, + "to": [ + { + "name": "Group A", + "members": [ + { + "name": "Bob", + "wallets": [ + "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", + "0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57", + "0xB0B0b0b0b0b0B000000000000000000000000000" + ] + } + ] + } + ] + }, + "primaryType": "Mail", + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Group": [ + { + "name": "name", + "type": "string" + }, + { + "name": "members", + "type": "Person[]" + } + ], + "Mail": [ + { + "name": "from", + "type": "Person" + }, + { + "name": "to", + "type": "Group[]" + }, + { + "name": "contents", + "type": "string" + } + ], + "Person": [ + { + "name": "name", + "type": "string" + }, + { + "name": "wallets", + "type": "address[]" + } + ] + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithBytesTypes.json b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithBytesTypes.json new file mode 100644 index 0000000000..b6b40d5a3a --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithBytesTypes.json @@ -0,0 +1,43 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "wallet", "type": "address"}, + {"name": "personInfo", "type": "bytes"}, + {"name": "personData", "type": "bytes3"} + ], + "Mail": [ + {"name": "from", "type": "Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + "personInfo": "0xABCD01234", + "personData": "0x12345" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", + "personInfo": "0x01234ABCD", + "personData": "0x54321" + }, + "contents": "Hello, Bob!" + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithSalt.json b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithSalt.json new file mode 100644 index 0000000000..1a69d5c48e --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithSalt.json @@ -0,0 +1,39 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"}, + {"name": "salt", "type": "bytes32"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "wallet", "type": "address"} + ], + "Mail": [ + {"name": "from", "type": "Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + "salt": "0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + } +} diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithValues.json b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithValues.json new file mode 100644 index 0000000000..a629f19940 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredDataWithValues.json @@ -0,0 +1,95 @@ +{ + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "RelayRequest": [ + { + "name": "target", + "type": "address" + }, + { + "name": "encodedFunction", + "type": "bytes" + }, + { + "name": "gasData", + "type": "GasData" + }, + { + "name": "relayData", + "type": "RelayData" + } + ], + "GasData": [ + { + "name": "gasLimit", + "type": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256" + }, + { + "name": "pctRelayFee", + "type": "uint256" + }, + { + "name": "baseRelayFee", + "type": "uint256" + } + ], + "RelayData": [ + { + "name": "senderAddress", + "type": "address" + }, + { + "name": "senderNonce", + "type": "uint256" + }, + { + "name": "relayWorker", + "type": "address" + }, + { + "name": "paymaster", + "type": "address" + } + ] + }, + "domain": { + "name": "Test Relayed Transaction", + "version": "1", + "chainId": 42, + "verifyingContract": "0x1234567890aBcDeF1234567890aBcDeF12345678" + }, + "primaryType": "RelayRequest", + "message": { + "target": "0x1234567890aBcDeF1234567890aBcDeF12345678", + "encodedFunction": "0xa9059cbb0000000000000000000000002e0d94754b348d208d64d52d78bcd443afa9fa520000000000000000000000000000000000000000000000000000000000000007", + "gasData": { + "gasLimit": "39507", + "gasPrice": "1700000000", + "pctRelayFee": "70", + "baseRelayFee": "0" + }, + "relayData": { + "senderAddress": "0x1234567890aBcDeF1234567890aBcDeF12345678", + "senderNonce": "3", + "relayWorker": "0x1234567890aBcDeF1234567890aBcDeF12345678", + "paymaster": "0x1234567890aBcDeF1234567890aBcDeF12345678" + } + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredGnosisData.json b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredGnosisData.json new file mode 100644 index 0000000000..4b2d8ecbdc --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/crypto/resources/ValidStructuredGnosisData.json @@ -0,0 +1,68 @@ +{ + "types": { + "EIP712Domain": [ + { + "type": "address", + "name": "verifyingContract" + } + ], + "SafeTx": [ + { + "type": "address", + "name": "to" + }, + { + "type": "uint256", + "name": "value" + }, + { + "type": "bytes", + "name": "data" + }, + { + "type": "uint8", + "name": "operation" + }, + { + "type": "uint256", + "name": "safeTxGas" + }, + { + "type": "uint256", + "name": "baseGas" + }, + { + "type": "uint256", + "name": "gasPrice" + }, + { + "type": "address", + "name": "gasToken" + }, + { + "type": "address", + "name": "refundReceiver" + }, + { + "type": "uint256", + "name": "nonce" + } + ] + }, + "domain": { + "verifyingContract": "0x0000000000000000000000000000000000000123" + }, + "primaryType": "SafeTx", + "message": { + "to": "0x0000000000000000000000000000000000000123", + "value": "0", + "data": "0x1cff79cd00000000000000000000000000000000000000000000000000000000000001234", + "operation": 0, + "safeTxGas": 222496, + "baseGas": 0, + "gasPrice": "0", + "gasToken": "0x0000000000000000000000000000000000000000", + "refundReceiver": "0x0000000000000000000000000000000000000000", + "nonce": 28 + } +} \ No newline at end of file From 4e4f8d65e12bd51137d82bb256b535f52c958820 Mon Sep 17 00:00:00 2001 From: justindg Date: Fri, 29 Jul 2022 09:18:13 -0700 Subject: [PATCH 036/183] Show WalletConnect Signed Transaction Count (#2750) * Display tx count in WC activity * Update wc signed transaction detail layout * Small improvement to transaction detail formatting * Set initial count to zero * Update UI after transaction * Slight refactor --- .../app/ui/SignDetailActivity.java | 42 +++++++-------- .../app/ui/WalletConnectActivity.java | 53 ++++++++++++++----- .../app/web3/entity/Web3Transaction.java | 26 ++++----- .../res/layout/activity_wallet_connect.xml | 31 +++++++++++ .../main/res/layout/item_sign_instance.xml | 30 +++-------- 5 files changed, 110 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/SignDetailActivity.java b/app/src/main/java/com/alphawallet/app/ui/SignDetailActivity.java index d9906f1d85..4cc38733bb 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SignDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SignDetailActivity.java @@ -13,12 +13,10 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.repository.SignRecord; -import com.alphawallet.app.util.LocaleUtils; import com.alphawallet.app.util.Utils; +import com.alphawallet.app.widget.StandardHeader; -import java.text.DateFormat; import java.util.ArrayList; -import java.util.Date; import dagger.hilt.android.AndroidEntryPoint; @@ -41,7 +39,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) setTitle(getString(R.string.signed_transactions)); signRecords = getIntent().getParcelableArrayListExtra(C.EXTRA_STATE); - if (signRecords != null) { + if (signRecords != null) + { recyclerView = findViewById(R.id.list); recyclerView.setLayoutManager(new LinearLayoutManager(this)); adapter = new CustomAdapter(); @@ -60,28 +59,14 @@ public CustomAdapter.CustomViewHolder onCreateViewHolder(ViewGroup parent, int v return new CustomAdapter.CustomViewHolder(itemView); } - class CustomViewHolder extends RecyclerView.ViewHolder - { - TextView date; - TextView type; - TextView detail; - - CustomViewHolder(View view) - { - super(view); - date = view.findViewById(R.id.date); - type = view.findViewById(R.id.sign_type); - detail = view.findViewById(R.id.details); - } - } - @Override public void onBindViewHolder(CustomAdapter.CustomViewHolder holder, int position) { SignRecord record = signRecords.get(position); - - holder.date.setText(Utils.localiseUnixTime(getApplicationContext(), record.date/1000)); - holder.type.setText(record.type); + holder.date.setText(record.type + + " (" + + Utils.localiseUnixTime(getApplicationContext(), record.date / 1000) + + ")"); holder.detail.setText(record.message); } @@ -90,5 +75,18 @@ public int getItemCount() { return signRecords.size(); } + + class CustomViewHolder extends RecyclerView.ViewHolder + { + StandardHeader date; + TextView detail; + + CustomViewHolder(View view) + { + super(view); + date = view.findViewById(R.id.date); + detail = view.findViewById(R.id.details); + } + } } } diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java index ded1116977..1c6244e40e 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java @@ -40,6 +40,7 @@ import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.walletconnect.WCRequest; import com.alphawallet.app.repository.EthereumNetworkBase; +import com.alphawallet.app.repository.SignRecord; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.viewmodel.WalletConnectViewModel; import com.alphawallet.app.walletconnect.WCClient; @@ -64,27 +65,24 @@ import com.alphawallet.token.entity.Signable; import com.bumptech.glide.Glide; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import org.jetbrains.annotations.NotNull; import org.web3j.utils.Numeric; import java.math.BigDecimal; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.UUID; -import java.util.concurrent.TimeUnit; import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import kotlin.Unit; -import okhttp3.OkHttpClient; import timber.log.Timber; @AndroidEntryPoint -public class WalletConnectActivity extends BaseActivity implements ActionSheetCallback, StandardFunctionInterface, WalletConnectCallback { +public class WalletConnectActivity extends BaseActivity implements ActionSheetCallback, StandardFunctionInterface, WalletConnectCallback +{ public static final String WC_LOCAL_PREFIX = "wclocal:"; public static final String WC_INTENT = "wcintent:"; private static final String TAG = "WCClient"; @@ -92,6 +90,7 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa private static final long CONNECT_TIMEOUT = 10 * DateUtils.SECOND_IN_MILLIS; // 10 Seconds timeout private final Handler handler = new Handler(Looper.getMainLooper()); private final LocalBroadcastManager broadcastManager; + private final long switchChainDialogCallbackId = 1; WalletConnectViewModel viewModel; private WCClient client; private WCSession session; @@ -101,7 +100,6 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa ActivityResultLauncher getGasSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> confirmationDialog.setCurrentGasIndex(result)); private AddEthereumChainPrompt addEthereumChainPrompt; - private final long switchChainDialogCallbackId = 1; // data for switch chain request private long switchChainRequestId; // rpc request id private long switchChainId; // new chain to switch to @@ -113,10 +111,12 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa private TextView peerUrl; private TextView statusText; private TextView textName; + private TextView txCount; private ChainName chainName; private TokenIcon chainIcon; private ProgressBar progressBar; private LinearLayout infoLayout; + private LinearLayout txCountLayout; private FunctionButtonBar functionBar; private boolean fromDappBrowser = false; //if using this from dappBrowser (which is a bit strange but could happen) then return back to browser once signed private boolean fromPhoneBrowser = false; //if from phone browser, clicking 'back' should take user back to dapp running on the phone's browser, @@ -138,7 +138,8 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa private boolean waitForWalletConnectSession = false; private long requestId = 0; private AWalletAlertDialog dialog = null; - private final BroadcastReceiver walletConnectActionReceiver = new BroadcastReceiver() { + private final BroadcastReceiver walletConnectActionReceiver = new BroadcastReceiver() + { @Override public void onReceive(Context context, Intent intent) { @@ -408,6 +409,8 @@ private void initViews() peerUrl = findViewById(R.id.peer_url); statusText = findViewById(R.id.connection_status); textName = findViewById(R.id.text_name); + txCountLayout = findViewById(R.id.layout_tx_count); + txCount = findViewById(R.id.tx_count); chainName = findViewById(R.id.chain_name); chainIcon = findViewById(R.id.chain_icon); @@ -680,8 +683,8 @@ protected void onSaveInstanceState(@NotNull Bundle state) state.putString("SESSIONIDSTR", getSessionId()); if (confirmationDialog != null && confirmationDialog.isShowing() && confirmationDialog.getTransaction() != null) { - state.putParcelable("TRANSACTION", confirmationDialog.getTransaction()); - state.putLong("CHAINID", viewModel.getChainId(getSessionId())); + state.putParcelable("TRANSACTION", confirmationDialog.getTransaction()); + state.putLong("CHAINID", viewModel.getChainId(getSessionId())); } if (confirmationDialog != null && confirmationDialog.isShowing() && signData != null) { @@ -736,6 +739,7 @@ private void displaySessionStatus(String sessionId) chainIcon.setVisibility(View.VISIBLE); chainIcon.bindData(viewModel.getChainId(sessionId)); viewModel.startGasCycle(viewModel.getChainId(sessionId)); + updateSignCount(); } } @@ -768,6 +772,7 @@ private void onSessionRequest(Long id, WCPeerMeta peer, long chainId) peerName.setText(peer.getName()); textName.setText(peer.getName()); peerUrl.setText(peer.getUrl()); + txCount.setText(R.string.empty); chainName.setChainID(chainIdOverride); chainIcon.setVisibility(View.VISIBLE); chainIcon.bindData(chainIdOverride); @@ -823,7 +828,8 @@ private void onFailure(@NonNull Throwable throwable) private void doSignMessage(final Signable signable) { - final DAppFunction dappFunction = new DAppFunction() { + final DAppFunction dappFunction = new DAppFunction() + { @Override public void DAppError(Throwable error, Signable message) { @@ -850,11 +856,13 @@ public void DAppReturn(byte[] data, Signable message) requestId = 0; lastId = 0; signData = null; + updateSignCount(); }); } }; - signCallback = new SignAuthenticationCallback() { + signCallback = new SignAuthenticationCallback() + { @Override public void gotAuthorisation(boolean gotAuth) { @@ -1186,7 +1194,8 @@ public void getAuthorisation(SignAuthenticationCallback callback) @Override public void sendTransaction(Web3Transaction finalTx) { - final SendTransactionInterface callback = new SendTransactionInterface() { + final SendTransactionInterface callback = new SendTransactionInterface() + { @Override public void transactionSuccess(Web3Transaction web3Tx, String hashData) { @@ -1196,6 +1205,7 @@ public void transactionSuccess(Web3Transaction web3Tx, String hashData) if (fromDappBrowser) switchToDappBrowser(); confirmationDialog.transactionWritten(hashData); requestId = 0; + updateSignCount(); } @Override @@ -1258,7 +1268,8 @@ public ActivityResultLauncher gasSelectLauncher() @Override public void signTransaction(Web3Transaction tx) { - DAppFunction dappFunction = new DAppFunction() { + DAppFunction dappFunction = new DAppFunction() + { @Override public void DAppError(Throwable error, Signable message) { @@ -1276,6 +1287,7 @@ public void DAppReturn(byte[] data, Signable message) confirmationDialog.transactionWritten(getString(R.string.dialog_title_sign_transaction)); if (fromDappBrowser) switchToDappBrowser(); requestId = 0; + updateSignCount(); } }; @@ -1440,4 +1452,19 @@ public void buttonClick(long callbackId, Token baseToken) displaySessionStatus(session.getTopic()); } } + + private void updateSignCount() + { + ArrayList recordList = viewModel.getSignRecords(getSessionId()); + txCount.setText(String.valueOf(recordList.size())); + if (recordList.size() > 0) + { + txCountLayout.setOnClickListener(v -> { + Intent intent = new Intent(getApplication(), SignDetailActivity.class); + intent.putParcelableArrayListExtra(C.EXTRA_STATE, recordList); + intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + startActivity(intent); + }); + } + } } diff --git a/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java b/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java index d7afc9b159..719430f7ee 100644 --- a/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java +++ b/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java @@ -245,35 +245,35 @@ public boolean isConstructor() public CharSequence getFormattedTransaction(Context ctx, long chainId, String symbol) { StyledStringBuilder sb = new StyledStringBuilder(); - sb.startStyleGroup().append(ctx.getString(R.string.to)).append(":\n "); + sb.startStyleGroup().append(ctx.getString(R.string.recipient)).append(": \n"); sb.setStyle(new StyleSpan(Typeface.BOLD)); - sb.append(recipient.toString()); + sb.append(recipient.toString()).append("\n"); - sb.startStyleGroup().append("\n").append(ctx.getString(R.string.value)).append(":\n "); + sb.startStyleGroup().append("\n").append(ctx.getString(R.string.value)).append(": \n"); sb.setStyle(new StyleSpan(Typeface.BOLD)); sb.append(BalanceUtils.getScaledValueWithLimit(new BigDecimal(value), 18)); - sb.append(" ").append(symbol); + sb.append(" ").append(symbol).append("\n"); - sb.startStyleGroup().append("\n").append(ctx.getString(R.string.label_gas_price)).append(":\n "); + sb.startStyleGroup().append("\n").append(ctx.getString(R.string.label_gas_price)).append(": \n"); sb.setStyle(new StyleSpan(Typeface.BOLD)); - sb.append(BalanceUtils.weiToGwei(gasPrice)); + sb.append(BalanceUtils.weiToGwei(gasPrice)).append("\n"); - sb.startStyleGroup().append("\n").append(ctx.getString(R.string.label_gas_limit)).append(":\n "); + sb.startStyleGroup().append("\n").append(ctx.getString(R.string.label_gas_limit)).append(": \n"); sb.setStyle(new StyleSpan(Typeface.BOLD)); - sb.append(gasLimit.toString()); + sb.append(gasLimit.toString()).append("\n"); - sb.startStyleGroup().append("\n").append(ctx.getString(R.string.label_nonce)).append(":\n "); + sb.startStyleGroup().append("\n").append(ctx.getString(R.string.label_nonce)).append(": \n"); sb.setStyle(new StyleSpan(Typeface.BOLD)); - sb.append(String.valueOf(nonce)); + sb.append(String.valueOf(nonce)).append("\n"); if (!TextUtils.isEmpty(payload)) { - sb.startStyleGroup().append("\n").append(ctx.getString(R.string.payload)).append(":\n "); + sb.startStyleGroup().append("\n").append(ctx.getString(R.string.payload)).append(": \n"); sb.setStyle(new StyleSpan(Typeface.BOLD)); - sb.append(payload); + sb.append(payload).append("\n"); } - sb.startStyleGroup().append("\n").append(ctx.getString(R.string.subtitle_network)).append(":\n "); + sb.startStyleGroup().append("\n").append(ctx.getString(R.string.subtitle_network)).append(": \n"); sb.setStyle(new StyleSpan(Typeface.BOLD)); sb.append(MagicLinkInfo.getNetworkNameById(chainId)); diff --git a/app/src/main/res/layout/activity_wallet_connect.xml b/app/src/main/res/layout/activity_wallet_connect.xml index d55c4b534d..50e756d883 100644 --- a/app/src/main/res/layout/activity_wallet_connect.xml +++ b/app/src/main/res/layout/activity_wallet_connect.xml @@ -190,6 +190,37 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/item_sign_instance.xml b/app/src/main/res/layout/item_sign_instance.xml index 48bfe415ad..8bcd75653d 100644 --- a/app/src/main/res/layout/item_sign_instance.xml +++ b/app/src/main/res/layout/item_sign_instance.xml @@ -1,43 +1,25 @@ + android:orientation="vertical"> - - - - - - - + custom:headerText="Date" /> \ No newline at end of file From c5457422d86251ddc76d31ff2a05d49162af6b1b Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 30 Jul 2022 22:42:17 +0100 Subject: [PATCH 037/183] Use Klaytn Production API --- app/src/main/cpp/keys.c | 13 +++++++++++++ .../app/repository/EthereumNetworkBase.java | 17 ++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/app/src/main/cpp/keys.c b/app/src/main/cpp/keys.c index 527e461907..17d9ec6ec4 100644 --- a/app/src/main/cpp/keys.c +++ b/app/src/main/cpp/keys.c @@ -125,6 +125,19 @@ Java_com_alphawallet_app_repository_EthereumNetworkBase_getSecondaryInfuraKey( J #endif } +JNIEXPORT jstring JNICALL +Java_com_alphawallet_app_repository_EthereumNetworkBase_getKlaytnKey( JNIEnv* env, jobject thiz ) +{ +#if (HAS_KEYS == 1) + return getDecryptedKey(env, klaytnKey); +#elif (HAS_INFURA == 1) + return (*env)->NewStringUTF(env, IFKEY); +#else + const jstring key = "da3717f25f824cc1baa32d812386d93f"; + return (*env)->NewStringUTF(env, key); +#endif +} + JNIEXPORT jstring JNICALL Java_com_alphawallet_app_service_TransactionsNetworkClient_getBSCExplorerKey( JNIEnv* env, jobject thiz ) { diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 7e3028677e..37775dd814 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -83,6 +83,7 @@ import java.util.Set; import io.reactivex.Single; +import okhttp3.Credentials; public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryType { @@ -104,12 +105,14 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy */ static { + System.loadLibrary("keys"); } public static native String getAmberDataKey(); public static native String getInfuraKey(); public static native String getSecondaryInfuraKey(); + public static native String getKlaytnKey(); private static final boolean usesProductionKey = !getInfuraKey().equals(DEFAULT_INFURA_KEY); public static final String FREE_MAINNET_RPC_URL = "https://main-rpc.linkpool.io"; @@ -150,6 +153,10 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy : FREE_PALM_RPC_URL; public static final String PALM_TEST_RPC_URL = usesProductionKey ? "https://palm-testnet.infura.io/v3/" + getInfuraKey() : FREE_PALM_TEST_RPC_URL; + public static final String USE_KLAYTN_RPC = usesProductionKey ? "https://node-api.klaytnapi.com/v1/klaytn" + : KLAYTN_RPC; + public static final String USE_KLAYTN_BAOBAB_RPC = usesProductionKey ? "https://node-api.klaytnapi.com/v1/klaytn" + : KLAYTN_BAOBAB_RPC; public static final String CRONOS_MAIN_RPC_URL = "https://evm.cronos.org"; // Use the "Free" routes as backup in order to diversify node usage; to avoid single point of failure @@ -322,11 +329,11 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy "https://explorer.palm-uat.xyz/api?")); put(KLAYTN_ID, new NetworkInfo(C.KLAYTN_NAME, C.KLAYTN_SYMBOL, - KLAYTN_RPC, + USE_KLAYTN_RPC, "https://scope.klaytn.com/tx/", KLAYTN_ID, "", "https://api.covalenthq.com/v1/" + COVALENT)); put(KLAYTN_BOABAB_ID, new NetworkInfo(C.KLAYTN_BAOBAB_NAME, C.KLAYTN_SYMBOL, - KLAYTN_BAOBAB_RPC, + USE_KLAYTN_BAOBAB_RPC, "https://baobab.scope.klaytn.com/tx/", KLAYTN_BOABAB_ID, "", "")); put(IOTEX_MAINNET_ID, new NetworkInfo(C.IOTEX_NAME, C.IOTEX_SYMBOL, @@ -955,7 +962,11 @@ public static List extraChains() public static void addRequiredCredentials(long chainId, HttpService publicNodeService) { - + if ((chainId == KLAYTN_BOABAB_ID || chainId == KLAYTN_ID) && usesProductionKey) + { + publicNodeService.addHeader("x-chain-id", Long.toString(chainId)); + publicNodeService.addHeader("Authorization", "Basic " + getKlaytnKey()); + } } public static List addDefaultNetworks() From 32f22bb28778828bed94c5827657a03eddf325a3 Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 30 Jul 2022 22:44:49 +0100 Subject: [PATCH 038/183] Tidy up fallback --- app/src/main/cpp/keys.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/cpp/keys.c b/app/src/main/cpp/keys.c index 17d9ec6ec4..1e7545cbc1 100644 --- a/app/src/main/cpp/keys.c +++ b/app/src/main/cpp/keys.c @@ -130,11 +130,8 @@ Java_com_alphawallet_app_repository_EthereumNetworkBase_getKlaytnKey( JNIEnv* en { #if (HAS_KEYS == 1) return getDecryptedKey(env, klaytnKey); -#elif (HAS_INFURA == 1) - return (*env)->NewStringUTF(env, IFKEY); #else - const jstring key = "da3717f25f824cc1baa32d812386d93f"; - return (*env)->NewStringUTF(env, key); + return (*env)->NewStringUTF(env, ""); #endif } From bddbf02263d430f9341db6d3add5caff1f9aad0f Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 30 Jul 2022 22:46:32 +0100 Subject: [PATCH 039/183] Tidy imports --- .../java/com/alphawallet/app/repository/EthereumNetworkBase.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 37775dd814..b39f1a2ab1 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -83,7 +83,6 @@ import java.util.Set; import io.reactivex.Single; -import okhttp3.Credentials; public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryType { From dc02a29ef6aabb43703b141dadf27c9bc0fa460f Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 30 Jul 2022 22:47:18 +0100 Subject: [PATCH 040/183] Tidy --- .../java/com/alphawallet/app/repository/EthereumNetworkBase.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index b39f1a2ab1..a8d65b1086 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -104,7 +104,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy */ static { - System.loadLibrary("keys"); } From c91f28abcd1f20a979e287d25828d35f3e09b31f Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 30 Jul 2022 22:49:14 +0100 Subject: [PATCH 041/183] Bump to v3.58.2 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 40e912e40b..ed68ea686c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -72,8 +72,8 @@ android { } } defaultConfig { - versionCode 200 - versionName "3.58.1" + versionCode 201 + versionName "3.58.2" applicationId "io.stormbird.wallet" minSdkVersion 23 From f92ff43103046b5cc98b607e03ae397bfc0310df Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 3 Aug 2022 15:06:01 +0800 Subject: [PATCH 042/183] Refactor and add ut --- .../app/repository/EthereumNetworkBase.java | 11 +---- .../app/repository/HttpServiceHelper.java | 18 +++++++ .../app/repository/TokenRepository.java | 4 +- .../app/repository/HttpServiceHelperTest.java | 49 +++++++++++++++++++ .../com/alphawallet/utils/ReflectionUtil.java | 19 +++++++ 5 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java create mode 100644 app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java create mode 100644 app/src/test/java/com/alphawallet/utils/ReflectionUtil.java diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index a8d65b1086..3b10c34a13 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -111,7 +111,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static native String getInfuraKey(); public static native String getSecondaryInfuraKey(); public static native String getKlaytnKey(); - private static final boolean usesProductionKey = !getInfuraKey().equals(DEFAULT_INFURA_KEY); + public static final boolean usesProductionKey = !getInfuraKey().equals(DEFAULT_INFURA_KEY); public static final String FREE_MAINNET_RPC_URL = "https://main-rpc.linkpool.io"; public static final String FREE_POLYGON_RPC_URL = "https://polygon-rpc.com"; @@ -958,15 +958,6 @@ public static List extraChains() return null; } - public static void addRequiredCredentials(long chainId, HttpService publicNodeService) - { - if ((chainId == KLAYTN_BOABAB_ID || chainId == KLAYTN_ID) && usesProductionKey) - { - publicNodeService.addHeader("x-chain-id", Long.toString(chainId)); - publicNodeService.addHeader("Authorization", "Basic " + getKlaytnKey()); - } - } - public static List addDefaultNetworks() { return CustomViewSettings.alwaysVisibleChains; diff --git a/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java b/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java new file mode 100644 index 0000000000..03c258e05f --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java @@ -0,0 +1,18 @@ +package com.alphawallet.app.repository; + +import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BOABAB_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; + +import org.web3j.protocol.http.HttpService; + +public class HttpServiceHelper +{ + public static void addRequiredCredentials(long chainId, HttpService httpService, String key) + { + if ((chainId == KLAYTN_BOABAB_ID || chainId == KLAYTN_ID) && EthereumNetworkBase.usesProductionKey) + { + httpService.addHeader("x-chain-id", Long.toString(chainId)); + httpService.addHeader("Authorization", "Basic " + key); + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java index eaf432cb4d..97afb6bd67 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java @@ -118,7 +118,7 @@ public TokenRepository( private void buildWeb3jClient(NetworkInfo networkInfo) { AWHttpService publicNodeService = new AWHttpService(networkInfo.rpcServerUrl, networkInfo.backupNodeUrl, okClient, false); - EthereumNetworkRepository.addRequiredCredentials(networkInfo.chainId, publicNodeService); + HttpServiceHelper.addRequiredCredentials(networkInfo.chainId, publicNodeService, EthereumNetworkBase.getKlaytnKey()); web3jNodeServers.put(networkInfo.chainId, Web3j.build(publicNodeService)); } @@ -1191,7 +1191,7 @@ public static Web3j getWeb3jService(long chainId) .retryOnConnectionFailure(true) .build(); AWHttpService publicNodeService = new AWHttpService(EthereumNetworkRepository.getNodeURLByNetworkId (chainId), EthereumNetworkRepository.getSecondaryNodeURL(chainId), okClient, false); - EthereumNetworkRepository.addRequiredCredentials(chainId, publicNodeService); + HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, EthereumNetworkBase.getKlaytnKey()); return Web3j.build(publicNodeService); } diff --git a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java new file mode 100644 index 0000000000..fed34b975c --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java @@ -0,0 +1,49 @@ +package com.alphawallet.app.repository; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import com.alphawallet.utils.ReflectionUtil; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.web3j.protocol.http.HttpService; + +import java.util.HashMap; + +public class HttpServiceHelperTest +{ + private HttpService httpService; + + @BeforeClass + public static void beforeClass() throws Exception + { + ReflectionUtil.setFinalFieldTo(EthereumNetworkBase.class, "usesProductionKey", true); + } + + @Before + public void setUp() + { + httpService = new HttpService(); + } + + @Test + public void should_addRequiredCredentials_for_Klaytn_baobab() throws Exception + { + HttpServiceHelper.addRequiredCredentials(1001L, httpService, "klaytn-key"); + HashMap headers = httpService.getHeaders(); + assertThat(headers.get("x-chain-id"), equalTo("1001")); + assertThat(headers.get("Authorization"), equalTo("Basic klaytn-key")); + } + + @Test + public void should_addRequiredCredentials_for_KLAYTN() throws Exception + { + HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key"); + HashMap headers = httpService.getHeaders(); + assertThat(headers.get("x-chain-id"), equalTo("8217")); + assertThat(headers.get("Authorization"), equalTo("Basic klaytn-key")); + } + +} diff --git a/app/src/test/java/com/alphawallet/utils/ReflectionUtil.java b/app/src/test/java/com/alphawallet/utils/ReflectionUtil.java new file mode 100644 index 0000000000..b2390a4483 --- /dev/null +++ b/app/src/test/java/com/alphawallet/utils/ReflectionUtil.java @@ -0,0 +1,19 @@ +package com.alphawallet.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public class ReflectionUtil +{ + public static void setFinalFieldTo(Class clazz, String fieldName, boolean value) throws NoSuchFieldException, IllegalAccessException + { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + + field.set(null, value); + } +} From a023fa96a89976b4da335b81ec0a8031a3107388 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 3 Aug 2022 15:07:34 +0800 Subject: [PATCH 043/183] Fix typo --- .../app/repository/EthereumNetworkBase.java | 15 +++++++-------- .../app/repository/HttpServiceHelper.java | 4 ++-- .../alphawallet/ethereum/EthereumNetworkBase.java | 6 +++--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 3b10c34a13..1f2e51f08a 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -28,7 +28,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_TESTNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_RPC; -import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BOABAB_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; @@ -70,7 +70,6 @@ import org.web3j.protocol.Web3j; import org.web3j.protocol.core.DefaultBlockParameterName; import org.web3j.protocol.core.methods.response.EthGetTransactionCount; -import org.web3j.protocol.http.HttpService; import java.math.BigDecimal; import java.math.BigInteger; @@ -330,9 +329,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy USE_KLAYTN_RPC, "https://scope.klaytn.com/tx/", KLAYTN_ID, "", "https://api.covalenthq.com/v1/" + COVALENT)); - put(KLAYTN_BOABAB_ID, new NetworkInfo(C.KLAYTN_BAOBAB_NAME, C.KLAYTN_SYMBOL, + put(KLAYTN_BAOBAB_ID, new NetworkInfo(C.KLAYTN_BAOBAB_NAME, C.KLAYTN_SYMBOL, USE_KLAYTN_BAOBAB_RPC, - "https://baobab.scope.klaytn.com/tx/", KLAYTN_BOABAB_ID, "", + "https://baobab.scope.klaytn.com/tx/", KLAYTN_BAOBAB_ID, "", "")); put(IOTEX_MAINNET_ID, new NetworkInfo(C.IOTEX_NAME, C.IOTEX_SYMBOL, IOTEX_MAINNET_RPC_URL, @@ -400,7 +399,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(PALM_ID, R.drawable.ic_icons_network_palm); put(PALM_TEST_ID, R.drawable.palm_logo_test); put(KLAYTN_ID, R.drawable.ic_klaytn_network_logo); - put(KLAYTN_BOABAB_ID, R.drawable.ic_klaytn_test); + put(KLAYTN_BAOBAB_ID, R.drawable.ic_klaytn_test); put(IOTEX_MAINNET_ID, R.drawable.ic_iotex); put(IOTEX_TESTNET_ID, R.drawable.ic_iotex_test); put(AURORA_MAINNET_ID, R.drawable.ic_aurora); @@ -443,7 +442,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(PALM_ID, R.drawable.ic_icons_network_palm); put(PALM_TEST_ID, R.drawable.palm_logo_test); put(KLAYTN_ID, R.drawable.ic_klaytn_network_logo); - put(KLAYTN_BOABAB_ID, R.drawable.ic_klaytn_test); + put(KLAYTN_BAOBAB_ID, R.drawable.ic_klaytn_test); put(IOTEX_MAINNET_ID, R.drawable.ic_iotex); put(IOTEX_TESTNET_ID, R.drawable.ic_iotex_test); put(AURORA_MAINNET_ID, R.drawable.ic_aurora); @@ -486,7 +485,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(PALM_ID, R.color.palm_main); put(PALM_TEST_ID, R.color.palm_test); put(KLAYTN_ID, R.color.klaytn_main); - put(KLAYTN_BOABAB_ID, R.color.klaytn_test); + put(KLAYTN_BAOBAB_ID, R.color.klaytn_test); put(IOTEX_MAINNET_ID, R.color.iotex_mainnet); put(IOTEX_TESTNET_ID, R.color.iotex_mainnet); put(AURORA_MAINNET_ID, R.color.aurora_mainnet); @@ -504,7 +503,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy private static final List hasGasOracleAPI = Arrays.asList(MAINNET_ID, HECO_ID, BINANCE_MAIN_ID, MATIC_ID); //These chains don't allow custom gas - private static final List hasLockedGas = Arrays.asList(OPTIMISTIC_MAIN_ID, OPTIMISTIC_TEST_ID, ARBITRUM_MAIN_ID, ARBITRUM_TEST_ID, KLAYTN_ID, KLAYTN_BOABAB_ID); + private static final List hasLockedGas = Arrays.asList(OPTIMISTIC_MAIN_ID, OPTIMISTIC_TEST_ID, ARBITRUM_MAIN_ID, ARBITRUM_TEST_ID, KLAYTN_ID, KLAYTN_BAOBAB_ID); private static final List hasOpenSeaAPI = Arrays.asList(MAINNET_ID, MATIC_ID, RINKEBY_ID); diff --git a/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java b/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java index 03c258e05f..ac61c7dbf9 100644 --- a/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java +++ b/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java @@ -1,6 +1,6 @@ package com.alphawallet.app.repository; -import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BOABAB_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; import org.web3j.protocol.http.HttpService; @@ -9,7 +9,7 @@ public class HttpServiceHelper { public static void addRequiredCredentials(long chainId, HttpService httpService, String key) { - if ((chainId == KLAYTN_BOABAB_ID || chainId == KLAYTN_ID) && EthereumNetworkBase.usesProductionKey) + if ((chainId == KLAYTN_BAOBAB_ID || chainId == KLAYTN_ID) && EthereumNetworkBase.usesProductionKey) { httpService.addHeader("x-chain-id", Long.toString(chainId)); httpService.addHeader("Authorization", "Basic " + key); diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 7ddfb40024..7c0ee5f6bd 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -38,7 +38,7 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final long PALM_ID = 0x2a15c308dL; //11297108109 public static final long PALM_TEST_ID = 0x2a15c3083L; //11297108099 public static final long KLAYTN_ID = 8217; - public static final long KLAYTN_BOABAB_ID = 1001; + public static final long KLAYTN_BAOBAB_ID = 1001; public static final long IOTEX_MAINNET_ID = 4689; public static final long IOTEX_TESTNET_ID = 4690; public static final long AURORA_MAINNET_ID = 1313161554; @@ -152,8 +152,8 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit put(KLAYTN_ID, new NetworkInfo("Klaytn Cypress","KLAY", KLAYTN_RPC, "https://scope.klaytn.com/tx/", KLAYTN_ID, false)); - put(KLAYTN_BOABAB_ID, new NetworkInfo("Klaytn Boabab (Test)","KLAY", KLAYTN_BAOBAB_RPC, "https://baobab.scope.klaytn.com/tx/", - KLAYTN_BOABAB_ID, false)); + put(KLAYTN_BAOBAB_ID, new NetworkInfo("Klaytn Baobab (Test)","KLAY", KLAYTN_BAOBAB_RPC, "https://baobab.scope.klaytn.com/tx/", + KLAYTN_BAOBAB_ID, false)); put(AURORA_MAINNET_ID, new NetworkInfo("Aurora","ETH", AURORA_MAINNET_RPC_URL, "https://aurorascan.dev/tx/", AURORA_MAINNET_ID, false)); put(AURORA_TESTNET_ID, new NetworkInfo("Aurora (Test)","ETH", AURORA_TESTNET_RPC_URL, "https://testnet.aurorascan.dev/tx/", From 4fdfb44f5d1d17cd0b37045b32adff892eacc05a Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 3 Aug 2022 15:29:37 +0800 Subject: [PATCH 044/183] Run with Robolectric to fix CI --- .../app/repository/HttpServiceHelperTest.java | 8 ++++++++ .../java/com/alphawallet/shadows/ShadowApp.java | 15 +++++++++++++++ .../com/alphawallet/shadows/ShadowSystem.java | 12 ++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowApp.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowSystem.java diff --git a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java index fed34b975c..fe5f9788b7 100644 --- a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java +++ b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java @@ -3,15 +3,23 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.shadows.ShadowApp; +import com.alphawallet.shadows.ShadowSystem; import com.alphawallet.utils.ReflectionUtil; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; import org.web3j.protocol.http.HttpService; import java.util.HashMap; +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowApp.class, ShadowSystem.class}) public class HttpServiceHelperTest { private HttpService httpService; diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowApp.java b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java new file mode 100644 index 0000000000..3068f88761 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java @@ -0,0 +1,15 @@ +package com.alphawallet.shadows; + +import com.alphawallet.app.App; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(App.class) +public class ShadowApp +{ + @Implementation + public void onCreate() + { + } +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowSystem.java b/app/src/test/java/com/alphawallet/shadows/ShadowSystem.java new file mode 100644 index 0000000000..8aad2650d5 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowSystem.java @@ -0,0 +1,12 @@ +package com.alphawallet.shadows; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(System.class) +public class ShadowSystem +{ + @Implementation + public static void loadLibrary(String libname) { + } +} From 21fc6e9c325628928e4fa8df50a605776f6e5ac1 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 3 Aug 2022 15:32:59 +0800 Subject: [PATCH 045/183] fix ci --- app/src/test/java/com/alphawallet/shadows/ShadowApp.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowApp.java b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java index 3068f88761..c1d543c4a3 100644 --- a/app/src/test/java/com/alphawallet/shadows/ShadowApp.java +++ b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java @@ -1,12 +1,14 @@ package com.alphawallet.shadows; +import android.app.Application; + import com.alphawallet.app.App; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; @Implements(App.class) -public class ShadowApp +public class ShadowApp extends Application { @Implementation public void onCreate() From ffab254607b3bee722bbe76b51a30624f3c5e349 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 3 Aug 2022 18:13:01 +0800 Subject: [PATCH 046/183] Fix ci --- app/src/test/java/com/alphawallet/shadows/ShadowApp.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowApp.java b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java index c1d543c4a3..483a62a261 100644 --- a/app/src/test/java/com/alphawallet/shadows/ShadowApp.java +++ b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java @@ -6,9 +6,10 @@ import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowApplication; @Implements(App.class) -public class ShadowApp extends Application +public class ShadowApp extends ShadowApplication { @Implementation public void onCreate() From 64b504e6d1b405388d8abae4063f44522b529b3c Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 4 Aug 2022 17:08:14 +0800 Subject: [PATCH 047/183] Fix test --- .../app/repository/HttpServiceHelperTest.java | 35 ++++++------------- .../com/alphawallet/shadows/ShadowApp.java | 18 ---------- .../com/alphawallet/shadows/ShadowSystem.java | 12 ------- 3 files changed, 10 insertions(+), 55 deletions(-) delete mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowApp.java delete mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowSystem.java diff --git a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java index fe5f9788b7..3d5edb566d 100644 --- a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java +++ b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java @@ -1,27 +1,20 @@ package com.alphawallet.app.repository; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsEqual.equalTo; +import static org.mockito.Mockito.verify; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import com.alphawallet.shadows.ShadowApp; -import com.alphawallet.shadows.ShadowSystem; import com.alphawallet.utils.ReflectionUtil; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; import org.web3j.protocol.http.HttpService; -import java.util.HashMap; - -@RunWith(AndroidJUnit4.class) -@Config(shadows = {ShadowApp.class, ShadowSystem.class}) +@RunWith(PowerMockRunner.class) public class HttpServiceHelperTest { + @Mock private HttpService httpService; @BeforeClass @@ -30,28 +23,20 @@ public static void beforeClass() throws Exception ReflectionUtil.setFinalFieldTo(EthereumNetworkBase.class, "usesProductionKey", true); } - @Before - public void setUp() - { - httpService = new HttpService(); - } - @Test public void should_addRequiredCredentials_for_Klaytn_baobab() throws Exception { HttpServiceHelper.addRequiredCredentials(1001L, httpService, "klaytn-key"); - HashMap headers = httpService.getHeaders(); - assertThat(headers.get("x-chain-id"), equalTo("1001")); - assertThat(headers.get("Authorization"), equalTo("Basic klaytn-key")); + verify(httpService).addHeader("x-chain-id", "1001"); + verify(httpService).addHeader("Authorization", "Basic klaytn-key"); } @Test - public void should_addRequiredCredentials_for_KLAYTN() throws Exception + public void should_addRequiredCredentials_for_Klaytn() throws Exception { HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key"); - HashMap headers = httpService.getHeaders(); - assertThat(headers.get("x-chain-id"), equalTo("8217")); - assertThat(headers.get("Authorization"), equalTo("Basic klaytn-key")); + verify(httpService).addHeader("x-chain-id", "8217"); + verify(httpService).addHeader("Authorization", "Basic klaytn-key"); } } diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowApp.java b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java deleted file mode 100644 index 483a62a261..0000000000 --- a/app/src/test/java/com/alphawallet/shadows/ShadowApp.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.alphawallet.shadows; - -import android.app.Application; - -import com.alphawallet.app.App; - -import org.robolectric.annotation.Implementation; -import org.robolectric.annotation.Implements; -import org.robolectric.shadows.ShadowApplication; - -@Implements(App.class) -public class ShadowApp extends ShadowApplication -{ - @Implementation - public void onCreate() - { - } -} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowSystem.java b/app/src/test/java/com/alphawallet/shadows/ShadowSystem.java deleted file mode 100644 index 8aad2650d5..0000000000 --- a/app/src/test/java/com/alphawallet/shadows/ShadowSystem.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.alphawallet.shadows; - -import org.robolectric.annotation.Implementation; -import org.robolectric.annotation.Implements; - -@Implements(System.class) -public class ShadowSystem -{ - @Implementation - public static void loadLibrary(String libname) { - } -} From 58fdb17935f1e1f30d230ba7800b88162cd87f4f Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Fri, 5 Aug 2022 11:21:43 +0800 Subject: [PATCH 048/183] Fix test --- .../app/repository/EthereumNetworkBase.java | 3 +- .../app/repository/HttpServiceHelper.java | 4 +- .../app/repository/TokenRepository.java | 4 +- .../alphawallet/app/util/SystemWrapper.java | 8 +++ .../app/repository/HttpServiceHelperTest.java | 49 +++++++++++-------- .../com/alphawallet/shadows/ShadowApp.java | 16 ++++++ .../shadows/ShadowSystemWrapper.java | 15 ++++++ 7 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/util/SystemWrapper.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowApp.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowSystemWrapper.java diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 1f2e51f08a..7ecba962ae 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -62,6 +62,7 @@ import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenInfo; +import com.alphawallet.app.util.SystemWrapper; import com.alphawallet.app.util.Utils; import com.alphawallet.token.entity.ChainSpec; import com.google.gson.Gson; @@ -103,7 +104,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy */ static { - System.loadLibrary("keys"); + SystemWrapper.loadLibrary("keys"); } public static native String getAmberDataKey(); diff --git a/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java b/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java index ac61c7dbf9..956d1b685f 100644 --- a/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java +++ b/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java @@ -7,9 +7,9 @@ public class HttpServiceHelper { - public static void addRequiredCredentials(long chainId, HttpService httpService, String key) + public static void addRequiredCredentials(long chainId, HttpService httpService, String key, boolean usesProductionKey) { - if ((chainId == KLAYTN_BAOBAB_ID || chainId == KLAYTN_ID) && EthereumNetworkBase.usesProductionKey) + if ((chainId == KLAYTN_BAOBAB_ID || chainId == KLAYTN_ID) && usesProductionKey) { httpService.addHeader("x-chain-id", Long.toString(chainId)); httpService.addHeader("Authorization", "Basic " + key); diff --git a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java index 97afb6bd67..95c134217c 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java @@ -118,7 +118,7 @@ public TokenRepository( private void buildWeb3jClient(NetworkInfo networkInfo) { AWHttpService publicNodeService = new AWHttpService(networkInfo.rpcServerUrl, networkInfo.backupNodeUrl, okClient, false); - HttpServiceHelper.addRequiredCredentials(networkInfo.chainId, publicNodeService, EthereumNetworkBase.getKlaytnKey()); + HttpServiceHelper.addRequiredCredentials(networkInfo.chainId, publicNodeService, EthereumNetworkBase.getKlaytnKey(), EthereumNetworkBase.usesProductionKey); web3jNodeServers.put(networkInfo.chainId, Web3j.build(publicNodeService)); } @@ -1191,7 +1191,7 @@ public static Web3j getWeb3jService(long chainId) .retryOnConnectionFailure(true) .build(); AWHttpService publicNodeService = new AWHttpService(EthereumNetworkRepository.getNodeURLByNetworkId (chainId), EthereumNetworkRepository.getSecondaryNodeURL(chainId), okClient, false); - HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, EthereumNetworkBase.getKlaytnKey()); + HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, EthereumNetworkBase.getKlaytnKey(), EthereumNetworkBase.usesProductionKey); return Web3j.build(publicNodeService); } diff --git a/app/src/main/java/com/alphawallet/app/util/SystemWrapper.java b/app/src/main/java/com/alphawallet/app/util/SystemWrapper.java new file mode 100644 index 0000000000..2b504534c1 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/SystemWrapper.java @@ -0,0 +1,8 @@ +package com.alphawallet.app.util; + +public class SystemWrapper +{ + public static void loadLibrary(String name) { + System.loadLibrary(name); + } +} diff --git a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java index 3d5edb566d..4e2436f9e2 100644 --- a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java +++ b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java @@ -1,42 +1,51 @@ package com.alphawallet.app.repository; -import static org.mockito.Mockito.verify; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertFalse; -import com.alphawallet.utils.ReflectionUtil; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.shadows.ShadowApp; +import com.alphawallet.shadows.ShadowSystemWrapper; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.powermock.modules.junit4.PowerMockRunner; +import org.robolectric.annotation.Config; import org.web3j.protocol.http.HttpService; -@RunWith(PowerMockRunner.class) +import java.util.HashMap; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowSystemWrapper.class, ShadowApp.class}) public class HttpServiceHelperTest { - @Mock - private HttpService httpService; + private final HttpService httpService = new HttpService(); - @BeforeClass - public static void beforeClass() throws Exception + @Test + public void should_addRequiredCredentials_for_Klaytn_baobab() throws Exception { - ReflectionUtil.setFinalFieldTo(EthereumNetworkBase.class, "usesProductionKey", true); + HttpServiceHelper.addRequiredCredentials(1001L, httpService, "klaytn-key", true); + HashMap headers = httpService.getHeaders(); + assertThat(headers.get("x-chain-id"), equalTo("1001")); + assertThat(headers.get("Authorization"), equalTo("Basic klaytn-key")); } @Test - public void should_addRequiredCredentials_for_Klaytn_baobab() throws Exception + public void should_addRequiredCredentials_for_KLAYTN() throws Exception { - HttpServiceHelper.addRequiredCredentials(1001L, httpService, "klaytn-key"); - verify(httpService).addHeader("x-chain-id", "1001"); - verify(httpService).addHeader("Authorization", "Basic klaytn-key"); + HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key", true); + HashMap headers = httpService.getHeaders(); + assertThat(headers.get("x-chain-id"), equalTo("8217")); + assertThat(headers.get("Authorization"), equalTo("Basic klaytn-key")); } @Test - public void should_addRequiredCredentials_for_Klaytn() throws Exception + public void should_not_addRequiredCredentials_for_KLAYTN_when_not_use_production_key() throws Exception { - HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key"); - verify(httpService).addHeader("x-chain-id", "8217"); - verify(httpService).addHeader("Authorization", "Basic klaytn-key"); + HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key", false); + HashMap headers = httpService.getHeaders(); + assertFalse(headers.containsKey("x-chain-id")); + assertFalse(headers.containsKey("Authorization")); } - } diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowApp.java b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java new file mode 100644 index 0000000000..14aef71bcb --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowApp.java @@ -0,0 +1,16 @@ +package com.alphawallet.shadows; + +import com.alphawallet.app.App; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowApplication; + +@Implements(App.class) +public class ShadowApp extends ShadowApplication +{ + @Implementation + public void onCreate() + { + } +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowSystemWrapper.java b/app/src/test/java/com/alphawallet/shadows/ShadowSystemWrapper.java new file mode 100644 index 0000000000..1c4ebecc95 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowSystemWrapper.java @@ -0,0 +1,15 @@ +package com.alphawallet.shadows; + +import com.alphawallet.app.util.SystemWrapper; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(SystemWrapper.class) +public class ShadowSystemWrapper +{ + @Implementation + public static void loadLibrary(String name) + { + } +} From 1020f32529386f04d7ef482ffa072d1c7701e4af Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Fri, 5 Aug 2022 11:43:43 +0800 Subject: [PATCH 049/183] Delete unused file --- .../com/alphawallet/utils/ReflectionUtil.java | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 app/src/test/java/com/alphawallet/utils/ReflectionUtil.java diff --git a/app/src/test/java/com/alphawallet/utils/ReflectionUtil.java b/app/src/test/java/com/alphawallet/utils/ReflectionUtil.java deleted file mode 100644 index b2390a4483..0000000000 --- a/app/src/test/java/com/alphawallet/utils/ReflectionUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.alphawallet.utils; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -public class ReflectionUtil -{ - public static void setFinalFieldTo(Class clazz, String fieldName, boolean value) throws NoSuchFieldException, IllegalAccessException - { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - - field.set(null, value); - } -} From fbb7b2e974784d0bd45833d158fc8e76fb14021e Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Fri, 5 Aug 2022 17:06:31 +0800 Subject: [PATCH 050/183] Fix coverage configuration --- app/build.gradle | 9 +++++++++ .../app/repository/HttpServiceHelperTest.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 40e912e40b..725c0f0b26 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,6 +28,15 @@ apply plugin: 'com.worker8.android_lint_reporter' apply plugin: 'io.gitlab.arturbosch.detekt' apply plugin: 'com.dicedmelon.gradle.jacoco-android' +jacoco { + toolVersion = "0.8.8" +} + +tasks.withType(Test) { + jacoco.includeNoLocationClasses = true + jacoco.excludes = ['jdk.internal.*'] +} + jacocoAndroidUnitTestReport { csv.enabled false html.enabled true diff --git a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java index 4e2436f9e2..a044c6d97c 100644 --- a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java +++ b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java @@ -48,4 +48,13 @@ public void should_not_addRequiredCredentials_for_KLAYTN_when_not_use_production assertFalse(headers.containsKey("x-chain-id")); assertFalse(headers.containsKey("Authorization")); } + + @Test + public void should_not_addRequiredCredentials_for_non_KLAYTN_chain() throws Exception + { + HttpServiceHelper.addRequiredCredentials(1, httpService, "klaytn-key", false); + HashMap headers = httpService.getHeaders(); + assertFalse(headers.containsKey("x-chain-id")); + assertFalse(headers.containsKey("Authorization")); + } } From 48c9e1cf498a08263d475c5cdc7334baee755180 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Sun, 14 Aug 2022 22:12:21 +0800 Subject: [PATCH 051/183] Add new workflow --- .github/workflows/stats.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/stats.yml diff --git a/.github/workflows/stats.yml b/.github/workflows/stats.yml new file mode 100644 index 0000000000..459c67e940 --- /dev/null +++ b/.github/workflows/stats.yml @@ -0,0 +1,15 @@ +name: Pull Request Stats + +on: + pull_request: + types: [opened] + +jobs: + stats: + runs-on: ubuntu-latest + steps: + - name: Run pull request stats + uses: flowwer-dev/pull-request-stats@master + with: + charts: true + sort-by: 'COMMENTS' \ No newline at end of file From f804a3fd4ebbaeb21025a576af94289b0f53c33c Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 16 Aug 2022 22:05:53 +0800 Subject: [PATCH 052/183] Remove JCenter use GitHub packages, jitpack instead --- app/build.gradle | 14 +++++++++----- build.gradle | 2 -- lib/build.gradle | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b5d4da637c..32fbbb5c0d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,7 +68,11 @@ android_lint_reporter { repositories { maven { - url 'https://maven.google.com' + url = uri("https://maven.pkg.github.com/trustwallet/wallet-core") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") + password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") + } } } @@ -249,7 +253,7 @@ dependencies { // Sugar implementation 'androidx.constraintlayout:constraintlayout:2.1.3' implementation 'com.github.apl-devs:appintro:v4.2.2' - implementation 'com.romandanylyk:pageindicatorview:1.0.0' + implementation 'com.github.romandanylyk:PageIndicatorView:v1.0.0' //coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5' @@ -308,12 +312,12 @@ dependencies { androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0' - implementation group: 'com.trustwallet', name: 'wallet-core', version: '2.6.3' + implementation 'com.trustwallet:wallet-core:2.6.4' - implementation 'com.github.florent37:tutoshowcase:1.0.1' + implementation 'com.github.florent37:TutoShowcase:d8b91be8a2' // Do not upgrade unless we have migrated to AndroidX - implementation 'com.google.android:flexbox:2.0.1' + implementation 'com.github.google:flexbox-layout:2.0.1' implementation 'com.github.salomonbrys.kotson:kotson:2.5.0' diff --git a/build.gradle b/build.gradle index 8a3dd0c8a4..97a3b10baf 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,6 @@ buildscript { repositories { // don't add anything here until you read to the bottom of this bracket google() - jcenter() mavenCentral() maven { url 'https://jitpack.io' } // WARNING WARNING WARNING @@ -27,7 +26,6 @@ buildscript { allprojects { repositories { google() - jcenter() mavenCentral() maven { url 'https://jitpack.io' } // WARNING WARNING WARNING diff --git a/lib/build.gradle b/lib/build.gradle index b0b0b6fa59..602fe07e6b 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -1,9 +1,9 @@ buildscript { repositories { - jcenter() + maven { url 'https://plugins.gradle.org/m2/' } } dependencies { - classpath 'com.github.jengelman.gradle.plugins:shadow:5.1.0' + classpath 'com.github.jengelman.gradle.plugins:shadow:6.1.0' } } From ad93df471afd9ffc66411b44080323345b8271bb Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 16 Aug 2022 22:25:12 +0800 Subject: [PATCH 053/183] Use embeded env variables when build with GitHub actions --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 32fbbb5c0d..0b6867b25a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,8 +70,8 @@ repositories { maven { url = uri("https://maven.pkg.github.com/trustwallet/wallet-core") credentials { - username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") - password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") } } } From 75774bd92060eecafd2d41261c9f2200b45e373f Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 16 Aug 2022 22:34:03 +0800 Subject: [PATCH 054/183] Revert "Use embeded env variables when build with GitHub actions" This reverts commit ad93df471afd9ffc66411b44080323345b8271bb. --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0b6867b25a..32fbbb5c0d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,8 +70,8 @@ repositories { maven { url = uri("https://maven.pkg.github.com/trustwallet/wallet-core") credentials { - username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") - password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") + password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") } } } From 42357234ca49af99faa180ce430e3d2ef2d0c243 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 16 Aug 2022 22:36:25 +0800 Subject: [PATCH 055/183] Set env variables in GitHub actions --- .github/workflows/lint.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fbea837c0f..68b6723179 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,6 +22,12 @@ jobs: java-version: 11 cache: gradle - name: Run Kotlin lint + env: + USERNAME: ${{GITHUB_ACTOR}} + TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:detekt - name: Run Android Lint + env: + USERNAME: ${{GITHUB_ACTOR}} + TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:lintAnalyticsDebug \ No newline at end of file From b4e1e06cb7deae695c6c4b7da5adc60720f0814f Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 16 Aug 2022 22:37:34 +0800 Subject: [PATCH 056/183] Fix syntax --- .github/workflows/lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 68b6723179..fea9622938 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,11 +23,11 @@ jobs: cache: gradle - name: Run Kotlin lint env: - USERNAME: ${{GITHUB_ACTOR}} + USERNAME: ${{ GITHUB_ACTOR }} TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:detekt - name: Run Android Lint env: - USERNAME: ${{GITHUB_ACTOR}} + USERNAME: ${{ GITHUB_ACTOR }} TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:lintAnalyticsDebug \ No newline at end of file From d85f67077bcceea9428030c918c7d7b3c18dcfaa Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 16 Aug 2022 22:41:24 +0800 Subject: [PATCH 057/183] Fix workflow syntax --- .github/workflows/lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fea9622938..a11fad8e11 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,11 +23,11 @@ jobs: cache: gradle - name: Run Kotlin lint env: - USERNAME: ${{ GITHUB_ACTOR }} + USERNAME: ${{ env.GITHUB_ACTOR }} TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:detekt - name: Run Android Lint env: - USERNAME: ${{ GITHUB_ACTOR }} + USERNAME: ${{ env.GITHUB_ACTOR }} TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:lintAnalyticsDebug \ No newline at end of file From dc5ef949541718e9cfb115fc94530fed3d01741d Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 16 Aug 2022 22:56:15 +0800 Subject: [PATCH 058/183] Fix CI --- .github/workflows/ci.yml | 3 +++ .github/workflows/e2e.yml | 3 +++ .github/workflows/lint-pr.yml | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 75f4dcba93..4680c6616e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,9 @@ jobs: java-version: 11 - name: Build the app + env: + USERNAME: ${{ env.GITHUB_ACTOR }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} run: sh ./build.sh - name: Upload coverage reports to Codecov diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 8cfb3449c2..79eb9b7861 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -24,6 +24,9 @@ jobs: - name: Run tests uses: reactivecircus/android-emulator-runner@v2 + env: + USERNAME: ${{ env.GITHUB_ACTOR }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index c9de6639a5..b8a3ceec15 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -19,12 +19,20 @@ jobs: java-version: 11 cache: gradle - name: Run detekt + env: + USERNAME: ${{ env.GITHUB_ACTOR }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:detekt continue-on-error: true - name: Run Android Lint + env: + USERNAME: ${{ env.GITHUB_ACTOR }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:lintAnalyticsDebug - name: Run Android Lint Reporter to report Lint and Detekt result to PR env: + USERNAME: ${{ env.GITHUB_ACTOR }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | From 891dd46729002b6e3396da693533db7f4d65429b Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 18 Aug 2022 22:57:01 +0800 Subject: [PATCH 059/183] Ignore .project --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 34074fb4f6..d7a43fcc9d 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,4 @@ gen-external-apklibs fastlane/.google-play-key.json DCIM/ vendor/ +.project From fa2a6269a45cb5cd2294362cb7f06f6ff9f93087 Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 18 Aug 2022 23:07:22 -0700 Subject: [PATCH 060/183] Prompt user to select networks upon creating/importing new wallet (#2751) * Show network selection screen for newly created/imported wallets * Store or fetch lowercase address * Add activity unit test * 2248 ci no coverage report found (#2748) * Test upload coverage report to Codecov * Config Jacoco report, ignore slow test * Split e2e test out of CI job * Update Codecov badge * Enable transfer test on API level 32 (#2677) * Enable transfer test on API level 32 * API 32 not supported by GitHub actions * Update EIP712 signing code (#2752) * Add signing unit tests * Show WalletConnect Signed Transaction Count (#2750) * Display tx count in WC activity * Update wc signed transaction detail layout * Small improvement to transaction detail formatting * Set initial count to zero * Update UI after transaction * Fixed a bug where testnets and mainnets appear at the same time in wallet * Run with Robolectric to fix CI * Integrate Robolectric with Hilt * Put all keys together * Test non-production mode uses free RPC nodes * Refactor: move methods out of EthereumNetworkBase * Try self-hosted runner * Run on M1 * Upgrade AGP and Gradle * Upgrade cmake version * Specific NDK version * Use cmake 3.18.1 * Run all jobs on self-hosted runner * All in one pipeline * Run all jobs on Mac OS * Add dns server * Remove DNS option & run e2e on all PRs * Run on API 30 * Enable transfer test * Test Rinkeby * Don't cache gradle * Fix transfer test * Revise CI trigger Co-authored-by: Seaborn Lee --- .github/workflows/ci.yml | 23 +-- .github/workflows/e2e.yml | 23 +-- .github/workflows/lint-pr.yml | 11 +- .github/workflows/lint.yml | 8 +- .gitignore | 1 + app/CMakeCache.txt | 150 ++++++++++++++++++ .../3.18.1-g262b901-dirty/CMakeSystem.cmake | 15 ++ app/CMakeFiles/cmake.check_cache | 1 + app/build.gradle | 17 +- .../app/service/AnalyticsService.java | 10 +- .../com/alphawallet/app/DappBrowserTest.java | 14 +- .../alphawallet/app/ManageNetworkTest.java | 12 +- .../com/alphawallet/app/TransferTest.java | 5 +- .../alphawallet/app/assertions/Should.java | 25 ++- .../java/com/alphawallet/app/steps/Steps.java | 30 ++-- .../java/com/alphawallet/app/util/Helper.java | 2 +- app/src/main/cpp/keys.c | 86 ++-------- .../app/di/RepositoriesModule.java | 40 +++-- .../app/repository/EthereumNetworkBase.java | 81 +++------- .../app/repository/KeyProvider.java | 17 ++ .../app/repository/KeyProviderFactory.java | 8 + .../app/repository/KeyProviderJNIImpl.java | 22 +++ .../app/repository/OnRampRepository.java | 10 +- .../repository/PreferenceRepositoryType.java | 3 + .../SharedPreferenceRepository.java | 20 +++ .../app/repository/TokenRepository.java | 7 +- .../alphawallet/app/service/GasService.java | 14 +- .../app/service/OpenSeaService.java | 11 +- .../service/TransactionsNetworkClient.java | 28 ++-- .../app/ui/DappBrowserFragment.java | 6 +- .../com/alphawallet/app/ui/HomeActivity.java | 130 ++++++++------- .../alphawallet/app/ui/WalletsActivity.java | 6 +- .../alphawallet/app/util/AWEnsResolver.java | 7 - .../app/util/DappBrowserUtils.java | 22 ++- .../alphawallet/app/util/SystemWrapper.java | 8 - .../app/viewmodel/HomeViewModel.java | 14 ++ .../app/viewmodel/SplashViewModel.java | 2 + .../app/viewmodel/WalletsViewModel.java | 8 +- .../app/widget/EmailPromptView.java | 11 +- .../app/di/EthereumNetworkBaseTest.java | 39 +++++ .../app/di/mock/KeyProviderMockImpl.java | 80 ++++++++++ .../KeyProviderMockNonProductionImpl.java | 79 +++++++++ .../app/repository/HttpServiceHelperTest.java | 3 +- .../alphawallet/app/ui/HomeActivityTest.java | 40 +++++ .../app/util/DappBrowserUtilsTest.java | 36 +++++ .../app/viewmodel/HomeViewModelTest.java | 46 ++++++ .../shadows/ShadowAnalyticsService.java | 20 +++ .../shadows/ShadowEthereumNetworkBase.java | 22 +++ .../shadows/ShadowKeyProviderFactory.java | 19 +++ ...ShadowKeyProviderFactoryNonProduction.java | 18 +++ .../alphawallet/shadows/ShadowKeyService.java | 19 +++ .../com/alphawallet/shadows/ShadowRealm.java | 4 +- .../shadows/ShadowRealmManager.java | 30 ++++ .../shadows/ShadowSystemWrapper.java | 15 -- build.gradle | 2 + contracts/TokenScript-Repo | 1 - .../token/web/AppSiteController.java | 5 - dmz/src/main/resources/application.properties | 1 - 58 files changed, 1002 insertions(+), 385 deletions(-) create mode 100644 app/CMakeCache.txt create mode 100644 app/CMakeFiles/3.18.1-g262b901-dirty/CMakeSystem.cmake create mode 100644 app/CMakeFiles/cmake.check_cache create mode 100644 app/src/main/java/com/alphawallet/app/repository/KeyProvider.java create mode 100644 app/src/main/java/com/alphawallet/app/repository/KeyProviderFactory.java create mode 100644 app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java delete mode 100644 app/src/main/java/com/alphawallet/app/util/SystemWrapper.java create mode 100644 app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java create mode 100644 app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java create mode 100644 app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java create mode 100644 app/src/test/java/com/alphawallet/app/ui/HomeActivityTest.java create mode 100644 app/src/test/java/com/alphawallet/app/util/DappBrowserUtilsTest.java create mode 100644 app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowAnalyticsService.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowEthereumNetworkBase.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowKeyProviderFactory.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowKeyProviderFactoryNonProduction.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowKeyService.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowRealmManager.java delete mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowSystemWrapper.java delete mode 160000 contracts/TokenScript-Repo diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4680c6616e..8818269b9e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,26 +4,29 @@ on: branches: - master pull_request: - branches: - - master jobs: test: runs-on: macos-latest steps: - - name: checkout - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - name: Set up JDK 11 - uses: actions/setup-java@v1 + - name: Set up JDK + uses: actions/setup-java@v3 with: + distribution: zulu java-version: 11 + cache: gradle - - name: Build the app - env: - USERNAME: ${{ env.GITHUB_ACTOR }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Run unit tests run: sh ./build.sh + - name: Upload Test Reports Folder + uses: actions/upload-artifact@v2 + if: ${{ always() }} # IMPORTANT: Upload reports regardless of status + with: + name: ut-reports + path: app/build/reports/tests + - name: Upload coverage reports to Codecov run: | curl -Os https://uploader.codecov.io/latest/macos/codecov diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 79eb9b7861..f788da8fe3 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -4,23 +4,22 @@ on: branches: - master pull_request: - branches: - - master jobs: test: - runs-on: macos-latest + runs-on: self-hosted strategy: matrix: - api-level: [31] + api-level: [30] target: [default] steps: - - name: checkout - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - name: Set up JDK 11 - uses: actions/setup-java@v1 + - name: Set up JDK + uses: actions/setup-java@v3 with: + distribution: zulu java-version: 11 + architecture: arm64 - name: Run tests uses: reactivecircus/android-emulator-runner@v2 @@ -30,10 +29,12 @@ jobs: with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} - arch: x86_64 + arch: arm64-v8a profile: Nexus 6 - ram-size: 4096M - sdcard-path-or-size: 4096M + channel: canary + disable-animations: true + force-avd-creation: false + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: ./e2e.sh --CI - name: Collect tests results diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index b8a3ceec15..ddcf22ac7a 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -1,17 +1,12 @@ name: Comments Android lint warnings on pull request -on: - pull_request: - branches: - - master +on: pull_request jobs: lint: - name: Run Lint - runs-on: ubuntu-18.04 + name: Comments lint result on PR + runs-on: macos-latest steps: - uses: actions/checkout@v3 - with: - fetch-depth: 1 - name: set up JDK uses: actions/setup-java@v3 with: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a11fad8e11..a503745754 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,18 +4,14 @@ on: branches: - master pull_request: - branches: - - master jobs: lint: name: Run Lint - runs-on: ubuntu-18.04 + runs-on: macos-latest steps: - uses: actions/checkout@v3 - with: - fetch-depth: 1 - - name: set up JDK + - name: Set up JDK uses: actions/setup-java@v3 with: distribution: zulu diff --git a/.gitignore b/.gitignore index d7a43fcc9d..4cd7d8520f 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ app/full-r8-config.txt app/awallet app/analytics app/noAnalytics +app/CMakeCache.txt # Files for the Dalvik VM *.dex diff --git a/app/CMakeCache.txt b/app/CMakeCache.txt new file mode 100644 index 0000000000..6ee713b60b --- /dev/null +++ b/app/CMakeCache.txt @@ -0,0 +1,150 @@ +# This is the CMakeCache file. +# For build in directory: c:/Users/soyle/StudioProjects/x/y/alpha-wallet-android/app +# It was generated by CMake: E:/dev/Android/cmake/3.18.1/bin/cmake.exe +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//No help, variable specified on the command line. +ANDROID_ABI:UNINITIALIZED=x86_64 + +//No help, variable specified on the command line. +ANDROID_NDK:UNINITIALIZED=E:\dev\Android\ndk\21.4.7075529 + +//No help, variable specified on the command line. +ANDROID_PLATFORM:UNINITIALIZED=android-23 + +//No help, variable specified on the command line. +ASKEY:UNINITIALIZED="HFDDY5BNKGXBB82DE2G8S64C3C41B76PYI" -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=C:\Users\soyle\StudioProjects\x\y\alpha-wallet-android\app\build\intermediates\cxx\Debug\3un4y862\obj\x86_64 -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=C:\Users\soyle\StudioProjects\x\y\alpha-wallet-android\app\build\intermediates\cxx\Debug\3un4y862\obj\x86_64 -DCMAKE_BUILD_TYPE=Debug -BC:\Users\soyle\StudioProjects\x\y\alpha-wallet-android\app\.cxx\Debug\3un4y862\x86_64 -GNinja + +//No help, variable specified on the command line. +CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=x86_64 + +//No help, variable specified on the command line. +CMAKE_ANDROID_NDK:UNINITIALIZED=E:\dev\Android\ndk\21.4.7075529 + +//Archiver +CMAKE_AR:FILEPATH=E:/dev/Android/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/bin/i686-linux-android-ar.exe + +//Flags used by the compiler during all build types. +CMAKE_ASM_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_ASM_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_ASM_FLAGS_RELEASE:STRING= + +//Semicolon separated list of supported configuration types, only +// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything +// else will be ignored. +CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_CXX_FLAGS_RELEASE:STRING= + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING=-DIFKEY="da3717f25f824cc1baa32d812386d93f" -DOSKEY="..." -DPSKEY=""" + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_C_FLAGS_RELEASE:STRING= + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//No help, variable specified on the command line. +CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON + +//No help, variable specified on the command line. +CMAKE_MAKE_PROGRAM:UNINITIALIZED=E:\dev\Android\cmake\3.18.1\bin\ninja.exe + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Ranlib +CMAKE_RANLIB:FILEPATH=E:/dev/Android/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/bin/i686-linux-android-ranlib.exe + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//No help, variable specified on the command line. +CMAKE_SYSTEM_NAME:UNINITIALIZED=Android + +//No help, variable specified on the command line. +CMAKE_SYSTEM_VERSION:UNINITIALIZED=23 + +//No help, variable specified on the command line. +CMAKE_TOOLCHAIN_FILE:UNINITIALIZED=E:\dev\Android\ndk\21.4.7075529\build\cmake\android.toolchain.cmake + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=C:/Users/soyle/StudioProjects/x/y/alpha-wallet-android/app + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=C:/Users/soyle/StudioProjects/x/y/alpha-wallet-android/app/src/main/cpp + + +######################## +# INTERNAL cache entries +######################## + +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=c:/Users/soyle/StudioProjects/x/y/alpha-wallet-android/app +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=18 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=E:/dev/Android/cmake/3.18.1/bin/cmake.exe +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=E:/dev/Android/cmake/3.18.1/bin/cpack.exe +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=E:/dev/Android/cmake/3.18.1/bin/ctest.exe +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Visual Studio 15 2017 +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL=C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=C:/Users/soyle/StudioProjects/x/y/alpha-wallet-android/app/src/main/cpp +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=E:/dev/Android/cmake/3.18.1/share/cmake-3.18 + diff --git a/app/CMakeFiles/3.18.1-g262b901-dirty/CMakeSystem.cmake b/app/CMakeFiles/3.18.1-g262b901-dirty/CMakeSystem.cmake new file mode 100644 index 0000000000..c09d28bbb6 --- /dev/null +++ b/app/CMakeFiles/3.18.1-g262b901-dirty/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Windows-10.0.19044") +set(CMAKE_HOST_SYSTEM_NAME "Windows") +set(CMAKE_HOST_SYSTEM_VERSION "10.0.19044") +set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64") + +include("E:/dev/Android/ndk/21.4.7075529/build/cmake/android.toolchain.cmake") + +set(CMAKE_SYSTEM "Android-1") +set(CMAKE_SYSTEM_NAME "Android") +set(CMAKE_SYSTEM_VERSION "1") +set(CMAKE_SYSTEM_PROCESSOR "i686") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/app/CMakeFiles/cmake.check_cache b/app/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000000..3dccd73172 --- /dev/null +++ b/app/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/app/build.gradle b/app/build.gradle index 32fbbb5c0d..684101d823 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,17 +68,13 @@ android_lint_reporter { repositories { maven { - url = uri("https://maven.pkg.github.com/trustwallet/wallet-core") - credentials { - username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") - password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") - } + url 'https://maven.google.com' } } android { compileSdkVersion 32 - buildToolsVersion '32.0.0' + buildToolsVersion '33.0.0' sourceSets { main { @@ -293,7 +289,7 @@ dependencies { testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9' // Component tests - testImplementation 'org.robolectric:robolectric:4.8' + testImplementation 'org.robolectric:robolectric:4.8.1' testImplementation 'androidx.test:core:1.4.0' testImplementation 'androidx.test.ext:junit:1.1.3' @@ -312,12 +308,13 @@ dependencies { androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0' - implementation 'com.trustwallet:wallet-core:2.6.4' + implementation group: 'com.trustwallet', name: 'wallet-core', version: '2.6.3' + //implementation "com.trustwallet:wallet-core:0.12.31" - implementation 'com.github.florent37:TutoShowcase:d8b91be8a2' + implementation 'com.github.florent37:tutoshowcase:1.0.1' // Do not upgrade unless we have migrated to AndroidX - implementation 'com.github.google:flexbox-layout:2.0.1' + implementation 'com.google.android:flexbox:2.0.1' implementation 'com.github.salomonbrys.kotson:kotson:2.5.0' diff --git a/app/src/analytics/java/com/alphawallet/app/service/AnalyticsService.java b/app/src/analytics/java/com/alphawallet/app/service/AnalyticsService.java index 65439ba943..ddc0907219 100644 --- a/app/src/analytics/java/com/alphawallet/app/service/AnalyticsService.java +++ b/app/src/analytics/java/com/alphawallet/app/service/AnalyticsService.java @@ -8,6 +8,8 @@ import com.alphawallet.app.C; import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ServiceErrorException; +import com.alphawallet.app.repository.KeyProvider; +import com.alphawallet.app.repository.KeyProviderFactory; import com.google.firebase.analytics.FirebaseAnalytics; import com.google.firebase.crashlytics.FirebaseCrashlytics; import com.google.firebase.iid.FirebaseInstanceId; @@ -23,15 +25,9 @@ public class AnalyticsService implements AnalyticsServiceType { private final MixpanelAPI mixpanelAPI; private final FirebaseAnalytics firebaseAnalytics; - public static native String getAnalyticsKey(); - - static { - System.loadLibrary("keys"); - } - public AnalyticsService(Context context) { - mixpanelAPI = MixpanelAPI.getInstance(context, getAnalyticsKey()); + mixpanelAPI = MixpanelAPI.getInstance(context, KeyProviderFactory.get().getAnalyticsKey()); firebaseAnalytics = FirebaseAnalytics.getInstance(context); } diff --git a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java index add8b33be1..ae1f0e471e 100644 --- a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java @@ -1,36 +1,34 @@ package com.alphawallet.app; -import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.Espresso.pressBack; -import static androidx.test.espresso.matcher.ViewMatchers.isRoot; -import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.alphawallet.app.assertions.Should.shouldSee; import static com.alphawallet.app.steps.Steps.createNewWallet; import static com.alphawallet.app.steps.Steps.navigateToBrowser; import static com.alphawallet.app.steps.Steps.selectTestNet; import static com.alphawallet.app.steps.Steps.visit; -import static com.alphawallet.app.util.Helper.waitUntil; import com.alphawallet.app.util.Helper; +import com.alphawallet.app.util.SnapshotUtil; -import org.junit.Ignore; import org.junit.Test; public class DappBrowserTest extends BaseE2ETest { @Test - @Ignore public void should_switch_network() { String urlString = "https://opensea.io"; createNewWallet(); visit(urlString); - onView(isRoot()).perform(waitUntil(withText("Ethereum"), 60)); + shouldSee("Ethereum"); + Helper.wait(5); + SnapshotUtil.take("1"); selectTestNet(); navigateToBrowser(); Helper.wait(3); pressBack(); - onView(isRoot()).perform(waitUntil(withText("Kovan"), 60)); + shouldSee("Görli"); } } diff --git a/app/src/androidTest/java/com/alphawallet/app/ManageNetworkTest.java b/app/src/androidTest/java/com/alphawallet/app/ManageNetworkTest.java index f1c0b79e43..9f51335361 100644 --- a/app/src/androidTest/java/com/alphawallet/app/ManageNetworkTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/ManageNetworkTest.java @@ -1,22 +1,30 @@ package com.alphawallet.app; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.alphawallet.app.assertions.Should.shouldSee; import static com.alphawallet.app.steps.Steps.addNewNetwork; import static com.alphawallet.app.steps.Steps.createNewWallet; import static com.alphawallet.app.steps.Steps.gotoSettingsPage; +import static com.alphawallet.app.steps.Steps.toggleSwitch; +import static com.alphawallet.app.util.Helper.click; + +import androidx.test.espresso.action.ViewActions; -import org.junit.Ignore; import org.junit.Test; public class ManageNetworkTest extends BaseE2ETest { @Test - @Ignore public void should_add_custom_network() { createNewWallet(); gotoSettingsPage(); addNewNetwork("MyTestNet"); + toggleSwitch(R.id.mainnet_header); + click(withText(R.string.action_enable_testnet)); shouldSee("MyTestNet"); } } diff --git a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java index fd72e69fd4..416a5753ea 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java @@ -14,7 +14,6 @@ import android.os.Build; -import org.junit.Ignore; import org.junit.Test; import java.util.HashMap; @@ -25,12 +24,11 @@ public class TransferTest extends BaseE2ETest { // Use different wallet to transfer token from can avoid this error private static final Map WALLETS = new HashMap() {{ put("24", new String[]{"essence allow crisp figure tired task melt honey reduce planet twenty rookie", "0xD0c424B3016E9451109ED97221304DeC639b3F84"}); - put("31", new String[]{"deputy review citizen bacon measure combine bag dose chronic retreat attack fly", "0xD8790c1eA5D15F8149C97F80524AC87f56301204"}); + put("30", new String[]{"deputy review citizen bacon measure combine bag dose chronic retreat attack fly", "0xD8790c1eA5D15F8149C97F80524AC87f56301204"}); put("32", new String[]{"omit mobile upgrade warm flock two era hamster local cat wink virus", "0x32f6F38137a79EA8eA237718b0AFAcbB1c58ca2e"}); }}; @Test - @Ignore public void should_transfer_from_an_account_to_another() { int apiLevel = Build.VERSION.SDK_INT; String[] array = WALLETS.get(String.valueOf(apiLevel)); @@ -53,5 +51,4 @@ public void should_transfer_from_an_account_to_another() { switchToWallet(newWalletAddress); assertBalanceIs("0.001"); } - } diff --git a/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java b/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java index 13cce63446..ac965d7de9 100644 --- a/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java +++ b/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java @@ -1,14 +1,37 @@ package com.alphawallet.app.assertions; import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isRoot; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; +import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.alphawallet.app.util.Helper.waitUntil; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.core.IsInstanceOf.instanceOf; + +import android.widget.TextView; + +import com.alphawallet.app.R; public class Should { + private static final int TIMEOUT_IN_SECONDS = 5 * 60; + public static void shouldSee(String text) { - onView(isRoot()).perform(waitUntil(withSubstring(text), 10 * 60)); + onView(isRoot()).perform(waitUntil(withSubstring(text), TIMEOUT_IN_SECONDS)); + } + + public static void shouldNotSee(String text) + { + onView(isRoot()).perform(waitUntil(not(withSubstring(text)), TIMEOUT_IN_SECONDS)); + } + + public static void shouldSee(int id) + { + onView(isRoot()).perform(waitUntil(withId(id), 10 * 60)); } } diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index bffb5435c9..2ead11d9f2 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -13,6 +13,8 @@ import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.alphawallet.app.assertions.Should.shouldNotSee; +import static com.alphawallet.app.assertions.Should.shouldSee; import static com.alphawallet.app.util.Helper.click; import static com.alphawallet.app.util.Helper.waitUntil; import static com.alphawallet.app.util.RootUtil.isDeviceRooted; @@ -41,7 +43,8 @@ public static void createNewWallet() click(withText(R.string.ok)); } click(withId(R.id.button_create)); - Helper.wait(10); + shouldSee("Select Active Networks"); + pressBack(); click(withText(R.string.action_close)); // works well locally but NOT work with GitHub actions } @@ -63,8 +66,10 @@ public static void selectTestNet() selectMenu("Select Active Networks"); toggleSwitch(R.id.mainnet_header); click(withText(R.string.action_enable_testnet)); - onView(withId(R.id.test_list)).perform(actionOnItemAtPosition(1, ViewActions.click())); // Rinkeby - onView(withId(R.id.test_list)).perform(actionOnItemAtPosition(3, ViewActions.click())); // Kovan + click(withSubstring("Rinkeby")); // Deselect + click(withSubstring("Görli")); // Select +// onView(withId(R.id.test_list)).perform(actionOnItemAtPosition(1, ViewActions.click())); // Rinkeby +// onView(withId(R.id.test_list)).perform(actionOnItemAtPosition(3, ViewActions.click())); // Kovan pressBack(); } @@ -81,14 +86,14 @@ public static void assertBalanceIs(String balanceStr) { public static void ensureTransactionConfirmed() { // onView(withText(R.string.rate_no_thanks)).perform(click()); click(withId(R.string.action_show_tx_details)); - onView(isRoot()).perform(waitUntil(withSubstring("Sent ETH"), 30 * 60)); + onView(isRoot()).perform(waitUntil(withSubstring("Sent"), 30 * 60)); pressBack(); } public static void sendBalanceTo(String receiverAddress, String amountStr) { click(withId(R.id.nav_wallet_text)); - onView(isRoot()).perform(waitUntil(R.id.eth_data, withText(not(startsWith("0"))))); - click(withId(R.id.eth_data)); + ensureBalanceFetched(); + click(withSubstring("ETH")); click(withText("Send")); onView(withHint("0")).perform(replaceText(amountStr)); onView(withHint(R.string.recipient_address)).perform(replaceText(receiverAddress)); @@ -97,6 +102,12 @@ public static void sendBalanceTo(String receiverAddress, String amountStr) { click(withId(R.string.action_confirm)); } + private static void ensureBalanceFetched() + { + shouldSee("Görli (Test)"); + shouldNotSee("0 GöETH"); + } + public static void switchToWallet(String address) { gotoSettingsPage(); click(withText("Change / Add Wallet")); @@ -115,21 +126,21 @@ public static String getWalletAddress() { public static void importWalletFromSettingsPage(String seedPhrase) { gotoSettingsPage(); click(withText("Change / Add Wallet")); - Helper.wait(10); click(withId(R.id.action_add)); // SnapshotUtil.take("after-add"); click(withId(R.id.import_account_action)); onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_seed)))))).perform(replaceText(seedPhrase)); Helper.wait(2); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis click(withId(R.id.import_action)); - Helper.wait(10); + shouldSee("Select Active Networks"); + pressBack(); } public static void gotoSettingsPage() { click(withId(R.id.nav_settings_text)); } - private static void toggleSwitch(int id) { + public static void toggleSwitch(int id) { onView(allOf(withId(R.id.switch_material), isDescendantOfA(withId(id)))).perform(ViewActions.click()); } @@ -143,6 +154,7 @@ public static void addNewNetwork(String name) input(R.id.input_network_symbol, "MTNSYM"); input(R.id.input_network_explorer_api, "http://xxx.yyy.zzz"); input(R.id.input_network_block_explorer_url, "http://xxx.yyy.zzz"); + click(withId(R.id.checkbox_testnet)); click(withId(R.string.action_add_network)); } diff --git a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java index 50211d0d88..4a0144f00e 100644 --- a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java +++ b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java @@ -96,7 +96,7 @@ public void perform(final UiController uiController, final View view) { } public static void click(Matcher matcher) { - Helper.wait(1); //slight pause +// Helper.wait(1); //slight pause onView(isRoot()).perform(Helper.waitUntil(Matchers.allOf(matcher, isDisplayed()))); onView(matcher).perform(ViewActions.click(doNothing())); // if click executed as long press, do nothing and retry clicking } diff --git a/app/src/main/cpp/keys.c b/app/src/main/cpp/keys.c index 1e7545cbc1..147dc8a361 100644 --- a/app/src/main/cpp/keys.c +++ b/app/src/main/cpp/keys.c @@ -34,18 +34,7 @@ #endif JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_repository_EthereumNetworkBase_getAmberDataKey( JNIEnv* env, jobject thiz ) -{ -#if (HAS_KEYS == 1) - return getDecryptedKey(env, amberdataKey); -#else - const jstring key = "obtain-api-key-from-amberdata-io"; - return (*env)->NewStringUTF(env, key); -#endif -} - -JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_repository_EthereumNetworkBase_getInfuraKey( JNIEnv* env, jobject thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getInfuraKey( JNIEnv* env, jobject thiz ) { #if (HAS_KEYS == 1) return getDecryptedKey(env, infuraKey); @@ -58,29 +47,7 @@ Java_com_alphawallet_app_repository_EthereumNetworkBase_getInfuraKey( JNIEnv* en } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_TickerService_getAmberDataKey( JNIEnv* env, jobject thiz ) -{ -#if (HAS_KEYS == 1) - return getDecryptedKey(env, amberdataKey); -#else - const jstring key = "obtain-api-key-from-amberdata-io"; - return (*env)->NewStringUTF(env, key); -#endif -} - -JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_TickerService_getCMCKey( JNIEnv* env, jobject thiz ) -{ -#if (HAS_KEYS == 1) - return getDecryptedKey(env, cmcKey); -#else - const jstring key = "ea2d0a6b-7e77-4015-bccf-4877e5c5b882"; - return (*env)->NewStringUTF(env, key); -#endif -} - -JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_AnalyticsService_getAnalyticsKey( JNIEnv* env, jobject thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getAnalyticsKey( JNIEnv* env, jobject thiz ) { #if (HAS_KEYS == 1) return getDecryptedKey(env, mixpanelKey); @@ -91,7 +58,7 @@ Java_com_alphawallet_app_service_AnalyticsService_getAnalyticsKey( JNIEnv* env, } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_viewmodel_Erc20DetailViewModel_getRampKey( JNIEnv* env, jobject thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getRampKey( JNIEnv* env, jobject thiz ) { #if (HAS_KEYS == 1) return getDecryptedKey(env, rampKey); @@ -102,18 +69,7 @@ Java_com_alphawallet_app_viewmodel_Erc20DetailViewModel_getRampKey( JNIEnv* env, } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_repository_OnRampRepository_getRampKey( JNIEnv* env, jobject thiz ) -{ -#if (HAS_KEYS == 1) - return getDecryptedKey(env, rampKey); -#else - const jstring key = "asfjkdhvcmbnekjfhskjdhfskjdhfskjdhfsdkjf"; // <-- replace with your Ramp key - return (*env)->NewStringUTF(env, key); -#endif -} - -JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_repository_EthereumNetworkBase_getSecondaryInfuraKey( JNIEnv* env, jobject thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getSecondaryInfuraKey( JNIEnv* env, jobject thiz ) { #if (HAS_KEYS == 1) return getDecryptedKey(env, secondaryInfuraKey); @@ -126,7 +82,7 @@ Java_com_alphawallet_app_repository_EthereumNetworkBase_getSecondaryInfuraKey( J } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_repository_EthereumNetworkBase_getKlaytnKey( JNIEnv* env, jobject thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getKlaytnKey( JNIEnv* env, jobject thiz ) { #if (HAS_KEYS == 1) return getDecryptedKey(env, klaytnKey); @@ -136,7 +92,7 @@ Java_com_alphawallet_app_repository_EthereumNetworkBase_getKlaytnKey( JNIEnv* en } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_TransactionsNetworkClient_getBSCExplorerKey( JNIEnv* env, jobject thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getBSCExplorerKey( JNIEnv* env, jobject thiz ) { #if (HAS_KEYS == 1) return getBSCExplorerKey(env); @@ -146,7 +102,7 @@ Java_com_alphawallet_app_service_TransactionsNetworkClient_getBSCExplorerKey( JN } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_TransactionsNetworkClient_getEtherscanKey( JNIEnv* env, jclass thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getEtherscanKey( JNIEnv* env, jclass thiz ) { #if (HAS_KEYS == 1) return getDecryptedKey(env, etherscanKey); @@ -157,18 +113,8 @@ Java_com_alphawallet_app_service_TransactionsNetworkClient_getEtherscanKey( JNIE } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_GasService_getEtherscanKey( JNIEnv* env, jobject thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getMailchimpKey(JNIEnv *env, jclass clazz) { -#if (HAS_KEYS == 1) - return getDecryptedKey(env, etherscanKey); -#else - const jstring key = "6U31FTHW3YYHKW6CYHKKGDPHI9HEJ9PU5F"; - return (*env)->NewStringUTF(env, key); -#endif -} - -JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_widget_EmailPromptView_getMailchimpKey(JNIEnv *env, jclass clazz) { #if (HAS_KEYS == 1) return getDecryptedKey(env, mailchimpKey); #else @@ -178,7 +124,7 @@ Java_com_alphawallet_app_widget_EmailPromptView_getMailchimpKey(JNIEnv *env, jcl } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_GasService_getPolygonScanKey(JNIEnv *env, jobject thiz) { +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getPolygonScanKey(JNIEnv *env, jobject thiz) { #if (HAS_KEYS == 1) return getDecryptedKey(env, polygonScanKey); #elif (HAS_PS == 1) @@ -190,13 +136,7 @@ Java_com_alphawallet_app_service_GasService_getPolygonScanKey(JNIEnv *env, jobje } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_TransactionsNetworkClient_getPolygonScanKey( JNIEnv* env, jclass thiz ) -{ - return Java_com_alphawallet_app_service_GasService_getPolygonScanKey(env, thiz); -} - -JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_TransactionsNetworkClient_getCovalentKey( JNIEnv* env, jclass thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getCovalentKey( JNIEnv* env, jclass thiz ) { #if (HAS_KEYS == 1) return getDecryptedCKey(env, 4, '_', covalentKey); @@ -207,7 +147,7 @@ Java_com_alphawallet_app_service_TransactionsNetworkClient_getCovalentKey( JNIEn } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_TransactionsNetworkClient_getAuroraScanKey( JNIEnv* env, jclass thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getAuroraScanKey( JNIEnv* env, jclass thiz ) { #if (HAS_KEYS == 1) return getDecryptedKey(env, auroraKey); @@ -220,7 +160,7 @@ Java_com_alphawallet_app_service_TransactionsNetworkClient_getAuroraScanKey( JNI } JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_service_OpenSeaService_getOpenSeaKey( JNIEnv* env, jclass thiz ) +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getOpenSeaKey( JNIEnv* env, jclass thiz ) { #if (HAS_KEYS == 1) return getDecryptedKey(env, openSeaKey); @@ -235,5 +175,5 @@ Java_com_alphawallet_app_service_OpenSeaService_getOpenSeaKey( JNIEnv* env, jcla JNIEXPORT jstring JNICALL Java_com_alphawallet_app_util_AWEnsResolver_getOpenSeaKey( JNIEnv* env, jclass thiz ) { - return Java_com_alphawallet_app_service_OpenSeaService_getOpenSeaKey(env, thiz); + return Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getOpenSeaKey(env, thiz); } \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java index 4e56b0fdb1..58edfca635 100644 --- a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java +++ b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java @@ -1,5 +1,7 @@ package com.alphawallet.app.di; +import static com.alphawallet.app.service.KeystoreAccountService.KEYSTORE_FOLDER; + import android.content.Context; import com.alphawallet.app.repository.EthereumNetworkRepository; @@ -49,8 +51,6 @@ import dagger.hilt.components.SingletonComponent; import okhttp3.OkHttpClient; -import static com.alphawallet.app.service.KeystoreAccountService.KEYSTORE_FOLDER; - @Module @InstallIn(SingletonComponent.class) public class RepositoriesModule { @@ -77,9 +77,11 @@ TickerService provideTickerService(OkHttpClient httpClient, PreferenceRepository @Provides EthereumNetworkRepositoryType provideEthereumNetworkRepository( PreferenceRepositoryType preferenceRepository, - @ApplicationContext Context context) { - return new EthereumNetworkRepository(preferenceRepository, context); - } + @ApplicationContext Context context + ) + { + return new EthereumNetworkRepository(preferenceRepository, context); + } @Singleton @Provides @@ -119,14 +121,15 @@ TransactionLocalSource provideTransactionInDiskCache(RealmManager realmManager) return new TransactionsRealmCache(realmManager); } - @Singleton - @Provides + @Singleton + @Provides TransactionsNetworkClientType provideBlockExplorerClient( - OkHttpClient httpClient, - Gson gson, - RealmManager realmManager) { - return new TransactionsNetworkClient(httpClient, gson, realmManager); - } + OkHttpClient httpClient, + Gson gson, + RealmManager realmManager) + { + return new TransactionsNetworkClient(httpClient, gson, realmManager); + } @Singleton @Provides @@ -175,11 +178,14 @@ TransactionsService provideTransactionsService(TokensService tokensService, return new TransactionsService(tokensService, ethereumNetworkRepositoryType, transactionsNetworkClientType, transactionLocalSource); } - @Singleton - @Provides - GasService provideGasService(EthereumNetworkRepositoryType ethereumNetworkRepository, OkHttpClient client, RealmManager realmManager) { - return new GasService(ethereumNetworkRepository, client, realmManager); - } + @Singleton + @Provides + GasService provideGasService(EthereumNetworkRepositoryType ethereumNetworkRepository, + OkHttpClient client, + RealmManager realmManager) + { + return new GasService(ethereumNetworkRepository, client, realmManager); + } @Singleton @Provides diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 7ecba962ae..f2f7b0236f 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -27,8 +27,8 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_TESTNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; @@ -62,7 +62,6 @@ import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenInfo; -import com.alphawallet.app.util.SystemWrapper; import com.alphawallet.app.util.Utils; import com.alphawallet.token.entity.ChainSpec; import com.google.gson.Gson; @@ -88,13 +87,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy { public static final String COVALENT = "[COVALENT]"; - private static final String DEFAULT_HOMEPAGE = "https://alphawallet.com/browser/"; - - private static final String POLYGON_HOMEPAGE = "https://alphawallet.com/browser-item-category/polygon/"; - private static final String GAS_API = "module=gastracker&action=gasoracle"; - private static final String DEFAULT_INFURA_KEY = "da3717f25f824cc1baa32d812386d93f"; + public static final String DEFAULT_INFURA_KEY = "da3717f25f824cc1baa32d812386d93f"; /* constructing URLs from BuildConfig. In the below area you will see hardcoded key like da3717... These hardcoded keys are fallbacks used by AlphaWallet forks. @@ -103,15 +98,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy If you wish your node to be the fallback, tried in case the primary times out then add/replace in ..._FALLBACK_RPC_URL list */ - static { - SystemWrapper.loadLibrary("keys"); - } - - public static native String getAmberDataKey(); - public static native String getInfuraKey(); - public static native String getSecondaryInfuraKey(); - public static native String getKlaytnKey(); - public static final boolean usesProductionKey = !getInfuraKey().equals(DEFAULT_INFURA_KEY); + private static final KeyProvider keyProvider = KeyProviderFactory.get(); + public static final boolean usesProductionKey = !keyProvider.getInfuraKey().equals(DEFAULT_INFURA_KEY); public static final String FREE_MAINNET_RPC_URL = "https://main-rpc.linkpool.io"; public static final String FREE_POLYGON_RPC_URL = "https://polygon-rpc.com"; @@ -127,29 +115,29 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String FREE_PALM_TEST_RPC_URL = "https://palm-testnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b"; public static final String FREE_CRONOS_MAIN_BETA_RPC_URL = "https://evm.cronos.org"; - public static final String MAINNET_RPC_URL = usesProductionKey ? "https://mainnet.infura.io/v3/" + getInfuraKey() + public static final String MAINNET_RPC_URL = usesProductionKey ? "https://mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_MAINNET_RPC_URL; - public static final String RINKEBY_RPC_URL = usesProductionKey ? "https://rinkeby.infura.io/v3/" + getInfuraKey() + public static final String RINKEBY_RPC_URL = usesProductionKey ? "https://rinkeby.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_RINKEBY_RPC_URL; - public static final String KOVAN_RPC_URL = usesProductionKey ? "https://kovan.infura.io/v3/" + getInfuraKey() + public static final String KOVAN_RPC_URL = usesProductionKey ? "https://kovan.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_KOVAN_RPC_URL; - public static final String GOERLI_RPC_URL = usesProductionKey ? "https://goerli.infura.io/v3/" + getInfuraKey() + public static final String GOERLI_RPC_URL = usesProductionKey ? "https://goerli.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_GOERLI_RPC_URL; - public static final String MATIC_RPC_URL = usesProductionKey ? "https://polygon-mainnet.infura.io/v3/" + getInfuraKey() + public static final String MATIC_RPC_URL = usesProductionKey ? "https://polygon-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_POLYGON_RPC_URL; - public static final String ARBITRUM_MAINNET_RPC = usesProductionKey ? "https://arbitrum-mainnet.infura.io/v3/" + getInfuraKey() + public static final String ARBITRUM_MAINNET_RPC = usesProductionKey ? "https://arbitrum-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_ARBITRUM_RPC_URL; - public static final String MUMBAI_TEST_RPC_URL = usesProductionKey ? "https://polygon-mumbai.infura.io/v3/" + getInfuraKey() + public static final String MUMBAI_TEST_RPC_URL = usesProductionKey ? "https://polygon-mumbai.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_MUMBAI_RPC_URL; - public static final String OPTIMISTIC_MAIN_URL = usesProductionKey ? "https://optimism-mainnet.infura.io/v3/" + getInfuraKey() + public static final String OPTIMISTIC_MAIN_URL = usesProductionKey ? "https://optimism-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_OPTIMISM_RPC_URL; - public static final String OPTIMISTIC_TEST_URL = usesProductionKey ? "https://optimism-kovan.infura.io/v3/" + getInfuraKey() + public static final String OPTIMISTIC_TEST_URL = usesProductionKey ? "https://optimism-kovan.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_OPTIMISM_TESTRPC_URL; - public static final String ARBITRUM_TESTNET_RPC = usesProductionKey ? "https://arbitrum-rinkeby.infura.io/v3/" + getInfuraKey() + public static final String ARBITRUM_TESTNET_RPC = usesProductionKey ? "https://arbitrum-rinkeby.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_ARBITRUM_TEST_RPC_URL; - public static final String PALM_RPC_URL = usesProductionKey ? "https://palm-mainnet.infura.io/v3/" + getInfuraKey() + public static final String PALM_RPC_URL = usesProductionKey ? "https://palm-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_PALM_RPC_URL; - public static final String PALM_TEST_RPC_URL = usesProductionKey ? "https://palm-testnet.infura.io/v3/" + getInfuraKey() + public static final String PALM_TEST_RPC_URL = usesProductionKey ? "https://palm-testnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_PALM_TEST_RPC_URL; public static final String USE_KLAYTN_RPC = usesProductionKey ? "https://node-api.klaytnapi.com/v1/klaytn" : KLAYTN_RPC; @@ -158,23 +146,23 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String CRONOS_MAIN_RPC_URL = "https://evm.cronos.org"; // Use the "Free" routes as backup in order to diversify node usage; to avoid single point of failure - public static final String MAINNET_FALLBACK_RPC_URL = usesProductionKey ? FREE_MAINNET_RPC_URL : "https://mainnet.infura.io/v3/" + getSecondaryInfuraKey(); - public static final String RINKEBY_FALLBACK_RPC_URL = usesProductionKey ? FREE_RINKEBY_RPC_URL : "https://rinkeby.infura.io/v3/" + getSecondaryInfuraKey(); - public static final String KOVAN_FALLBACK_RPC_URL = usesProductionKey ? FREE_KOVAN_RPC_URL : "https://kovan.infura.io/v3/" + getSecondaryInfuraKey(); - public static final String GOERLI_FALLBACK_RPC_URL = usesProductionKey ? FREE_GOERLI_RPC_URL : "https://goerli.infura.io/v3/" + getSecondaryInfuraKey(); - public static final String ARBITRUM_FALLBACK_MAINNET_RPC = usesProductionKey ? FREE_ARBITRUM_RPC_URL : "https://arbitrum-mainnet.infura.io/v3/" + getSecondaryInfuraKey(); - public static final String PALM_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-mainnet.infura.io/v3/" + getSecondaryInfuraKey(); - public static final String PALM_TEST_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-testnet.infura.io/v3/" + getSecondaryInfuraKey(); + public static final String MAINNET_FALLBACK_RPC_URL = usesProductionKey ? FREE_MAINNET_RPC_URL : "https://mainnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); + public static final String RINKEBY_FALLBACK_RPC_URL = usesProductionKey ? FREE_RINKEBY_RPC_URL : "https://rinkeby.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); + public static final String KOVAN_FALLBACK_RPC_URL = usesProductionKey ? FREE_KOVAN_RPC_URL : "https://kovan.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); + public static final String GOERLI_FALLBACK_RPC_URL = usesProductionKey ? FREE_GOERLI_RPC_URL : "https://goerli.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); + public static final String ARBITRUM_FALLBACK_MAINNET_RPC = usesProductionKey ? FREE_ARBITRUM_RPC_URL : "https://arbitrum-mainnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); + public static final String PALM_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-mainnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); + public static final String PALM_TEST_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-testnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); //Note that AlphaWallet now uses a double node configuration. See class AWHttpService comment 'try primary node'. //If you supply a main RPC and secondary it will try the secondary if the primary node times out after 10 seconds. //See the declaration of NetworkInfo - it has a member backupNodeUrl. Put your secondary node here. - public static final String ROPSTEN_FALLBACK_RPC_URL = "https://ropsten.infura.io/v3/" + getSecondaryInfuraKey(); + public static final String ROPSTEN_FALLBACK_RPC_URL = "https://ropsten.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); public static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; public static final String XDAI_RPC_URL = com.alphawallet.ethereum.EthereumNetworkBase.XDAI_RPC_URL; public static final String POA_RPC_URL = "https://core.poa.network/"; - public static final String ROPSTEN_RPC_URL = "https://ropsten.infura.io/v3/" + getInfuraKey(); + public static final String ROPSTEN_RPC_URL = "https://ropsten.infura.io/v3/" + keyProvider.getInfuraKey(); public static final String SOKOL_RPC_URL = "https://sokol.poa.network"; public static final String ARTIS_SIGMA1_RPC_URL = "https://rpc.sigma1.artis.network"; public static final String ARTIS_TAU1_RPC_URL = "https://rpc.tau1.artis.network"; @@ -990,24 +978,6 @@ public static int decimalOverride(String address, long chainId) return 0; } - public static String defaultDapp(long chainId) - { - String dapp = (chainId == MATIC_ID || chainId == MATIC_TEST_ID) ? POLYGON_HOMEPAGE : DEFAULT_HOMEPAGE; - return dapp; - } - - public static boolean isWithinHomePage(String url) - { - String homePageRoot = DEFAULT_HOMEPAGE.substring(0, DEFAULT_HOMEPAGE.length() - 1); //remove final slash - return (url != null && url.startsWith(homePageRoot)); - } - - public static boolean isDefaultDapp(String url) - { - return url != null && (url.equals(DEFAULT_HOMEPAGE) - || url.equals(POLYGON_HOMEPAGE)); - } - public Token getBlankOverrideToken(NetworkInfo networkInfo) { return createCurrencyToken(networkInfo); @@ -1138,4 +1108,5 @@ public NetworkInfo getBuiltInNetwork(long chainId) { return builtinNetworkMap.get(chainId); } + } diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java new file mode 100644 index 0000000000..ea4635814c --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java @@ -0,0 +1,17 @@ +package com.alphawallet.app.repository; + +public interface KeyProvider +{ + String getBSCExplorerKey(); + String getAnalyticsKey(); + String getEtherscanKey(); + String getPolygonScanKey(); + String getAuroraScanKey(); + String getCovalentKey(); + String getKlaytnKey(); + String getInfuraKey(); + String getSecondaryInfuraKey(); + String getRampKey(); + String getOpenSeaKey(); + String getMailchimpKey(); +} diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProviderFactory.java b/app/src/main/java/com/alphawallet/app/repository/KeyProviderFactory.java new file mode 100644 index 0000000000..617766e29c --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProviderFactory.java @@ -0,0 +1,8 @@ +package com.alphawallet.app.repository; + +public class KeyProviderFactory +{ + public static KeyProvider get() { + return new KeyProviderJNIImpl(); + } +} diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java new file mode 100644 index 0000000000..908d293530 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java @@ -0,0 +1,22 @@ +package com.alphawallet.app.repository; + +public class KeyProviderJNIImpl implements KeyProvider +{ + public KeyProviderJNIImpl() + { + System.loadLibrary("keys"); + } + + public native String getInfuraKey(); + public native String getSecondaryInfuraKey(); + public native String getBSCExplorerKey(); + public native String getAnalyticsKey(); + public native String getEtherscanKey(); + public native String getPolygonScanKey(); + public native String getAuroraScanKey(); + public native String getCovalentKey(); + public native String getKlaytnKey(); + public native String getRampKey(); + public native String getOpenSeaKey(); + public native String getMailchimpKey(); +} diff --git a/app/src/main/java/com/alphawallet/app/repository/OnRampRepository.java b/app/src/main/java/com/alphawallet/app/repository/OnRampRepository.java index bcd144be34..8c069dfec7 100644 --- a/app/src/main/java/com/alphawallet/app/repository/OnRampRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/OnRampRepository.java @@ -19,13 +19,9 @@ public class OnRampRepository implements OnRampRepositoryType { private static final String RAMP = "ramp"; private static final String ONRAMP_CONTRACTS_FILE_NAME = "onramp_contracts.json"; - static - { - System.loadLibrary("keys"); - } - private final Context context; private final AnalyticsServiceType analyticsService; + private final KeyProvider keyProvider = KeyProviderFactory.get(); public OnRampRepository(Context context, AnalyticsServiceType analyticsService) { @@ -33,8 +29,6 @@ public OnRampRepository(Context context, AnalyticsServiceType analyticsService) this.analyticsService = analyticsService; } - public static native String getRampKey(); - @Override public String getUri(String address, Token token) { @@ -80,7 +74,7 @@ private Uri buildRampUri(String address, String symbol) Uri.Builder builder = new Uri.Builder(); builder.scheme("https") .authority("buy.ramp.network") - .appendQueryParameter("hostApiKey", getRampKey()) + .appendQueryParameter("hostApiKey", keyProvider.getRampKey()) .appendQueryParameter("hostLogoUrl", C.ALPHAWALLET_LOGO_URI) .appendQueryParameter("hostAppName", "AlphaWallet") .appendQueryParameter("userAddress", address); diff --git a/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java index 0c9e44b5bd..99b177faad 100644 --- a/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java +++ b/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java @@ -93,4 +93,7 @@ public interface PreferenceRepositoryType { int getTheme(); void setTheme(int state); + + boolean isNewWallet(String address); + void setNewWallet(String address, boolean isNewWallet); } diff --git a/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java b/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java index 8be1bc9bd9..61fa1e01f9 100644 --- a/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.SharedPreferences; +import androidx.annotation.NonNull; import androidx.preference.PreferenceManager; import com.alphawallet.app.C; @@ -43,6 +44,7 @@ public class SharedPreferenceRepository implements PreferenceRepositoryType { private static final String RATE_APP_SHOWN = "rate_us_shown"; private static final String LAUNCH_COUNT = "launch_count"; + private static final String NEW_WALLET = "new_wallet_"; private final SharedPreferences pref; @@ -364,4 +366,22 @@ public void setTheme(int state) { pref.edit().putInt(THEME_KEY, state).apply(); } + + @Override + public boolean isNewWallet(String address) + { + return pref.getBoolean(keyOf(address), false); + } + + @Override + public void setNewWallet(String address, boolean isNewWallet) + { + pref.edit().putBoolean(keyOf(address), isNewWallet).apply(); + } + + @NonNull + private String keyOf(String address) + { + return NEW_WALLET + address.toLowerCase(Locale.ENGLISH); + } } diff --git a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java index 95c134217c..4fd62fda5e 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java @@ -77,6 +77,7 @@ public class TokenRepository implements TokenRepositoryType { private static final String TAG = "TRT"; private final TokenLocalSource localSource; + private final KeyProvider keyProvider = KeyProviderFactory.get(); private final EthereumNetworkRepositoryType ethereumNetworkRepository; private final OkHttpClient okClient; private final Context context; @@ -118,7 +119,7 @@ public TokenRepository( private void buildWeb3jClient(NetworkInfo networkInfo) { AWHttpService publicNodeService = new AWHttpService(networkInfo.rpcServerUrl, networkInfo.backupNodeUrl, okClient, false); - HttpServiceHelper.addRequiredCredentials(networkInfo.chainId, publicNodeService, EthereumNetworkBase.getKlaytnKey(), EthereumNetworkBase.usesProductionKey); + HttpServiceHelper.addRequiredCredentials(networkInfo.chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(), EthereumNetworkBase.usesProductionKey); web3jNodeServers.put(networkInfo.chainId, Web3j.build(publicNodeService)); } @@ -1190,8 +1191,8 @@ public static Web3j getWeb3jService(long chainId) .writeTimeout(C.LONG_WRITE_TIMEOUT, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); - AWHttpService publicNodeService = new AWHttpService(EthereumNetworkRepository.getNodeURLByNetworkId (chainId), EthereumNetworkRepository.getSecondaryNodeURL(chainId), okClient, false); - HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, EthereumNetworkBase.getKlaytnKey(), EthereumNetworkBase.usesProductionKey); + AWHttpService publicNodeService = new AWHttpService(EthereumNetworkRepository.getNodeURLByNetworkId(chainId), EthereumNetworkRepository.getSecondaryNodeURL(chainId), okClient, false); + HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(), EthereumNetworkBase.usesProductionKey); return Web3j.build(publicNodeService); } diff --git a/app/src/main/java/com/alphawallet/app/service/GasService.java b/app/src/main/java/com/alphawallet/app/service/GasService.java index ac4de27e84..9cd9d142c0 100644 --- a/app/src/main/java/com/alphawallet/app/service/GasService.java +++ b/app/src/main/java/com/alphawallet/app/service/GasService.java @@ -26,6 +26,8 @@ import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; +import com.alphawallet.app.repository.KeyProvider; +import com.alphawallet.app.repository.KeyProviderFactory; import com.alphawallet.app.repository.entity.Realm1559Gas; import com.alphawallet.app.repository.entity.RealmGasSpread; import com.alphawallet.app.web3.entity.Web3Transaction; @@ -85,13 +87,6 @@ public class GasService implements ContractGasProvider @Nullable private Disposable gasFetchDisposable; - static { - System.loadLibrary("keys"); - } - - public static native String getEtherscanKey(); - public static native String getPolygonScanKey(); - public GasService(EthereumNetworkRepositoryType networkRepository, OkHttpClient httpClient, RealmManager realm) { this.networkRepository = networkRepository; @@ -101,8 +96,9 @@ public GasService(EthereumNetworkRepositoryType networkRepository, OkHttpClient this.currentChainId = MAINNET_ID; web3j = null; - ETHERSCAN_API_KEY = "&apikey=" + getEtherscanKey(); - POLYGONSCAN_API_KEY = "&apikey=" + getPolygonScanKey(); + KeyProvider keyProvider = KeyProviderFactory.get(); + ETHERSCAN_API_KEY = "&apikey=" + keyProvider.getEtherscanKey(); + POLYGONSCAN_API_KEY = "&apikey=" + keyProvider.getPolygonScanKey(); keyFail = false; } diff --git a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java index 04aaad1671..0b1b7227b0 100644 --- a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java +++ b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java @@ -12,6 +12,8 @@ import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenFactory; import com.alphawallet.app.entity.tokens.TokenInfo; +import com.alphawallet.app.repository.KeyProviderFactory; +import com.alphawallet.app.repository.KeyProviderJNIImpl; import com.alphawallet.app.util.JsonUtils; import com.alphawallet.ethereum.EthereumNetworkBase; import com.google.gson.Gson; @@ -45,13 +47,6 @@ public class OpenSeaService private final LongSparseArray networkCheckTimes = new LongSparseArray<>(); private final LongSparseArray pageOffsets = new LongSparseArray<>(); - static - { - System.loadLibrary("keys"); - } - - public static native String getOpenSeaKey(); - public OpenSeaService() { pageOffsets.clear(); @@ -71,7 +66,7 @@ private Request buildRequest(long networkId, String api) .method("GET", null) .addHeader("Content-Type", "application/json"); - String apiKey = getOpenSeaKey(); + String apiKey = KeyProviderFactory.get().getOpenSeaKey(); if (networkId != EthereumNetworkBase.RINKEBY_ID && !TextUtils.isEmpty(apiKey) && !apiKey.equals("...")) { requestB.addHeader("X-API-KEY", apiKey); diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java index 5a4aa15f0b..bda363f1af 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java @@ -27,6 +27,8 @@ import com.alphawallet.app.entity.tokens.ERC721Token; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenInfo; +import com.alphawallet.app.repository.KeyProvider; +import com.alphawallet.app.repository.KeyProviderFactory; import com.alphawallet.app.repository.TransactionsRealmCache; import com.alphawallet.app.repository.entity.RealmAuxData; import com.alphawallet.app.repository.entity.RealmToken; @@ -73,34 +75,24 @@ public class TransactionsNetworkClient implements TransactionsNetworkClientType private final String BSC_EXPLORER_API_KEY; private final String POLYGONSCAN_API_KEY; private final String AURORASCAN_API_KEY; + private final KeyProvider keyProvider = KeyProviderFactory.get(); private final OkHttpClient httpClient; private final Gson gson; private final RealmManager realmManager; - static { - System.loadLibrary("keys"); - } - - public static native String getEtherscanKey(); - public static native String getBSCExplorerKey(); - public static native String getCovalentKey(); - public static native String getPolygonScanKey(); - public static native String getAuroraScanKey(); - public TransactionsNetworkClient( OkHttpClient httpClient, Gson gson, - RealmManager realmManager - ) { + RealmManager realmManager) { this.httpClient = httpClient; this.gson = gson; this.realmManager = realmManager; - BSC_EXPLORER_API_KEY = getBSCExplorerKey().length() > 0 ? "&apikey=" + getBSCExplorerKey() : ""; - ETHERSCAN_API_KEY = "&apikey=" + getEtherscanKey(); - POLYGONSCAN_API_KEY = getPolygonScanKey().length() > 3 ? "&apikey=" + getPolygonScanKey() : ""; - AURORASCAN_API_KEY = getAuroraScanKey().length() > 3 ? "&apikey=" + getAuroraScanKey() : ""; + BSC_EXPLORER_API_KEY = keyProvider.getBSCExplorerKey().length() > 0 ? "&apikey=" + keyProvider.getBSCExplorerKey() : ""; + ETHERSCAN_API_KEY = "&apikey=" + keyProvider.getEtherscanKey(); + POLYGONSCAN_API_KEY = keyProvider.getPolygonScanKey().length() > 3 ? "&apikey=" + keyProvider.getPolygonScanKey() : ""; + AURORASCAN_API_KEY = keyProvider.getAuroraScanKey().length() > 3 ? "&apikey=" + keyProvider.getAuroraScanKey() : ""; } @Override @@ -723,7 +715,7 @@ else if (networkInfo.chainId == AURORA_MAINNET_ID || networkInfo.chainId == AURO private EtherscanTransaction[] readCovalentTransactions(TokensService svs, String accountAddress, NetworkInfo networkInfo, boolean ascending, int page, int pageSize) throws JSONException { String covalent = "" + networkInfo.chainId + "/address/" + accountAddress.toLowerCase() + "/transactions_v2/?"; - String args = "block-signed-at-asc=" + (ascending ? "true" : "false") + "&page-number=" + (page - 1) + "&page-size=" + pageSize + "&key=" + getCovalentKey(); //read logs to get all the transfers + String args = "block-signed-at-asc=" + (ascending ? "true" : "false") + "&page-number=" + (page - 1) + "&page-size=" + pageSize + "&key=" + keyProvider.getCovalentKey(); //read logs to get all the transfers String fullUrl = networkInfo.etherscanAPI.replace(COVALENT, covalent); String result = null; @@ -1114,4 +1106,4 @@ private ERC721Token createNewERC721Token(EtherscanEvent ev, NetworkInfo networkI newToken.setTokenWallet(walletAddress); return newToken; } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index 17eb20dbb0..5e22e39c7f 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -872,7 +872,7 @@ private void startBalanceListener() symbol.setVisibility(View.VISIBLE); String newBalanceStr = BalanceUtils.getScaledValueFixed(new BigDecimal(realmToken.getBalance()), ETHER_DECIMALS, TOKEN_BALANCE_PRECISION); balance.setText(newBalanceStr); - symbol.setText(activeNetwork.getShortName()); + symbol.setText(activeNetwork != null ? activeNetwork.getShortName() : ""); }); } @@ -1680,7 +1680,7 @@ private boolean isOnHomePage() if (web3 != null) { String url = web3.getUrl(); - return EthereumNetworkRepository.isDefaultDapp(url); + return DappBrowserUtils.isDefaultDapp(url); } else { @@ -2277,7 +2277,7 @@ private String determineMimeType(@NotNull WebChromeClient.FileChooserParams file private String getDefaultDappUrl() { String customHome = viewModel.getHomePage(getContext()); - return customHome != null ? customHome : EthereumNetworkRepository.defaultDapp(activeNetwork != null ? activeNetwork.chainId : 0); + return customHome != null ? customHome : DappBrowserUtils.defaultDapp(activeNetwork != null ? activeNetwork.chainId : 0); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java index 384d1206ed..88dbc77ed5 100644 --- a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java @@ -33,6 +33,8 @@ import android.widget.LinearLayout; import android.widget.Toast; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; @@ -97,41 +99,48 @@ public class HomeActivity extends BaseNavigationActivity implements View.OnClickListener, HomeCommsInterface, FragmentMessenger, Runnable, SignAuthenticationCallback, LifecycleObserver, PagerCallback { - private HomeViewModel viewModel; + public static final int RC_ASSET_EXTERNAL_WRITE_PERM = 223; + public static final int RC_ASSET_NOTIFICATION_PERM = 224; + public static final int DAPP_BARCODE_READER_REQUEST_CODE = 1; + public static final String STORED_PAGE = "currentPage"; + public static final String RESET_TOKEN_SERVICE = "HOME_reset_ts"; + public static final String AW_MAGICLINK = "aw.app/"; + public static final String AW_MAGICLINK_DIRECT = "openurl?url="; + private static boolean updatePrompt = false; + private final FragmentStateAdapter pager2Adapter; + private final Handler handler = new Handler(Looper.getMainLooper()); + private final ActivityResultLauncher networkSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> getSupportFragmentManager().setFragmentResult(RESET_TOKEN_SERVICE, new Bundle())); + private HomeViewModel viewModel; private Dialog dialog; private ViewPager2 viewPager; - private final FragmentStateAdapter pager2Adapter; private LinearLayout successOverlay; private ImageView successImage; - private final Handler handler = new Handler(Looper.getMainLooper()); private HomeReceiver homeReceiver; private Fragment settingsFragment; private Fragment dappBrowserFragment; private Fragment walletFragment; private Fragment activityFragment; private String walletTitle; - private static boolean updatePrompt = false; private TutoShowcase backupWalletDialog; private boolean isForeground; private volatile boolean tokenClicked = false; private String openLink; - public static final int RC_ASSET_EXTERNAL_WRITE_PERM = 223; - public static final int RC_ASSET_NOTIFICATION_PERM = 224; - - public static final int DAPP_BARCODE_READER_REQUEST_CODE = 1; - public static final String STORED_PAGE = "currentPage"; - public static final String RESET_TOKEN_SERVICE = "HOME_reset_ts"; - public static final String AW_MAGICLINK = "aw.app/"; - public static final String AW_MAGICLINK_DIRECT = "openurl?url="; - public HomeActivity() { // fragment creation is shifted to adapter pager2Adapter = new ScreenSlidePagerAdapter(this); } + public static void setUpdatePrompt() + { + //TODO: periodically check this value (eg during page flipping) + //Set alert to user to update their app + updatePrompt = true; + } + @OnLifecycleEvent(Lifecycle.Event.ON_START) private void onMoveToForeground() { @@ -241,6 +250,7 @@ public void onPageScrollStateChanged(int state) viewModel.walletName().observe(this, this::onWalletName); viewModel.backUpMessage().observe(this, this::onBackup); viewModel.splashReset().observe(this, this::onRequireInit); + viewModel.defaultWallet().observe(this, this::onDefaultWallet); if (CustomViewSettings.hideDappBrowser()) { @@ -301,6 +311,17 @@ public void onPageScrollStateChanged(int state) startService(i); } + private void onDefaultWallet(Wallet wallet) + { + if (viewModel.checkNewWallet(wallet.address)) + { + viewModel.setNewWallet(wallet.address, false); + Intent selectNetworkIntent = new Intent(this, SelectNetworkFilterActivity.class); + selectNetworkIntent.putExtra(C.EXTRA_SINGLE_ITEM, false); + networkSettingsHandler.launch(selectNetworkIntent); + } + } + private void setupFragmentListeners() { //TODO: Move all fragment comms to this model - see all instances of ((HomeActivity)getActivity()). @@ -830,44 +851,6 @@ else if (lastId >= 0 && lastId < WalletPage.values().length) } } - private class ScreenSlidePagerAdapter extends FragmentStateAdapter - { - public ScreenSlidePagerAdapter(@NonNull FragmentActivity fragmentActivity) - { - super(fragmentActivity); - } - - @NonNull - @Override - public Fragment createFragment(int position) - { - switch (WalletPage.values()[position]) - { - case WALLET: - default: - walletFragment = new WalletFragment(); - return walletFragment; - case ACTIVITY: - activityFragment = new ActivityFragment(); - return activityFragment; - case DAPP_BROWSER: - if (CustomViewSettings.hideDappBrowser()) dappBrowserFragment = new Fragment(); - else dappBrowserFragment = new DappBrowserFragment(); - return dappBrowserFragment; - case SETTINGS: - settingsFragment = new NewSettingsFragment(); - return settingsFragment; - } - } - - @Override - public int getItemCount() - { - return WalletPage.values().length; - } - - } - private BaseFragment getFragment(WalletPage page) { //build map, return correct fragment. @@ -1112,13 +1095,6 @@ protected boolean onPrepareOptionsPanel(View view, Menu menu) return super.onPrepareOptionsPanel(view, menu); } - public static void setUpdatePrompt() - { - //TODO: periodically check this value (eg during page flipping) - //Set alert to user to update their app - updatePrompt = true; - } - void postponeWalletBackupWarning(String walletAddress) { removeSettingsBadgeKey(C.KEY_NEEDS_BACKUP); @@ -1241,4 +1217,42 @@ else if (importPath != null) Timber.tag("Intent").w(e); } } + + private class ScreenSlidePagerAdapter extends FragmentStateAdapter + { + public ScreenSlidePagerAdapter(@NonNull FragmentActivity fragmentActivity) + { + super(fragmentActivity); + } + + @NonNull + @Override + public Fragment createFragment(int position) + { + switch (WalletPage.values()[position]) + { + case WALLET: + default: + walletFragment = new WalletFragment(); + return walletFragment; + case ACTIVITY: + activityFragment = new ActivityFragment(); + return activityFragment; + case DAPP_BROWSER: + if (CustomViewSettings.hideDappBrowser()) dappBrowserFragment = new Fragment(); + else dappBrowserFragment = new DappBrowserFragment(); + return dappBrowserFragment; + case SETTINGS: + settingsFragment = new NewSettingsFragment(); + return settingsFragment; + } + } + + @Override + public int getItemCount() + { + return WalletPage.values().length; + } + + } } \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java index 1cc542358e..6df7564f8d 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java @@ -281,7 +281,7 @@ else if (requestCode == C.IMPORT_REQUEST_CODE) if (importedWallet != null) { requiresHomeRefresh = true; - viewModel.setDefaultWallet(importedWallet); + viewModel.setDefaultWallet(importedWallet, true); } } } @@ -377,7 +377,7 @@ private void onFetchWallets(Wallet[] wallets) private void onCreatedWallet(Wallet wallet) { hideToolbar(); - viewModel.setDefaultWallet(wallet); + viewModel.setDefaultWallet(wallet, true); callNewWalletPage(wallet); finish(); } @@ -401,7 +401,7 @@ private void onError(ErrorEnvelope errorEnvelope) private void onSetWalletDefault(Wallet wallet) { requiresHomeRefresh = true; - viewModel.setDefaultWallet(wallet); + viewModel.setDefaultWallet(wallet, false); } private void hideDialog() diff --git a/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java b/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java index 19772ff72f..caee2ace81 100644 --- a/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java +++ b/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java @@ -46,13 +46,6 @@ public class AWEnsResolver extends EnsResolver private final Context context; private final OkHttpClient client; - static - { - System.loadLibrary("keys"); - } - - public static native String getOpenSeaKey(); - public AWEnsResolver(Web3j web3j, Context context) { super(web3j, DEFAULT_SYNC_THRESHOLD); diff --git a/app/src/main/java/com/alphawallet/app/util/DappBrowserUtils.java b/app/src/main/java/com/alphawallet/app/util/DappBrowserUtils.java index 06e4fc6a94..0ddfd35f75 100644 --- a/app/src/main/java/com/alphawallet/app/util/DappBrowserUtils.java +++ b/app/src/main/java/com/alphawallet/app/util/DappBrowserUtils.java @@ -1,7 +1,8 @@ package com.alphawallet.app.util; -import static com.alphawallet.app.repository.EthereumNetworkBase.isWithinHomePage; import static com.alphawallet.app.util.Utils.isValidUrl; +import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_TEST_ID; import android.content.Context; import android.content.SharedPreferences; @@ -31,6 +32,8 @@ public class DappBrowserUtils { private static final String DAPPS_LIST_FILENAME = "dapps_list.json"; private static final String MY_DAPPS_FILE = "mydapps"; private static final String DAPPS_HISTORY_FILE = "dappshistory"; + private static final String DEFAULT_HOMEPAGE = "https://alphawallet.com/browser/"; + private static final String POLYGON_HOMEPAGE = "https://alphawallet.com/browser-item-category/polygon/"; //TODO: Move to database public static void saveToPrefs(Context context, List myDapps) { @@ -253,4 +256,21 @@ private static void blankPrefEntry(Context context, String key) .putString(key, "") .apply(); } + + public static String defaultDapp(long chainId) + { + return (chainId == MATIC_ID || chainId == MATIC_TEST_ID) ? POLYGON_HOMEPAGE : DEFAULT_HOMEPAGE; + } + + public static boolean isWithinHomePage(String url) + { + String homePageRoot = DEFAULT_HOMEPAGE.substring(0, DEFAULT_HOMEPAGE.length() - 1); //remove final slash + return (url != null && url.startsWith(homePageRoot)); + } + + public static boolean isDefaultDapp(String url) + { + return (DEFAULT_HOMEPAGE.equals(url) + || POLYGON_HOMEPAGE.equals(url)); + } } diff --git a/app/src/main/java/com/alphawallet/app/util/SystemWrapper.java b/app/src/main/java/com/alphawallet/app/util/SystemWrapper.java deleted file mode 100644 index 2b504534c1..0000000000 --- a/app/src/main/java/com/alphawallet/app/util/SystemWrapper.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.alphawallet.app.util; - -public class SystemWrapper -{ - public static void loadLibrary(String name) { - System.loadLibrary(name); - } -} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java index 6610cb26af..1f9cf79837 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java @@ -187,6 +187,10 @@ public LiveData splashReset() { return splashActivity; } + public LiveData defaultWallet() { + return defaultWallet; + } + public void prepare(Activity activity) { progress.postValue(false); disposable = genericWalletInteract @@ -724,4 +728,14 @@ public void onServiceDisconnected(ComponentName name) WCUtils.startServiceLocal(activity, connection, WalletConnectActions.CONNECT); } + + public boolean checkNewWallet(String address) + { + return preferenceRepository.isNewWallet(address); + } + + public void setNewWallet(String address, boolean isNewWallet) + { + preferenceRepository.setNewWallet(address, isNewWallet); + } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java index 2deefeb9c3..5bb14189f2 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java @@ -98,6 +98,8 @@ public void StoreHDKey(String address, KeyService.AuthenticationLevel authLevel) { wallets.postValue(new Wallet[0]); } + + preferenceRepository.setNewWallet(address, true); } public void completeAuthentication(Operation taskCode) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java index 252967fea6..41f43774c9 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java @@ -25,6 +25,7 @@ import com.alphawallet.app.interact.SetDefaultWalletInteract; import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; +import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.repository.TokenRepositoryType; import com.alphawallet.app.router.HomeRouter; @@ -70,6 +71,7 @@ public class WalletsViewModel extends BaseViewModel implements ServiceSyncCallba private final TokensService tokensService; private final AWEnsResolver ensResolver; private final AssetDefinitionService assetService; + private final PreferenceRepositoryType preferenceRepository; private final EthereumNetworkRepositoryType ethereumNetworkRepository; private final TokenRepositoryType tokenRepository; @@ -113,6 +115,7 @@ public class WalletsViewModel extends BaseViewModel implements ServiceSyncCallba TokenRepositoryType tokenRepository, TickerService tickerService, AssetDefinitionService assetService, + PreferenceRepositoryType preferenceRepository, @ApplicationContext Context context) { this.setDefaultWalletInteract = setDefaultWalletInteract; @@ -126,7 +129,7 @@ public class WalletsViewModel extends BaseViewModel implements ServiceSyncCallba this.tokenRepository = tokenRepository; this.tickerService = tickerService; this.assetService = assetService; - + this.preferenceRepository = preferenceRepository; this.tokensService = new TokensService(ethereumNetworkRepository, tokenRepository, tickerService, null, null); ensResolver = new AWEnsResolver(TokenRepository.getWeb3jService(MAINNET_ID), context); @@ -154,8 +157,9 @@ public LiveData createWalletError() } public LiveData noWalletsError() { return noWalletsError; } - public void setDefaultWallet(Wallet wallet) + public void setDefaultWallet(Wallet wallet, boolean isNewWallet) { + preferenceRepository.setNewWallet(wallet.address, isNewWallet); disposable = setDefaultWalletInteract .set(wallet) .subscribe(() -> onDefaultWallet(wallet), this::onError); diff --git a/app/src/main/java/com/alphawallet/app/widget/EmailPromptView.java b/app/src/main/java/com/alphawallet/app/widget/EmailPromptView.java index 918969906f..82ed5c7365 100644 --- a/app/src/main/java/com/alphawallet/app/widget/EmailPromptView.java +++ b/app/src/main/java/com/alphawallet/app/widget/EmailPromptView.java @@ -1,6 +1,5 @@ package com.alphawallet.app.widget; -import android.app.Activity; import android.content.Context; import android.os.Handler; import android.text.InputType; @@ -8,16 +7,14 @@ import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; -import android.widget.FrameLayout; import android.widget.LinearLayout; import androidx.annotation.LayoutRes; import com.alphawallet.app.R; import com.alphawallet.app.entity.StandardFunctionInterface; -import com.alphawallet.app.ui.HomeActivity; +import com.alphawallet.app.repository.KeyProviderFactory; import com.alphawallet.app.util.KeyboardUtils; -import com.alphawallet.app.util.Utils; import com.google.android.material.bottomsheet.BottomSheetDialog; import com.mailchimp.sdk.api.model.Contact; import com.mailchimp.sdk.api.model.ContactStatus; @@ -31,10 +28,6 @@ public class EmailPromptView extends LinearLayout implements StandardFunctionInterface { - static { - System.loadLibrary("keys"); - } - private BottomSheetDialog parentDialog; public void setParentDialog(BottomSheetDialog parentDialog) { @@ -88,7 +81,7 @@ public void handleClick(String action, int actionId) { return ; } - String sdkKey = getMailchimpKey(); + String sdkKey = KeyProviderFactory.get().getMailchimpKey(); try { KeyboardUtils.hideKeyboard(this); diff --git a/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java b/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java new file mode 100644 index 0000000000..f95f12fea2 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java @@ -0,0 +1,39 @@ +package com.alphawallet.app.di; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.app.repository.EthereumNetworkBase; +import com.alphawallet.shadows.ShadowApp; +import com.alphawallet.shadows.ShadowKeyProviderFactory; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowApp.class, ShadowKeyProviderFactory.class}) +public class EthereumNetworkBaseTest +{ + @Test + public void should_getNodeURLByNetworkId_when_use_production_key() + { + assertThat(EthereumNetworkBase.getNodeURLByNetworkId(61L), equalTo("https://www.ethercluster.com/etc")); + assertThat(EthereumNetworkBase.getNodeURLByNetworkId(100L), equalTo("https://rpc.ankr.com/gnosis")); + } + + @Test + public void should_construct_infura_url_when_getNodeURLByNetworkId_given_production_key() + { + assertThat(EthereumNetworkBase.getNodeURLByNetworkId(1L), equalTo("https://mainnet.infura.io/v3/fake-key-for-testing")); + assertThat(EthereumNetworkBase.getNodeURLByNetworkId(3L), equalTo("https://ropsten.infura.io/v3/fake-key-for-testing")); + } + + @Test + public void should_get_main_net_url_when_getNodeURLByNetworkId_given_not_existed_network_id() + { + assertThat(EthereumNetworkBase.getNodeURLByNetworkId(Integer.MAX_VALUE), equalTo("https://mainnet.infura.io/v3/fake-key-for-testing")); + } +} diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java new file mode 100644 index 0000000000..1c29aadac8 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java @@ -0,0 +1,80 @@ +package com.alphawallet.app.di.mock; + +import com.alphawallet.app.repository.KeyProvider; + +public class KeyProviderMockImpl implements KeyProvider +{ + private static final String FAKE_KEY_FOR_TESTING = "fake-key-for-testing"; + + @Override + public String getBSCExplorerKey() + { + return "mock-bsc-explorer-key"; + } + + @Override + public String getAnalyticsKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getEtherscanKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getPolygonScanKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getAuroraScanKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getCovalentKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getKlaytnKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getInfuraKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getSecondaryInfuraKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getRampKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getOpenSeaKey() + { + return FAKE_KEY_FOR_TESTING; + } + + @Override + public String getMailchimpKey() + { + return FAKE_KEY_FOR_TESTING; + } +} diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java new file mode 100644 index 0000000000..a8c55b4a1c --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java @@ -0,0 +1,79 @@ +package com.alphawallet.app.di.mock; + +import com.alphawallet.app.repository.EthereumNetworkBase; +import com.alphawallet.app.repository.KeyProvider; + +public class KeyProviderMockNonProductionImpl implements KeyProvider +{ + @Override + public String getInfuraKey() + { + return EthereumNetworkBase.DEFAULT_INFURA_KEY; + } + + @Override + public String getBSCExplorerKey() + { + return null; + } + + @Override + public String getAnalyticsKey() + { + return null; + } + + @Override + public String getEtherscanKey() + { + return null; + } + + @Override + public String getPolygonScanKey() + { + return null; + } + + @Override + public String getAuroraScanKey() + { + return null; + } + + @Override + public String getCovalentKey() + { + return null; + } + + @Override + public String getKlaytnKey() + { + return null; + } + + @Override + public String getSecondaryInfuraKey() + { + return null; + } + + @Override + public String getRampKey() + { + return null; + } + + @Override + public String getOpenSeaKey() + { + return null; + } + + @Override + public String getMailchimpKey() + { + return null; + } +} diff --git a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java index a044c6d97c..525f48bef9 100644 --- a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java +++ b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java @@ -7,7 +7,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.alphawallet.shadows.ShadowApp; -import com.alphawallet.shadows.ShadowSystemWrapper; import org.junit.Test; import org.junit.runner.RunWith; @@ -17,7 +16,7 @@ import java.util.HashMap; @RunWith(AndroidJUnit4.class) -@Config(shadows = {ShadowSystemWrapper.class, ShadowApp.class}) +@Config(shadows = {ShadowApp.class}) public class HttpServiceHelperTest { private final HttpService httpService = new HttpService(); diff --git a/app/src/test/java/com/alphawallet/app/ui/HomeActivityTest.java b/app/src/test/java/com/alphawallet/app/ui/HomeActivityTest.java new file mode 100644 index 0000000000..27426d5673 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/ui/HomeActivityTest.java @@ -0,0 +1,40 @@ +package com.alphawallet.app.ui; + +import static org.junit.Assert.assertEquals; +import static org.robolectric.Shadows.shadowOf; + +import android.content.Intent; + +import androidx.test.core.app.ActivityScenario; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.shadows.ShadowAnalyticsService; +import com.alphawallet.shadows.ShadowApp; +import com.alphawallet.shadows.ShadowKeyProviderFactory; +import com.alphawallet.shadows.ShadowKeyService; +import com.alphawallet.shadows.ShadowRealmManager; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowPackageManager; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowApp.class, ShadowKeyProviderFactory.class, ShadowRealmManager.class, ShadowKeyService.class, ShadowAnalyticsService.class, ShadowPackageManager.class}) +public class HomeActivityTest +{ + @Test + public void should_show_splash_when_first_launch() + { + ShadowPackageManager shadowPackageManager = new ShadowPackageManager(); + shadowPackageManager.setInstallSourceInfo(RuntimeEnvironment.getApplication().getPackageName(), "", ""); + + ActivityScenario launch = ActivityScenario.launch(HomeActivity.class); + launch.onActivity(activity -> { + Intent expectedIntent = new Intent(activity, SplashActivity.class); + Intent actual = shadowOf(RuntimeEnvironment.getApplication()).getNextStartedActivity(); + assertEquals(expectedIntent.getComponent(), actual.getComponent()); + }); + } +} diff --git a/app/src/test/java/com/alphawallet/app/util/DappBrowserUtilsTest.java b/app/src/test/java/com/alphawallet/app/util/DappBrowserUtilsTest.java new file mode 100644 index 0000000000..53667ce629 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/util/DappBrowserUtilsTest.java @@ -0,0 +1,36 @@ +package com.alphawallet.app.util; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class DappBrowserUtilsTest +{ + @Test + public void testDefaultDapp() + { + assertThat(DappBrowserUtils.defaultDapp(1L), equalTo("https://alphawallet.com/browser/")); + assertThat(DappBrowserUtils.defaultDapp(137L), equalTo("https://alphawallet.com/browser-item-category/polygon/")); + assertThat(DappBrowserUtils.defaultDapp(80001L), equalTo("https://alphawallet.com/browser-item-category/polygon/")); + } + + @Test + public void testIsDefaultDapp() + { + assertTrue(DappBrowserUtils.isDefaultDapp("https://alphawallet.com/browser/")); + assertTrue(DappBrowserUtils.isDefaultDapp("https://alphawallet.com/browser-item-category/polygon/")); + assertFalse(DappBrowserUtils.isDefaultDapp("https://app.1inch.finance/")); + } + + @Test + public void testIsWithinHomePage() + { + assertTrue(DappBrowserUtils.isWithinHomePage("https://alphawallet.com/browser")); + assertTrue(DappBrowserUtils.isWithinHomePage("https://alphawallet.com/browser/")); + assertTrue(DappBrowserUtils.isWithinHomePage("https://alphawallet.com/browser/xxx")); + assertFalse(DappBrowserUtils.isWithinHomePage("https://alphawallet1.com/browser")); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java b/app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java new file mode 100644 index 0000000000..55373f1793 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java @@ -0,0 +1,46 @@ +package com.alphawallet.app.viewmodel; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.app.repository.SharedPreferenceRepository; +import com.alphawallet.shadows.ShadowRealm; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowRealm.class}) +public class HomeViewModelTest +{ + private HomeViewModel homeViewModel; + + @Before + public void setUp() throws Exception + { + SharedPreferenceRepository sharedPreferenceRepository = new SharedPreferenceRepository(RuntimeEnvironment.getApplication()); + homeViewModel = new HomeViewModel(sharedPreferenceRepository, null, null, null, null, null, null, null, null, null, null, null, null, null); + } + + @Test + public void should_not_be_new_wallet_by_default() + { + String address = "0x1"; + assertThat(homeViewModel.checkNewWallet(address), is(false)); + } + + @Test + public void should_set_is_new_wallet() + { + String address = "0x1"; + homeViewModel.setNewWallet(address, true); + assertThat(homeViewModel.checkNewWallet(address), is(true)); + homeViewModel.setNewWallet(address, false); + assertThat(homeViewModel.checkNewWallet(address), is(false)); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowAnalyticsService.java b/app/src/test/java/com/alphawallet/shadows/ShadowAnalyticsService.java new file mode 100644 index 0000000000..92ebf64d31 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowAnalyticsService.java @@ -0,0 +1,20 @@ +package com.alphawallet.shadows; + +import android.content.Context; + +import com.alphawallet.app.service.AnalyticsService; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(AnalyticsService.class) +public class ShadowAnalyticsService +{ + @Implementation + public void __constructor__(Context context) { + } + + @Implementation + public void identify(String uuid) { + } +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowEthereumNetworkBase.java b/app/src/test/java/com/alphawallet/shadows/ShadowEthereumNetworkBase.java new file mode 100644 index 0000000000..2bbc70f178 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowEthereumNetworkBase.java @@ -0,0 +1,22 @@ +package com.alphawallet.shadows; + +import com.alphawallet.app.repository.EthereumNetworkBase; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(EthereumNetworkBase.class) +public class ShadowEthereumNetworkBase +{ + @Implementation + public static String getKlaytnKey() + { + return "klaytn-key"; + } + + @Implementation + public static String getInfuraKey() + { + return "infura-key"; + } +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowKeyProviderFactory.java b/app/src/test/java/com/alphawallet/shadows/ShadowKeyProviderFactory.java new file mode 100644 index 0000000000..1a1e331b48 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowKeyProviderFactory.java @@ -0,0 +1,19 @@ +package com.alphawallet.shadows; + +import com.alphawallet.app.di.mock.KeyProviderMockImpl; +import com.alphawallet.app.repository.KeyProvider; +import com.alphawallet.app.repository.KeyProviderFactory; +import com.alphawallet.app.repository.KeyProviderJNIImpl; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.RealObject; + +@Implements(KeyProviderFactory.class) +public class ShadowKeyProviderFactory +{ + @Implementation + public static KeyProvider get() { + return new KeyProviderMockImpl(); + } +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowKeyProviderFactoryNonProduction.java b/app/src/test/java/com/alphawallet/shadows/ShadowKeyProviderFactoryNonProduction.java new file mode 100644 index 0000000000..850cc3ab21 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowKeyProviderFactoryNonProduction.java @@ -0,0 +1,18 @@ +package com.alphawallet.shadows; + + +import com.alphawallet.app.di.mock.KeyProviderMockNonProductionImpl; +import com.alphawallet.app.repository.KeyProvider; +import com.alphawallet.app.repository.KeyProviderFactory; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(KeyProviderFactory.class) +public class ShadowKeyProviderFactoryNonProduction +{ + @Implementation + public static KeyProvider get() { + return new KeyProviderMockNonProductionImpl(); + } +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowKeyService.java b/app/src/test/java/com/alphawallet/shadows/ShadowKeyService.java new file mode 100644 index 0000000000..cabcea9e51 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowKeyService.java @@ -0,0 +1,19 @@ +package com.alphawallet.shadows; + +import android.content.Context; + +import com.alphawallet.app.entity.AnalyticsProperties; +import com.alphawallet.app.service.AnalyticsServiceType; +import com.alphawallet.app.service.KeyService; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(KeyService.class) +public class ShadowKeyService +{ + @Implementation + public void __constructor__(Context ctx, AnalyticsServiceType analyticsService) { + + } +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowRealm.java b/app/src/test/java/com/alphawallet/shadows/ShadowRealm.java index bdf60aab39..31d6a2a093 100644 --- a/app/src/test/java/com/alphawallet/shadows/ShadowRealm.java +++ b/app/src/test/java/com/alphawallet/shadows/ShadowRealm.java @@ -2,7 +2,6 @@ import android.content.Context; -import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; @@ -11,7 +10,8 @@ @Implements(Realm.class) public class ShadowRealm { + @Implementation public static synchronized void init(Context context) { } -} +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowRealmManager.java b/app/src/test/java/com/alphawallet/shadows/ShadowRealmManager.java new file mode 100644 index 0000000000..aedf5183f9 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowRealmManager.java @@ -0,0 +1,30 @@ +package com.alphawallet.shadows; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import com.alphawallet.app.repository.entity.RealmAuxData; +import com.alphawallet.app.service.RealmManager; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +import io.realm.Realm; +import io.realm.RealmQuery; + +@Implements(RealmManager.class) +public class ShadowRealmManager +{ + @Implementation + public Realm getRealmInstance(String walletAddress) + { + Realm realm = mock(Realm.class); + RealmAuxData auxData = mock(RealmAuxData.class); + RealmQuery realmQuery = mock(RealmQuery.class); + doReturn(realmQuery).when(realmQuery).equalTo(anyString(), anyString()); + doReturn(auxData).when(realmQuery).findFirst(); + doReturn(realmQuery).when(realm).where(RealmAuxData.class); + return realm; + } +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowSystemWrapper.java b/app/src/test/java/com/alphawallet/shadows/ShadowSystemWrapper.java deleted file mode 100644 index 1c4ebecc95..0000000000 --- a/app/src/test/java/com/alphawallet/shadows/ShadowSystemWrapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.alphawallet.shadows; - -import com.alphawallet.app.util.SystemWrapper; - -import org.robolectric.annotation.Implementation; -import org.robolectric.annotation.Implements; - -@Implements(SystemWrapper.class) -public class ShadowSystemWrapper -{ - @Implementation - public static void loadLibrary(String name) - { - } -} diff --git a/build.gradle b/build.gradle index 97a3b10baf..8a3dd0c8a4 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ buildscript { repositories { // don't add anything here until you read to the bottom of this bracket google() + jcenter() mavenCentral() maven { url 'https://jitpack.io' } // WARNING WARNING WARNING @@ -26,6 +27,7 @@ buildscript { allprojects { repositories { google() + jcenter() mavenCentral() maven { url 'https://jitpack.io' } // WARNING WARNING WARNING diff --git a/contracts/TokenScript-Repo b/contracts/TokenScript-Repo deleted file mode 160000 index 3972756505..0000000000 --- a/contracts/TokenScript-Repo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 397275650552783c95dc4252e2c8139644ded343 diff --git a/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java b/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java index 56091278fc..11d4e5eee4 100644 --- a/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java +++ b/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java @@ -392,11 +392,6 @@ private void checkTokensOwnedByMagicLinkCreator(MagicLinkData data) throws Excep } } - @Value("${repository.dir}") - public void setRepoDir(String value) { - repoDir = Paths.get(value); - } - public static void main(String[] args) throws IOException { // TODO: should run System.exit() if IOException addresses = new HashMap>(); SpringApplication.run(AppSiteController.class, args); diff --git a/dmz/src/main/resources/application.properties b/dmz/src/main/resources/application.properties index ae4a5c18cb..e69de29bb2 100644 --- a/dmz/src/main/resources/application.properties +++ b/dmz/src/main/resources/application.properties @@ -1 +0,0 @@ -repository.dir=../../TokenScript-Repo From d8d2df5bf6a86c1dd1b1dbcddfcb92c7af3e5dd9 Mon Sep 17 00:00:00 2001 From: justindg Date: Fri, 19 Aug 2022 00:52:06 -0700 Subject: [PATCH 061/183] Change "paste" button to "clear" when edittext has contents (#2769) * Change "paste" button to "clear" when edittext has contents * unit tests Co-authored-by: Seaborn Lee --- .../alphawallet/app/widget/InputAddress.java | 60 ++++++---- .../app/widget/InputAddressTest.java | 107 ++++++++++++++++++ .../alphawallet/shadows/ShadowUserAvatar.java | 24 ++++ 3 files changed, 171 insertions(+), 20 deletions(-) create mode 100644 app/src/test/java/com/alphawallet/app/widget/InputAddressTest.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowUserAvatar.java diff --git a/app/src/main/java/com/alphawallet/app/widget/InputAddress.java b/app/src/main/java/com/alphawallet/app/widget/InputAddress.java index 69d1e39aed..aceca3cb04 100644 --- a/app/src/main/java/com/alphawallet/app/widget/InputAddress.java +++ b/app/src/main/java/com/alphawallet/app/widget/InputAddress.java @@ -1,7 +1,6 @@ package com.alphawallet.app.widget; import static android.content.Context.CLIPBOARD_SERVICE; - import static com.alphawallet.app.entity.tokenscript.TokenscriptFunction.ZERO_ADDRESS; import android.app.Activity; @@ -14,13 +13,11 @@ import android.text.TextUtils; import android.text.TextWatcher; import android.util.AttributeSet; -import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.AutoCompleteTextView; import android.widget.ImageButton; -import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; @@ -57,6 +54,34 @@ public class InputAddress extends RelativeLayout implements ItemClickListener, E private final RelativeLayout boxLayout; private final TextView errorText; private final Context context; + private final ENSHandler ensHandler; + private final Pattern findAddress = Pattern.compile("^(\\s?)+(0x)([0-9a-fA-F]{40})(\\s?)+\\z"); + private final float standardTextSize; + private final View.OnClickListener pasteListener = new OnClickListener() + { + @Override + public void onClick(View view) + { + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE); + try + { + CharSequence textToPaste = clipboard.getPrimaryClip().getItemAt(0).getText(); + editText.append(textToPaste); + } + catch (Exception e) + { + Timber.e(e); + } + } + }; + private final View.OnClickListener clearListener = new OnClickListener() + { + @Override + public void onClick(View view) + { + editText.getText().clear(); + } + }; private int labelResId; private int hintRedId; private boolean noCam; @@ -64,12 +89,9 @@ public class InputAddress extends RelativeLayout implements ItemClickListener, E private String fullAddress; private String ensName; private boolean handleENS = false; - private final ENSHandler ensHandler; private AWalletAlertDialog dialog; private AddressReadyCallback addressReadyCallback = null; private long chainOverride; - private final Pattern findAddress = Pattern.compile("^(\\s?)+(0x)([0-9a-fA-F]{40})(\\s?)+\\z"); - private final float standardTextSize; public InputAddress(Context context, AttributeSet attrs) { @@ -158,20 +180,7 @@ private void setViews() editText.setHint(hintRedId); - //Paste - pasteItem.setOnClickListener(v -> { - //from clipboard - ClipboardManager clipboard = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE); - try - { - CharSequence textToPaste = clipboard.getPrimaryClip().getItemAt(0).getText(); - editText.append(textToPaste); - } - catch (Exception e) - { - Timber.e(e, e.getMessage()); - } - }); + pasteItem.setOnClickListener(pasteListener); if (noCam) { @@ -522,6 +531,17 @@ public void afterTextChanged(Editable s) { ensHandler.checkAddress(); } + + if (TextUtils.isEmpty(s)) + { + pasteItem.setText(R.string.paste); + pasteItem.setOnClickListener(pasteListener); + } + else + { + pasteItem.setText(R.string.action_clear); + pasteItem.setOnClickListener(clearListener); + } } public void setEnsNodeNotSyncCallback(EnsNodeNotSyncCallback callback) diff --git a/app/src/test/java/com/alphawallet/app/widget/InputAddressTest.java b/app/src/test/java/com/alphawallet/app/widget/InputAddressTest.java new file mode 100644 index 0000000000..a1a90bcf87 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/widget/InputAddressTest.java @@ -0,0 +1,107 @@ +package com.alphawallet.app.widget; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.app.R; +import com.alphawallet.app.ui.SendActivity; +import com.alphawallet.app.ui.widget.entity.AddressReadyCallback; +import com.alphawallet.shadows.ShadowApp; +import com.alphawallet.shadows.ShadowUserAvatar; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.android.controller.ActivityController; +import org.robolectric.annotation.Config; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowApp.class, ShadowUserAvatar.class}) +public class InputAddressTest +{ + private InputAddress inputAddress; + private TextView addressText; + private TextView pasteButton; + + @Before + public void setUp() throws Exception + { + ActivityController activityController = Robolectric.buildActivity(SendActivity.class); + SendActivity sendActivity = activityController.get(); + inputAddress = new InputAddress(sendActivity, null); + inputAddress.setAddressCallback(new AddressReadyCallback() + { + @Override + public void addressReady(String address, String ensName) + { + + } + }); + initViews(); + } + + @Test + public void should_paste_and_clean_address() + { + assertThat(pasteButton.getText(), equalTo("Paste")); + + setClipboardText("this_is_an_address"); + pasteButton.performClick(); + + assertThat(getAddress(), equalTo("this_is_an_address")); + assertThat(pasteButton.getText(), equalTo("Clear")); + + pasteButton.performClick(); + assertThat(getAddress(), equalTo("")); + assertThat(pasteButton.getText(), equalTo("Paste")); + } + + @Test + public void should_trigger_callback_after_text_changed() + { + AddressReadyCallback mock = mock(AddressReadyCallback.class); + inputAddress.setAddressCallback(mock); + + setClipboardText("not_an_address"); + pasteButton.performClick(); + verify(mock).addressValid(false); + + pasteButton.performClick(); // Clear + setClipboardText("0xD8790c1eA5D15F8149C97F80524AC87f56301204"); + pasteButton.performClick(); + verify(mock).addressValid(true); + } + + @NonNull + private String getAddress() + { + return addressText.getText().toString(); + } + + private void initViews() + { + addressText = inputAddress.findViewById(R.id.edit_text); + pasteButton = inputAddress.findViewById(R.id.text_paste); + } + + private void setClipboardText(String text) + { + ClipboardManager clipboardManager = (ClipboardManager) RuntimeEnvironment.getApplication().getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("label", text); + clipboardManager.setPrimaryClip(clip); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowUserAvatar.java b/app/src/test/java/com/alphawallet/shadows/ShadowUserAvatar.java new file mode 100644 index 0000000000..dc2a3807b9 --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowUserAvatar.java @@ -0,0 +1,24 @@ +package com.alphawallet.shadows; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +import com.alphawallet.app.widget.UserAvatar; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowView; + +@Implements(UserAvatar.class) +public class ShadowUserAvatar extends ShadowView +{ + public void __constructor__(Context context, AttributeSet attrs) + { + } + + @Implementation + public void resetBinding() + { + } +} From 8357bac0d8b814e27bc678f08c233b7e1c9ed33b Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 19 Aug 2022 20:37:46 +1000 Subject: [PATCH 062/183] ENSIP Resolution (#2770) * ENSIP work * Update ENSIP10 with working unit tests --- .../com/alphawallet/app/ui/SendActivity.java | 10 +- .../app/ui/TransferNFTActivity.java | 8 +- .../app/ui/widget/entity/ENSHandler.java | 13 +- .../alphawallet/app/util/AWEnsResolver.java | 134 ++++- .../com/alphawallet/app/util/EnsResolver.java | 376 ------------ .../java/com/alphawallet/app/util/Utils.java | 4 + .../viewmodel/NameThisWalletViewModel.java | 8 +- .../alphawallet/app/web3j/ens/Contracts.java | 42 ++ .../app/web3j/ens/EnsException.java | 28 + .../app/web3j/ens/EnsGatewayRequestDTO.java | 34 ++ .../app/web3j/ens/EnsGatewayResponseDTO.java | 34 ++ .../app/web3j/ens/EnsResolutionException.java | 28 + .../app/web3j/ens/EnsResolver.java | 544 ++++++++++++++++++ .../alphawallet/app/web3j/ens/EnsUtils.java | 46 ++ .../alphawallet/app/web3j/ens/NameHash.java | 107 ++++ .../app/web3j/ens/OffchainLookup.java | 157 +++++ .../app/web3j/ens/RecordTypes.java | 27 + .../alphawallet/app/widget/InputAddress.java | 5 +- .../java/com/alphawallet/app/ENSTest.java | 140 +++++ .../java/com/alphawallet/app/TextUtils.java | 34 ++ 20 files changed, 1366 insertions(+), 413 deletions(-) delete mode 100644 app/src/main/java/com/alphawallet/app/util/EnsResolver.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/Contracts.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/EnsException.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/EnsGatewayRequestDTO.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/EnsGatewayResponseDTO.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolutionException.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolver.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/EnsUtils.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/OffchainLookup.java create mode 100644 app/src/main/java/com/alphawallet/app/web3j/ens/RecordTypes.java create mode 100644 app/src/test/java/com/alphawallet/app/ENSTest.java diff --git a/app/src/main/java/com/alphawallet/app/ui/SendActivity.java b/app/src/main/java/com/alphawallet/app/ui/SendActivity.java index d608f7ba76..13b18bf069 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SendActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SendActivity.java @@ -481,8 +481,8 @@ protected void onDestroy() if (handler != null) handler.removeCallbacksAndMessages(null); if (amountInput != null) amountInput.onDestroy(); if (confirmationDialog != null) confirmationDialog.onDestroy(); - if (addressInput != null) - addressInput.setEnsNodeNotSyncCallback(null); // prevent leak by removing reference to activity method + //if (addressInput != null) + // addressInput.setEnsNodeNotSyncCallback(null); // prevent leak by removing reference to activity method } private void setupTokenContent() @@ -492,8 +492,8 @@ private void setupTokenContent() addressInput = findViewById(R.id.input_address); addressInput.setAddressCallback(this); addressInput.setChainOverrideForWalletConnect(token.tokenInfo.chainId); - addressInput.setEnsHandlerNodeSyncFlag(true); // allow node sync - addressInput.setEnsNodeNotSyncCallback(this::showNodeNotSyncSheet); // callback to invoke if node not synced + //addressInput.setEnsHandlerNodeSyncFlag(true); // allow node sync + //addressInput.setEnsNodeNotSyncCallback(this::showNodeNotSyncSheet); // callback to invoke if node not synced FunctionButtonBar functionBar = findViewById(R.id.layoutButtons); functionBar.revealButtons(); List functions = new ArrayList<>(Collections.singletonList(R.string.action_next)); @@ -712,7 +712,7 @@ void showNodeNotSyncSheet() alertDialog.setButtonListener(v -> alertDialog.dismiss()); alertDialog.setSecondaryButtonText(R.string.ignore); alertDialog.setSecondaryButtonListener(v -> { - addressInput.setEnsHandlerNodeSyncFlag(false); // skip node sync check + //addressInput.setEnsHandlerNodeSyncFlag(false); // skip node sync check // re enter current input to resolve again String currentInput = addressInput.getEditText().getText().toString(); addressInput.getEditText().setText(""); diff --git a/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java b/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java index f98dedcaed..8d72636e54 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java @@ -9,7 +9,6 @@ import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; -import android.util.Log; import android.util.Pair; import android.view.View; import android.view.WindowManager; @@ -55,7 +54,6 @@ import com.alphawallet.token.tools.Numeric; import org.jetbrains.annotations.NotNull; -import org.web3j.protocol.core.methods.response.EthEstimateGas; import java.math.BigDecimal; import java.math.BigInteger; @@ -63,8 +61,6 @@ import java.util.Collections; import java.util.List; -import javax.inject.Inject; - import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; @@ -117,7 +113,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) addressInput = findViewById(R.id.input_address); addressInput.setAddressCallback(this); - addressInput.setEnsNodeNotSyncCallback(this); + //addressInput.setEnsNodeNotSyncCallback(this); sendAddress = null; ensAddress = null; @@ -522,7 +518,7 @@ public void onNodeNotSynced() dialog.setButtonListener(v -> dialog.dismiss()); dialog.setSecondaryButtonText(R.string.ignore); dialog.setSecondaryButtonListener(v -> { - addressInput.setEnsHandlerNodeSyncFlag(false); // skip node sync check + //addressInput.setEnsHandlerNodeSyncFlag(false); // skip node sync check // re enter current input to resolve again String currentInput = addressInput.getEditText().getText().toString(); addressInput.getEditText().setText(""); diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ENSHandler.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ENSHandler.java index 39b421441f..558b3ce4dc 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ENSHandler.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ENSHandler.java @@ -4,20 +4,18 @@ * Created by JB on 28/10/2020. */ +import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; + import android.content.Context; import android.os.Handler; import android.os.Looper; -import android.text.Editable; import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.TypedValue; import androidx.annotation.Nullable; import androidx.preference.PreferenceManager; import com.alphawallet.app.C; import com.alphawallet.app.R; -import com.alphawallet.app.entity.EnsNodeNotSyncCallback; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.ui.widget.adapter.AutoCompleteAddressAdapter; import com.alphawallet.app.util.AWEnsResolver; @@ -34,9 +32,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -import timber.log.Timber; - -import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; /** * Created by James on 4/12/2018. @@ -335,9 +330,9 @@ private void storeHistory(HashMap history) PreferenceManager.getDefaultSharedPreferences(host.getContext()).edit().putString(C.ENS_HISTORY_PAIR, historyJson).apply(); } - public void setEnsNodeNotSyncCallback(EnsNodeNotSyncCallback callback) + /*public void setEnsNodeNotSyncCallback(EnsNodeNotSyncCallback callback) { Timber.d("setEnsNodeNotSyncCallback: "); ensResolver.nodeNotSyncCallback = callback; - } + }*/ } diff --git a/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java b/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java index caee2ace81..9dd8056406 100644 --- a/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java +++ b/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java @@ -10,14 +10,22 @@ import com.alphawallet.app.service.OpenSeaService; import com.alphawallet.app.util.das.DASBody; import com.alphawallet.app.util.das.DASRecord; +import com.alphawallet.app.web3j.ens.EnsResolver; import com.alphawallet.token.tools.Numeric; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.json.JSONObject; +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.Utf8String; +import org.web3j.ens.NameHash; import org.web3j.protocol.Web3j; import org.web3j.protocol.http.HttpService; +import java.math.BigInteger; +import java.util.Arrays; import java.util.HashMap; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -43,16 +51,25 @@ public class AWEnsResolver extends EnsResolver private static final String DAS_PAYLOAD = "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"das_searchAccount\",\"params\":[\"" + DAS_NAME + "\"]}"; private static final String OPENSEA_IMAGE_PREVIEW = "image_preview_url"; private static final String OPENSEA_IMAGE_ORIGINAL = "image_original_url"; //in case of SVG; Opensea breaks SVG compression + public static final String CRYPTO_RESOLVER = "0xD1E5b0FF1287aA9f9A268759062E4Ab08b9Dacbe"; + public static final String CRYPTO_ETH_KEY = "crypto.ETH.address"; private final Context context; private final OkHttpClient client; - + public AWEnsResolver(Web3j web3j, Context context) { - super(web3j, DEFAULT_SYNC_THRESHOLD); + super(web3j); this.context = context; this.client = setupClient(); } + public AWEnsResolver(Web3j web3j) + { + super(web3j); + this.context = null; + this.client = setupClient(); + } + /** * Given an address, find any corresponding ENS name (eg fredblogs.eth) * @@ -71,7 +88,7 @@ public Single reverseResolveEns(String address) if (!TextUtils.isEmpty(ensName)) { //check ENS name integrity - it must point to the wallet address - String resolveAddress = resolve(ensName, true); + String resolveAddress = resolve(ensName); if (!resolveAddress.equalsIgnoreCase(address)) { ensName = ""; @@ -206,6 +223,7 @@ private enum LocatorType public String checkENSHistoryForAddress(String address) { String ensName = ""; + if (context == null) return ensName; //try previously resolved names String historyJson = PreferenceManager.getDefaultSharedPreferences(context).getString(C.ENS_HISTORY_PAIR, ""); if (historyJson.length() > 0) @@ -225,6 +243,7 @@ public String checkENSHistoryForAddress(String address) private String fetchPreviouslyUsedENS(String address) { String ensName = ""; + if (context == null) return ensName; //try previously resolved names String historyJson = PreferenceManager.getDefaultSharedPreferences(context).getString(C.ENS_HISTORY_PAIR, ""); if (historyJson.length() > 0) @@ -269,16 +288,16 @@ public Single resolveENSAddress(String ensName, boolean performNodeSync) { return Single.fromCallable(() -> { - Timber.d("Verify: " + ensName); + Timber.d("Verify: %s", ensName); String address = ""; if (!isValidEnsName(ensName)) return ""; try { - address = resolve(ensName, performNodeSync); + address = resolve(ensName); } catch (Exception e) { - Timber.d("Verify: error: " + e.getMessage()); + Timber.d("Verify: error: %s", e.getMessage()); // no action } return address; @@ -286,15 +305,33 @@ public Single resolveENSAddress(String ensName, boolean performNodeSync) } @Override - public String resolve(String ensName, boolean performSync) + public String resolve(String ensName) throws Exception { - if (!TextUtils.isEmpty(ensName) && ensName.endsWith(".bit")) + if (TextUtils.isEmpty(ensName)) + { + return ""; + } + if (ensName.endsWith(".bit")) { return resolveDAS(ensName); } + else if (ensName.endsWith(".crypto")) //check crypto namespace + { + byte[] nameHash = NameHash.nameHashAsBytes(ensName); + BigInteger nameId = new BigInteger(nameHash); + String resolverAddress = getContractData(CRYPTO_RESOLVER, getResolverOf(nameId), ""); + if (!TextUtils.isEmpty(resolverAddress)) + { + return getContractData(resolverAddress, get(nameId), ""); + } + else + { + return ""; + } + } else { - return super.resolve(ensName, performSync); + return super.resolve(ensName); } } @@ -335,6 +372,85 @@ private String resolveDAS(String ensName) return ""; } + private Function getResolverOf(BigInteger nameId) + { + return new Function("resolverOf", + Arrays.asList(new org.web3j.abi.datatypes.Uint(nameId)), + Arrays.asList(new TypeReference
() + { + })); + } + + private Function getAvatar(byte[] nameHash) + { + return new Function("text", + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash), + new org.web3j.abi.datatypes.Utf8String("avatar")), + Arrays.asList(new TypeReference() + { + })); + } + + private Function getResolver(byte[] nameHash) + { + return new Function("resolver", + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash)), + Arrays.asList(new TypeReference
() + { + })); + } + + private Function get(BigInteger nameId) + { + return new Function("get", + Arrays.asList(new org.web3j.abi.datatypes.Utf8String(CRYPTO_ETH_KEY), new org.web3j.abi.datatypes.generated.Uint256(nameId)), + Arrays.asList(new TypeReference() + { + })); + } + + public String resolveAvatar(String ensName) + { + if (isValidEnsName(ensName, addressLength)) + { + try + { + String resolverAddress = getResolverAddress(ensName); + if (!TextUtils.isEmpty(resolverAddress)) + { + byte[] nameHash = NameHash.nameHashAsBytes(ensName); + //now attempt to get the address of this ENS + return getContractData(resolverAddress, getAvatar(nameHash), ""); + } + } + catch (Exception e) + { + // + Timber.e(e); + } + } + + return ""; + } + + public String resolveAvatarFromAddress(String address) + { + if (Utils.isAddressValid(address)) + { + try + { + String ensName = reverseResolve(address); + return resolveAvatar(ensName); + } + catch (Exception e) + { + Timber.e(e); + } + } + + return ""; + } + private OkHttpClient setupClient() { return new OkHttpClient.Builder() diff --git a/app/src/main/java/com/alphawallet/app/util/EnsResolver.java b/app/src/main/java/com/alphawallet/app/util/EnsResolver.java deleted file mode 100644 index c3ae165f69..0000000000 --- a/app/src/main/java/com/alphawallet/app/util/EnsResolver.java +++ /dev/null @@ -1,376 +0,0 @@ -package com.alphawallet.app.util; - -import android.os.Handler; -import android.os.Looper; -import android.text.TextUtils; - -import com.alphawallet.app.BuildConfig; -import com.alphawallet.app.entity.EnsNodeNotSyncCallback; -import com.alphawallet.app.entity.UnableToResolveENS; -import com.alphawallet.app.entity.tokenscript.TokenscriptFunction; -import com.alphawallet.app.repository.TokenRepository; -import com.fasterxml.jackson.core.JsonParseException; - -import org.web3j.abi.FunctionEncoder; -import org.web3j.abi.FunctionReturnDecoder; -import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.Utf8String; -import org.web3j.crypto.Keys; -import org.web3j.ens.Contracts; -import org.web3j.ens.EnsResolutionException; -import org.web3j.ens.NameHash; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.core.DefaultBlockParameterName; -import org.web3j.protocol.core.methods.response.EthBlock; -import org.web3j.protocol.core.methods.response.EthCall; -import org.web3j.protocol.core.methods.response.EthSyncing; -import org.web3j.protocol.core.methods.response.NetVersion; -import org.web3j.utils.Numeric; - -import java.io.InterruptedIOException; -import java.math.BigInteger; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.List; - -import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; - -import timber.log.Timber; - -/** - * EnsResolver from Web3j adapted for Android Java's BigInteger - */ -public class EnsResolver -{ - - public static final long DEFAULT_SYNC_THRESHOLD = 1000 * 60 * 3; - public static final String REVERSE_NAME_SUFFIX = ".addr.reverse"; - public static final String CRYPTO_RESOLVER = "0xD1E5b0FF1287aA9f9A268759062E4Ab08b9Dacbe"; - public static final String CRYPTO_ETH_KEY = "crypto.ETH.address"; - - private final Web3j web3j; - private final int addressLength; - private long syncThreshold; // non-final in case this value needs to be tweaked - - public EnsNodeNotSyncCallback nodeNotSyncCallback = null; - - public EnsResolver(Web3j web3j, long syncThreshold, int addressLength) - { - this.web3j = web3j; - this.syncThreshold = syncThreshold; - this.addressLength = addressLength; - } - - public EnsResolver(Web3j web3j, long syncThreshold) - { - this(web3j, syncThreshold, Keys.ADDRESS_LENGTH_IN_HEX); - } - - public EnsResolver(Web3j web3j) - { - this(web3j, DEFAULT_SYNC_THRESHOLD); - } - - public void setSyncThreshold(long syncThreshold) - { - this.syncThreshold = syncThreshold; - } - - public long getSyncThreshold() - { - return syncThreshold; - } - - /** - * This function takes ensName (eg 'scotty.eth') and returns the matching Ethereum Address. - * NOTE: It is highly important to check the node is synced before resolving, as this could be an attack - * - * @param ensName - * @return - */ - public String resolve(String ensName, boolean performSync) - { - Timber.d("resolve %s, %s", ensName, performSync); - String contractAddress = ensName; - if (isValidEnsName(ensName, addressLength)) - { - try - { // performSync used to skip syncing if required by user - if (performSync && !isSynced()) //ensure node is synced - { - Timber.d("resolve: node not synced"); - if (nodeNotSyncCallback != null) - { - new Handler(Looper.getMainLooper()).post(() -> nodeNotSyncCallback.onNodeNotSynced()); - } - throw new EnsResolutionException("Node is not currently synced"); - } - else if (ensName.endsWith(".crypto")) //check crypto namespace - { - byte[] nameHash = NameHash.nameHashAsBytes(ensName); - BigInteger nameId = new BigInteger(nameHash); - String resolverAddress = getContractData(MAINNET_ID, CRYPTO_RESOLVER, getResolverOf(nameId)); - if (!TextUtils.isEmpty(resolverAddress)) - { - contractAddress = getContractData(MAINNET_ID, resolverAddress, get(nameId)); - } - } - else - { - String resolverAddress = lookupResolver(ensName); - if (!TextUtils.isEmpty(resolverAddress)) - { - byte[] nameHash = NameHash.nameHashAsBytes(ensName); - //now attempt to get the address of this ENS - contractAddress = getContractData(MAINNET_ID, resolverAddress, getAddr(nameHash)); - } - } - } - catch (Exception e) - { - //throw new RuntimeException("Unable to execute Ethereum request", e); - return ""; - } - - if (!Utils.isAddressValid(contractAddress)) - { - //throw new RuntimeException("Unable to resolve address for name: " + ensName); - return ""; - } - else - { - return contractAddress; - } - } - else - { - return ensName; - } - } - - /** - * Reverse name resolution as documented in the specification. - * - * @param address an ethereum address, example: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" - * @return a EnsName registered for provided address - */ - public String reverseResolve(String address) throws UnableToResolveENS - { - String name = ""; - if (Utils.isAddressValid(address)) - { - String reverseName = Numeric.cleanHexPrefix(address) + REVERSE_NAME_SUFFIX; - try - { - String resolverAddress = lookupResolver(reverseName); - byte[] nameHash = NameHash.nameHashAsBytes(reverseName); - name = getContractData(MAINNET_ID, resolverAddress, getName(nameHash)); - } - catch (Exception e) - { - //throw new RuntimeException("Unable to execute Ethereum request", e); - return ""; - } - - if (!isValidEnsName(name, addressLength)) - { - throw new UnableToResolveENS("Unable to resolve name for address: " + address); - } - else - { - return name; - } - } - else - { - throw new EnsResolutionException("Address is invalid: " + address); - } - } - - public String resolveAvatar(String ensName) - { - if (isValidEnsName(ensName, addressLength)) - { - try - { - String resolverAddress = lookupResolver(ensName); - if (!TextUtils.isEmpty(resolverAddress)) - { - byte[] nameHash = NameHash.nameHashAsBytes(ensName); - //now attempt to get the address of this ENS - return getContractData(MAINNET_ID, resolverAddress, getAvatar(nameHash)); - } - } - catch (Exception e) - { - // - Timber.e(e); - } - } - - return ""; - } - - public String resolveAvatarFromAddress(String address) - { - if (Utils.isAddressValid(address)) - { - String reverseName = Numeric.cleanHexPrefix(address.toLowerCase()) + REVERSE_NAME_SUFFIX; - try - { - String resolverAddress = lookupResolver(reverseName); - byte[] nameHash = NameHash.nameHashAsBytes(reverseName); - String avatar = getContractData(MAINNET_ID, resolverAddress, getAvatar(nameHash)); - return avatar != null ? avatar : ""; - } - catch (Exception e) - { - Timber.e(e); - //throw new RuntimeException("Unable to execute Ethereum request", e); - } - } - - return ""; - } - - private String lookupResolver(String ensName) throws Exception - { - NetVersion netVersion = web3j.netVersion().send(); - String registryContract = Contracts.resolveRegistryContract(netVersion.getNetVersion()); - byte[] nameHash = NameHash.nameHashAsBytes(ensName); - Function resolver = getResolver(nameHash); - return getContractData(MAINNET_ID, registryContract, resolver); - } - - private Function getResolver(byte[] nameHash) - { - return new Function("resolver", - Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash)), - Arrays.asList(new TypeReference
() - { - })); - } - - private Function getAvatar(byte[] nameHash) - { - return new Function("text", - Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash), - new org.web3j.abi.datatypes.Utf8String("avatar")), - Arrays.asList(new TypeReference() - { - })); - } - - private Function getResolverOf(BigInteger nameId) - { - return new Function("resolverOf", - Arrays.asList(new org.web3j.abi.datatypes.Uint(nameId)), - Arrays.asList(new TypeReference
() - { - })); - } - - private Function get(BigInteger nameId) - { - return new Function("get", - Arrays.asList(new org.web3j.abi.datatypes.Utf8String(EnsResolver.CRYPTO_ETH_KEY), new org.web3j.abi.datatypes.generated.Uint256(nameId)), - Arrays.asList(new TypeReference() - { - })); - } - - private Function getAddr(byte[] nameHash) - { - return new Function("addr", - Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash)), - Arrays.asList(new TypeReference
() - { - })); - } - - private Function getName(byte[] nameHash) - { - return new Function("name", - Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash)), - Arrays.asList(new TypeReference() - { - })); - } - - boolean isSynced() throws Exception - { - EthSyncing ethSyncing = web3j.ethSyncing().send(); - if (ethSyncing.isSyncing()) - { - return false; - } - else - { - EthBlock ethBlock = - web3j.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, false).send(); - long timestamp = ethBlock.getBlock().getTimestamp().longValue() * 1000; - - return System.currentTimeMillis() - syncThreshold < timestamp; - } - } - - private String callSmartContractFunction( - Function function, String contractAddress, long chainId) throws Exception - { - try - { - String encodedFunction = FunctionEncoder.encode(function); - - org.web3j.protocol.core.methods.request.Transaction transaction - = createEthCallTransaction(TokenscriptFunction.ZERO_ADDRESS, contractAddress, encodedFunction); - EthCall response = TokenRepository.getWeb3jService(chainId).ethCall(transaction, DefaultBlockParameterName.LATEST).send(); - - return response.getValue(); - } - catch (InterruptedIOException | UnknownHostException | JsonParseException e) - { - //expected to happen when user switches wallets - return "0x"; - } - } - - private T getContractData(long chainId, String address, Function function) throws Exception - { - String responseValue = callSmartContractFunction(function, address, chainId); - - if (TextUtils.isEmpty(responseValue)) - { - throw new Exception("Bad contract value"); - } - else if (responseValue.equals("0x")) - { - return (T) ""; - } - - List response = FunctionReturnDecoder.decode( - responseValue, function.getOutputParameters()); - if (response.size() == 1) - { - return (T) response.get(0).getValue(); - } - else - { - return (T) ""; - } - } - - public static boolean isValidEnsName(String input) - { - return isValidEnsName(input, Keys.ADDRESS_LENGTH_IN_HEX); - } - - public static boolean isValidEnsName(String input, int addressLength) - { - return input != null && input.contains(".") && input.length() > 4; - } -} diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index c096d2c3c2..ef70103546 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -962,4 +962,8 @@ else if (context instanceof ContextWrapper) return false; } } + + public static String removeDoubleQuotes(String string) { + return string != null ? string.replace("\"", "") : null; + } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java index 9bfabf8ded..5349c83bb4 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java @@ -1,6 +1,8 @@ package com.alphawallet.app.viewmodel; +import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; + import android.content.Context; import android.text.TextUtils; @@ -12,21 +14,17 @@ import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.repository.WalletItem; import com.alphawallet.app.util.AWEnsResolver; -import com.alphawallet.app.util.EnsResolver; import javax.annotation.Nullable; import javax.inject.Inject; import dagger.hilt.android.lifecycle.HiltViewModel; import dagger.hilt.android.qualifiers.ApplicationContext; -import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import io.realm.Realm; -import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; - @HiltViewModel public class NameThisWalletViewModel extends BaseViewModel { @@ -104,7 +102,7 @@ public void setWalletName(String name, Realm.Transaction.OnSuccess onSuccess) public boolean checkEnsName(String newName, Realm.Transaction.OnSuccess onSuccess) { - if (!TextUtils.isEmpty(newName) && EnsResolver.isValidEnsName(newName)) + if (!TextUtils.isEmpty(newName) && AWEnsResolver.isValidEnsName(newName)) { //does this new name correspond to ENS? ensResolver.resolveENSAddress(newName, true) diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/Contracts.java b/app/src/main/java/com/alphawallet/app/web3j/ens/Contracts.java new file mode 100644 index 0000000000..bb9766db73 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/Contracts.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.alphawallet.app.web3j.ens; + +import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; + +/** ENS registry contract addresses. */ +public class Contracts { + + public static final String MAINNET = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; + public static final String ROPSTEN = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; + public static final String RINKEBY = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; + public static final String GOERLI = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; + + public static String resolveRegistryContract(long chainId) { + if (chainId == MAINNET_ID) { + return MAINNET; + } else if (chainId == ROPSTEN_ID) { + return ROPSTEN; + } else if (chainId == RINKEBY_ID) { + return RINKEBY; + } else if (chainId == GOERLI_ID) { + return GOERLI; + } else { + throw new EnsResolutionException( + "Unable to resolve ENS registry contract for network id: " + chainId); + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/EnsException.java b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsException.java new file mode 100644 index 0000000000..5be79d87ee --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2022 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.alphawallet.app.web3j.ens; + +public class EnsException extends RuntimeException { + + public EnsException(Throwable cause) { + super(cause); + } + + public EnsException(String message) { + super(message); + } + + public EnsException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/EnsGatewayRequestDTO.java b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsGatewayRequestDTO.java new file mode 100644 index 0000000000..c05f922ec4 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsGatewayRequestDTO.java @@ -0,0 +1,34 @@ +package com.alphawallet.app.web3j.ens; + +/* + * Copyright 2022 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +// https://eips.ethereum.org/EIPS/eip-3668#use-of-get-and-post-requests-for-the-gateway-interface +public class EnsGatewayRequestDTO { + + private String data; + + public EnsGatewayRequestDTO() {} + + public EnsGatewayRequestDTO(String data) { + this.data = data; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/EnsGatewayResponseDTO.java b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsGatewayResponseDTO.java new file mode 100644 index 0000000000..c41f7ed6da --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsGatewayResponseDTO.java @@ -0,0 +1,34 @@ +package com.alphawallet.app.web3j.ens; + +/* + * Copyright 2022 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +// https://eips.ethereum.org/EIPS/eip-3668#use-of-get-and-post-requests-for-the-gateway-interface +public class EnsGatewayResponseDTO { + + private String data; + + public EnsGatewayResponseDTO() {} + + public EnsGatewayResponseDTO(String data) { + this.data = data; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolutionException.java b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolutionException.java new file mode 100644 index 0000000000..31a83fb362 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolutionException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.alphawallet.app.web3j.ens; + +/** ENS resolution exception. */ +public class EnsResolutionException extends EnsException { + public EnsResolutionException(String message) { + super(message); + } + + public EnsResolutionException(Throwable cause) { + super(cause); + } + + public EnsResolutionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolver.java b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolver.java new file mode 100644 index 0000000000..89702abc08 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolver.java @@ -0,0 +1,544 @@ +/* + * Copyright 2019 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.alphawallet.app.web3j.ens; + +import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; + +import android.text.TextUtils; + +import com.alphawallet.app.entity.tokenscript.TokenscriptFunction; +import com.alphawallet.app.util.Utils; +import com.alphawallet.token.entity.ContractAddress; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.web3j.abi.DefaultFunctionReturnDecoder; +import org.web3j.abi.FunctionEncoder; +import org.web3j.abi.FunctionReturnDecoder; +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.Bool; +import org.web3j.abi.datatypes.DynamicBytes; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.Type; +import org.web3j.abi.datatypes.Utf8String; +import org.web3j.crypto.Keys; +import org.web3j.crypto.WalletUtils; +import org.web3j.protocol.ObjectMapperFactory; +import org.web3j.protocol.Web3j; +import org.web3j.protocol.core.DefaultBlockParameterName; +import org.web3j.protocol.core.methods.response.EthCall; +import org.web3j.protocol.core.methods.response.NetVersion; +import org.web3j.tx.ClientTransactionManager; +import org.web3j.tx.TransactionManager; +import org.web3j.utils.Numeric; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InterruptedIOException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; + +/** Resolution logic for contract addresses. According to https://eips.ethereum.org/EIPS/eip-2544 */ +public class EnsResolver { + + private static final Logger log = LoggerFactory.getLogger(EnsResolver.class); + + public static final long DEFAULT_SYNC_THRESHOLD = 1000 * 60 * 3; + public static final MediaType JSON = MediaType.parse("application/json"); + + // Permit number offchain calls for a single contract call. + public static final int LOOKUP_LIMIT = 4; + + public static final String REVERSE_NAME_SUFFIX = ".addr.reverse"; + + private final Web3j web3j; + protected final int addressLength; + private final TransactionManager transactionManager; + protected final long chainId; + + private OkHttpClient client = new OkHttpClient(); + + private static DefaultFunctionReturnDecoder decoder; + + public EnsResolver(Web3j web3j, int addressLength) + { + this.web3j = web3j; + transactionManager = new ClientTransactionManager(web3j, null); // don't use empty string + this.addressLength = addressLength; + + long chainId = 1; + + try + { + NetVersion v = web3j.netVersion().send(); + String ver = v.getNetVersion(); + chainId = Long.parseLong(ver); + } + catch (Exception e) + { + // + } + + this.chainId = chainId; + } + + public EnsResolver(Web3j web3j) { + this(web3j, Keys.ADDRESS_LENGTH_IN_HEX); + } + + protected ContractAddress obtainOffchainResolverAddr(String ensName) throws Exception + { + return new ContractAddress(chainId, getResolverAddress(ensName)); + } + + /** + * Returns the address of the resolver for the specified node. + * + * @param ensName The specified node. + * @return address of the resolver. + */ + public String resolve(String ensName) throws Exception + { + if (TextUtils.isEmpty(ensName) || (ensName.trim().length() == 1 && ensName.contains("."))) { + return null; + } + + try { + if (isValidEnsName(ensName, addressLength)) + { + ContractAddress resolverAddress = obtainOffchainResolverAddr(ensName); + + boolean supportWildcard = + supportsInterface(EnsUtils.ENSIP_10_INTERFACE_ID, resolverAddress.address); + byte[] nameHash = NameHash.nameHashAsBytes(ensName); + + String resolvedName; + if (supportWildcard) { + String dnsEncoded = NameHash.dnsEncode(ensName); + String addrFunction = encodeResolverAddr(nameHash); + + EthCall result = + resolve( + Numeric.hexStringToByteArray(dnsEncoded), + Numeric.hexStringToByteArray(addrFunction), + resolverAddress.address); + + String lookupDataHex = result.isReverted() ? Utils.removeDoubleQuotes(result.getError().getData()) : result.getValue();// .toString(); + resolvedName = resolveOffchain(lookupDataHex, resolverAddress, LOOKUP_LIMIT); + } else { + try { + resolvedName = resolverAddr(nameHash, resolverAddress.address); + } catch (Exception e) { + throw new RuntimeException("Unable to execute Ethereum request: ", e); + } + } + + if (!WalletUtils.isValidAddress(resolvedName)) { + throw new EnsResolutionException( + "Unable to resolve address for name: " + ensName); + } else { + return resolvedName; + } + + } else { + return ensName; + } + } catch (Exception e) { + throw new EnsResolutionException(e); + } + } + + protected String resolveOffchain( + String lookupData, ContractAddress resolverAddress, int lookupCounter) + throws Exception + { + if (EnsUtils.isEIP3668(lookupData)) + { + OffchainLookup offchainLookup = + OffchainLookup.build(Numeric.hexStringToByteArray(lookupData.substring(10))); + + if (!resolverAddress.address.equals(offchainLookup.getSender())) + { + throw new EnsResolutionException( + "Cannot handle OffchainLookup raised inside nested call"); + } + + String gatewayResult = + ccipReadFetch( + offchainLookup.getUrls(), + offchainLookup.getSender(), + Numeric.toHexString(offchainLookup.getCallData())); + + if (gatewayResult == null) + { + throw new EnsResolutionException("CCIP Read disabled or provided no URLs."); + } + + ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper(); + EnsGatewayResponseDTO gatewayResponseDTO = + objectMapper.readValue(gatewayResult, EnsGatewayResponseDTO.class); + + EthCall result = + resolveWithProof( + Numeric.hexStringToByteArray(gatewayResponseDTO.getData()), + offchainLookup.getExtraData(), resolverAddress.address); + + String resolvedNameHex = result.isReverted() ? Utils.removeDoubleQuotes(result.getError().getData()) : result.getValue();// .toString(); + + // This protocol can result in multiple lookups being requested by the same contract. + if (EnsUtils.isEIP3668(resolvedNameHex)) + { + if (lookupCounter <= 0) + { + throw new EnsResolutionException("Lookup calls is out of limit."); + } + + return resolveOffchain(lookupData, resolverAddress, --lookupCounter); + } + else + { + byte[] resolvedNameBytes = decodeDynamicBytes(resolvedNameHex); + + return decodeAddress( + Numeric.toHexString(resolvedNameBytes)); + } + } + + return lookupData; + } + + private static byte[] decodeDynamicBytes(String rawInput) + { + if (decoder == null) decoder = new DefaultFunctionReturnDecoder(); + List outputParameters = new ArrayList>(); + outputParameters.add(new TypeReference() {}); + + List typeList = decoder.decodeFunctionResult(rawInput, outputParameters); + + return typeList.isEmpty() ? null : ((DynamicBytes) typeList.get(0)).getValue(); + } + + private static String decodeAddress(String rawInput) + { + if (decoder == null) decoder = new DefaultFunctionReturnDecoder(); + List outputParameters = new ArrayList>(); + outputParameters.add(new TypeReference
() {}); + + List typeList = decoder.decodeFunctionResult(rawInput, outputParameters); + + return typeList.isEmpty() ? null : ((Address) typeList.get(0)).getValue(); + } + + protected String ccipReadFetch(List urls, String sender, String data) { + List errorMessages = new ArrayList<>(); + + for (String url : urls) { + Request request; + try { + request = buildRequest(url, sender, data); + } catch (JsonProcessingException | EnsResolutionException e) { + log.error(e.getMessage(), e); + break; + } + + try (okhttp3.Response response = client.newCall(request).execute()) { + if (response.isSuccessful()) { + ResponseBody responseBody = response.body(); + if (responseBody == null) { + log.warn("Response body is null, url: {}", url); + break; + } + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(responseBody.byteStream()))) + { + StringBuilder sb = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + sb.append(line).append("\n"); + } + return sb.toString(); + } + catch (Exception e) + { + // + return ""; + } + } else { + int statusCode = response.code(); + // 4xx indicates the result is not present; stop + if (statusCode >= 400 && statusCode < 500) { + log.error( + "Response error during CCIP fetch: url {}, error: {}", + url, + response.message()); + throw new EnsResolutionException(response.message()); + } + + // 5xx indicates server issue; try the next url + errorMessages.add(response.message()); + + log.warn( + "Response error 500 during CCIP fetch: url {}, error: {}", + url, + response.message()); + } + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + + log.warn(Arrays.toString(errorMessages.toArray())); + return null; + } + + protected Request buildRequest(String url, String sender, String data) + throws JsonProcessingException { + if (sender == null || !WalletUtils.isValidAddress(sender)) { + throw new EnsResolutionException("Sender address is null or not valid"); + } + if (data == null) { + throw new EnsResolutionException("Data is null"); + } + if (!url.contains("{sender}")) { + throw new EnsResolutionException("Url is not valid, sender parameter is not exist"); + } + + // URL expansion + String href = url.replace("{sender}", sender).replace("{data}", data); + + Request.Builder builder = new Request.Builder().url(href); + + if (url.contains("{data}")) { + return builder.get().build(); + } else { + EnsGatewayRequestDTO requestDTO = new EnsGatewayRequestDTO(data); + ObjectMapper om = ObjectMapperFactory.getObjectMapper(); + + return builder.post(RequestBody.create(om.writeValueAsString(requestDTO), JSON)) + .addHeader("Content-Type", "application/json") + .build(); + } + } + + /** + * Reverse name resolution as documented in the specification. + * + * @param address an ethereum address, example: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" + * @return a EnsName registered for provided address + */ + public String reverseResolve(String address) throws Exception + { + if (WalletUtils.isValidAddress(address, addressLength)) + { + String reverseName = Numeric.cleanHexPrefix(address) + REVERSE_NAME_SUFFIX; + ContractAddress resolverAddress = obtainOffchainResolverAddr(reverseName); + + byte[] nameHash = NameHash.nameHashAsBytes(reverseName); + String name; + try { + name = resolveName(nameHash, resolverAddress.address); + } catch (Exception e) { + throw new RuntimeException("Unable to execute Ethereum request", e); + } + + if (!isValidEnsName(name, addressLength)) { + throw new RuntimeException("Unable to resolve name for address: " + address); + } else { + return name; + } + } else { + throw new EnsResolutionException("Address is invalid: " + address); + } + } + + private Function getResolver(byte[] nameHash) + { + return new Function("resolver", + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash)), + Arrays.asList(new TypeReference
() + { + })); + } + + protected String getResolverAddress(String ensName) throws Exception + { + String registryContract = Contracts.resolveRegistryContract(chainId); + byte[] nameHash = NameHash.nameHashAsBytes(ensName); + Function resolver = getResolver(nameHash); + String address = getContractData(registryContract, resolver, ""); + + if (EnsUtils.isAddressEmpty(address)) { + address = getResolverAddress(EnsUtils.getParent(ensName)); + } + + return address; + } + + public static boolean isValidEnsName(String input) { + return isValidEnsName(input, Keys.ADDRESS_LENGTH_IN_HEX); + } + + public static boolean isValidEnsName(String input, int addressLength) { + return input != null // will be set to null on new Contract creation + && (input.contains(".") || !WalletUtils.isValidAddress(input, addressLength)); + } + + public void setHttpClient(OkHttpClient client) { + this.client = client; + } + + public static final String FUNC_SUPPORTSINTERFACE = "supportsInterface"; + public static final String FUNC_addr = "addr"; + public static final String FUNC_RESOLVE = "resolve"; + public static final String FUNC_RESOLVEWITHPROOF = "resolveWithProof"; + public static final String FUNC_NAME = "name"; + + public boolean supportsInterface(byte[] interfaceID, String address) throws Exception + { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_SUPPORTSINTERFACE, + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes4(interfaceID)), + Arrays.asList(new TypeReference() + { + })); + + return getContractData(address, function, true); + } + + public String resolverAddr(byte[] node, String address) throws Exception + { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_addr, + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(node)), + Arrays.>asList(new TypeReference
() {})); + + return getContractData(address, function, ""); + } + + public String encodeResolverAddr(byte[] node) + { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_addr, + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(node)), + Arrays.>asList(new TypeReference
() {})); + + return FunctionEncoder.encode(function); + } + + public EthCall resolve(byte[] name, byte[] data, String address) throws Exception + { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_RESOLVE, + Arrays.asList(new org.web3j.abi.datatypes.DynamicBytes(name), + new org.web3j.abi.datatypes.DynamicBytes(data)), + Arrays.>asList(new TypeReference() {})); + + String encodedFunction = FunctionEncoder.encode(function); + + org.web3j.protocol.core.methods.request.Transaction transaction + = createEthCallTransaction(TokenscriptFunction.ZERO_ADDRESS, address, encodedFunction); + return web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send(); + } + + public EthCall resolveWithProof(byte[] response, byte[] extraData, String address) throws Exception + { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_RESOLVEWITHPROOF, + Arrays.asList(new org.web3j.abi.datatypes.DynamicBytes(response), + new org.web3j.abi.datatypes.DynamicBytes(extraData)), + Arrays.>asList(new TypeReference() {})); + + String encodedFunction = FunctionEncoder.encode(function); + + org.web3j.protocol.core.methods.request.Transaction transaction + = createEthCallTransaction(TokenscriptFunction.ZERO_ADDRESS, address, encodedFunction); + return web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send(); + } + + private String resolveName(byte[] node, String address) throws Exception + { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_NAME, + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(node)), + Arrays.>asList(new TypeReference() {})); + + return getContractData(address, function, ""); + } + + protected T getContractData(String address, Function function, T type) throws Exception + { + String responseValue = callSmartContractFunction(function, address); + + if (TextUtils.isEmpty(responseValue)) + { + throw new Exception("Bad contract value"); + } + else if (responseValue.equals("0x")) + { + if (type instanceof Boolean) + { + return (T) Boolean.FALSE; + } + else + { + return null; + } + } + + List response = FunctionReturnDecoder.decode( + responseValue, function.getOutputParameters()); + if (response.size() == 1) + { + return (T) response.get(0).getValue(); + } + else + { + if (type instanceof Boolean) + { + return (T) Boolean.FALSE; + } + else + { + return null; + } + } + } + + private String callSmartContractFunction( + Function function, String contractAddress) throws Exception + { + try + { + String encodedFunction = FunctionEncoder.encode(function); + + org.web3j.protocol.core.methods.request.Transaction transaction + = createEthCallTransaction(TokenscriptFunction.ZERO_ADDRESS, contractAddress, encodedFunction); + EthCall response = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send(); + + return response.getValue(); + } + catch (InterruptedIOException | UnknownHostException | JsonParseException e) + { + //expected to happen when user switches wallets + return "0x"; + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/EnsUtils.java b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsUtils.java new file mode 100644 index 0000000000..28a83cd431 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/EnsUtils.java @@ -0,0 +1,46 @@ +/* + * Copyright 2022 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.alphawallet.app.web3j.ens; + +import com.alphawallet.token.tools.Numeric; + +public class EnsUtils { + + public static final String EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000"; + + // Wildcard resolution + public static final byte[] ENSIP_10_INTERFACE_ID = Numeric.hexStringToByteArray("0x9061b923"); + public static final String EIP_3668_CCIP_INTERFACE_ID = "0x556f1830"; + + public static boolean isAddressEmpty(String address) { + return EMPTY_ADDRESS.equals(address); + } + + public static boolean isEIP3668(String data) { + if (data == null || data.length() < 10) { + return false; + } + + return EnsUtils.EIP_3668_CCIP_INTERFACE_ID.equals(data.substring(0, 10)); + } + + public static String getParent(String url) { + String ensUrl = url != null ? url.trim() : ""; + + if (ensUrl.equals(".") || !ensUrl.contains(".")) { + return null; + } + + return ensUrl.substring(ensUrl.indexOf(".") + 1); + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java b/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java new file mode 100644 index 0000000000..6f50e4ce7d --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java @@ -0,0 +1,107 @@ +/* + * Copyright 2019 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.alphawallet.app.web3j.ens; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.IDN; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Locale; + +import org.web3j.crypto.Hash; +import org.web3j.utils.Numeric; + +/** ENS name hash implementation. */ +public class NameHash { + + private static final byte[] EMPTY = new byte[32]; + + public static byte[] nameHashAsBytes(String ensName) { + return Numeric.hexStringToByteArray(nameHash(ensName)); + } + + public static String nameHash(String ensName) { + String normalisedEnsName = normalise(ensName); + return Numeric.toHexString(nameHash(normalisedEnsName.split("\\."))); + } + + private static byte[] nameHash(String[] labels) { + if (labels.length == 0 || labels[0].equals("")) { + return EMPTY; + } else { + String[] tail; + if (labels.length == 1) { + tail = new String[] {}; + } else { + tail = Arrays.copyOfRange(labels, 1, labels.length); + } + + byte[] remainderHash = nameHash(tail); + byte[] result = Arrays.copyOf(remainderHash, 64); + + byte[] labelHash = Hash.sha3(labels[0].getBytes(StandardCharsets.UTF_8)); + System.arraycopy(labelHash, 0, result, 32, labelHash.length); + + return Hash.sha3(result); + } + } + + /** + * Normalise ENS name as per the specification. + * + * @param ensName our user input ENS name + * @return normalised ens name + * @throws EnsResolutionException if the name cannot be normalised + */ + public static String normalise(String ensName) { + try { + return IDN.toASCII(ensName, IDN.USE_STD3_ASCII_RULES).toLowerCase(Locale.ROOT); + } catch (IllegalArgumentException e) { + throw new EnsResolutionException("Invalid ENS name provided: " + ensName); + } + } + + public static byte[] toUtf8Bytes(String string) { + if (string == null || string.isEmpty()) { + return null; + } + return string.getBytes(StandardCharsets.UTF_8); + } + + /** + * Encode Dns name. Reference implementation + * https://github.com/ethers-io/ethers.js/blob/fc1e006575d59792fa97b4efb9ea2f8cca1944cf/packages/hash/src.ts/namehash.ts#L49 + * + * @param name Dns name + * @return Encoded name in Hex format. + * @throws IOException + */ + public static String dnsEncode(String name) throws IOException { + String[] parts = name.split("\\."); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + for (String part : parts) { + byte[] bytes = toUtf8Bytes("_" + normalise(part)); + if (bytes == null) { + break; + } + bytes[0] = (byte) (bytes.length - 1); + + outputStream.write(bytes); + } + + return Numeric.toHexString(outputStream.toByteArray()) + "00"; + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/OffchainLookup.java b/app/src/main/java/com/alphawallet/app/web3j/ens/OffchainLookup.java new file mode 100644 index 0000000000..28c4264c8c --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/OffchainLookup.java @@ -0,0 +1,157 @@ +package com.alphawallet.app.web3j.ens; + +/* + * Copyright 2022 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +//package org.web3j.abi.datatypes.ens; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.web3j.abi.FunctionReturnDecoder; +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.DynamicArray; +import org.web3j.abi.datatypes.DynamicBytes; +import org.web3j.abi.datatypes.DynamicStruct; +import org.web3j.abi.datatypes.Type; +import org.web3j.abi.datatypes.Utf8String; +import org.web3j.abi.datatypes.generated.Bytes4; +import org.web3j.utils.Numeric; + +/** https://eips.ethereum.org/EIPS/eip-3668#client-lookup-protocol */ +public class OffchainLookup extends DynamicStruct { + + private String sender; + private List urls; + private byte[] callData; + + /** + * Callback selector / Abi method Id + * org.web3j.abi.FunctionEncoder#buildMethodId(java.lang.String) + */ + private byte[] callbackFunction; + + private byte[] extraData; + + private static final List outputParameters = new ArrayList>(); + + static { + outputParameters.addAll( + Arrays.asList( + new TypeReference
() {}, + new TypeReference>() {}, + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {})); + } + + /*public OffchainLookup( + String sender, + List urls, + byte[] callData, + byte[] callbackFunction, + byte[] extraData) { + super( + new Address(sender), + new DynamicArray<>( + Utf8String.class, + urls.stream().map(Utf8String::new).collect(Collectors.toList())), + new DynamicBytes(callbackFunction), + new Bytes4(callData), + new DynamicBytes(extraData)); + this.sender = sender; + this.urls = urls; + this.callData = callData; + this.callbackFunction = callbackFunction; + this.extraData = extraData; + }*/ + + public OffchainLookup( + Address sender, + DynamicArray urls, + DynamicBytes callData, + Bytes4 callbackFunction, + DynamicBytes extraData) { + super(sender, urls, callData, callbackFunction, extraData); + this.sender = sender.getValue(); + this.urls = arrayToList(urls); + this.callData = callData.getValue(); + this.callbackFunction = callbackFunction.getValue(); + this.extraData = extraData.getValue(); + } + + private List arrayToList(DynamicArray values) + { + List valueList = new ArrayList<>(); + for (Utf8String val : values.getValue()) + { + valueList.add(val.getValue()); + } + + return valueList; + } + + public static OffchainLookup build(byte[] bytes) { + List resultList = + FunctionReturnDecoder.decode(Numeric.toHexString(bytes), outputParameters); + + return new OffchainLookup( + (Address) resultList.get(0), + (DynamicArray) resultList.get(1), + (DynamicBytes) resultList.get(2), + (Bytes4) resultList.get(3), + (DynamicBytes) resultList.get(4)); + } + + public String getSender() { + return sender; + } + + public void setSender(String sender) { + this.sender = sender; + } + + public List getUrls() { + return urls; + } + + public void setUrls(List urls) { + this.urls = urls; + } + + public byte[] getCallData() { + return callData; + } + + public void setCallData(byte[] callData) { + this.callData = callData; + } + + public byte[] getCallbackFunction() { + return callbackFunction; + } + + public void setCallbackFunction(byte[] callbackFunction) { + this.callbackFunction = callbackFunction; + } + + public byte[] getExtraData() { + return extraData; + } + + public void setExtraData(byte[] extraData) { + this.extraData = extraData; + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/RecordTypes.java b/app/src/main/java/com/alphawallet/app/web3j/ens/RecordTypes.java new file mode 100644 index 0000000000..c3a64e68a4 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/RecordTypes.java @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Web3 Labs Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package com.alphawallet.app.web3j.ens; + +import org.web3j.utils.Numeric; + +/** + * Record type interfaces supported by resolvers as per EIP-137 + */ +public class RecordTypes { + + public static final byte[] ADDR = Numeric.hexStringToByteArray("0x3b3b57de"); + public static final byte[] NAME = Numeric.hexStringToByteArray("0x691f3431"); + public static final byte[] ABI = Numeric.hexStringToByteArray("0x2203ab56"); + public static final byte[] PUB_KEY = Numeric.hexStringToByteArray("0xc8690233"); +} diff --git a/app/src/main/java/com/alphawallet/app/widget/InputAddress.java b/app/src/main/java/com/alphawallet/app/widget/InputAddress.java index aceca3cb04..fd66ad3393 100644 --- a/app/src/main/java/com/alphawallet/app/widget/InputAddress.java +++ b/app/src/main/java/com/alphawallet/app/widget/InputAddress.java @@ -24,7 +24,6 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.entity.ENSCallback; -import com.alphawallet.app.entity.EnsNodeNotSyncCallback; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.ui.QRScanning.QRScanner; import com.alphawallet.app.ui.widget.adapter.AutoCompleteAddressAdapter; @@ -544,7 +543,7 @@ public void afterTextChanged(Editable s) } } - public void setEnsNodeNotSyncCallback(EnsNodeNotSyncCallback callback) + /*public void setEnsNodeNotSyncCallback(EnsNodeNotSyncCallback callback) { Timber.d("setEnsNodeNotSyncCallback: "); ensHandler.setEnsNodeNotSyncCallback(callback); @@ -553,6 +552,6 @@ public void setEnsNodeNotSyncCallback(EnsNodeNotSyncCallback callback) public void setEnsHandlerNodeSyncFlag(boolean performSync) { ensHandler.performEnsSync = performSync; - } + }*/ } diff --git a/app/src/test/java/com/alphawallet/app/ENSTest.java b/app/src/test/java/com/alphawallet/app/ENSTest.java new file mode 100644 index 0000000000..ac6268fc8a --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/ENSTest.java @@ -0,0 +1,140 @@ +package com.alphawallet.app; + +import static com.alphawallet.app.web3j.ens.NameHash.nameHash; +import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; +import static org.junit.Assert.assertEquals; + +import com.alphawallet.app.service.AWHttpService; +import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.web3j.ens.Contracts; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.junit.Test; +import org.web3j.protocol.ObjectMapperFactory; +import org.web3j.protocol.Web3j; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; + +//Note that these tests may go 'stale' if ownership of the ENS domains changes or avatars change. This is not expected to happen frequently. + +public class ENSTest +{ + @Test + public void testResolveRegistryContract() { + assertEquals(Contracts.resolveRegistryContract(MAINNET_ID), (Contracts.MAINNET)); + assertEquals(Contracts.resolveRegistryContract(ROPSTEN_ID), (Contracts.ROPSTEN)); + assertEquals(Contracts.resolveRegistryContract(RINKEBY_ID), (Contracts.RINKEBY)); + } + + private final AWHttpService web3jService; + private final Web3j web3j; + private final AWEnsResolver ensResolver; + + private ObjectMapper om = ObjectMapperFactory.getObjectMapper(); + + private static List urls = new ArrayList<>(); + + private String sender = "0x226159d592E2b063810a10Ebf6dcbADA94Ed68b8"; + private static String Inf = "p8qs5p30583q5q65n40s8nn89s257964"; + + private String data = "0x00112233"; + + public static String LOOKUP_HEX = + "0x556f1830000000000000000000000000c1735677a60884abbcf72295e88d47764beda28200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000160f4d4d2f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004768747470733a2f2f6f6666636861696e2d7265736f6c7665722d6578616d706c652e75632e722e61707073706f742e636f6d2f7b73656e6465727d2f7b646174617d2e6a736f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e49061b92300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001701310f6f6666636861696e6578616d706c65036574680000000000000000000000000000000000000000000000000000000000000000000000000000000000243b3b57de1c9fb8c1fe76f464ccec6d2c003169598fdfcbcb6bbddf6af9c097a39fa0048c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e49061b92300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001701310f6f6666636861696e6578616d706c65036574680000000000000000000000000000000000000000000000000000000000000000000000000000000000243b3b57de1c9fb8c1fe76f464ccec6d2c003169598fdfcbcb6bbddf6af9c097a39fa0048c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + public static String RESOLVED_NAME_HEX = + "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000041563129cdbbd0c5d3e1c86cf9563926b243834d"; + + public ENSTest() + { + web3jService = getWeb3jService(); + web3j = getWeb3j(web3jService); + ensResolver = new AWEnsResolver(web3j); + urls.add("https://example-1.com/gateway/{sender}/{data}.json"); + urls.add("https://example-2.com/gateway/{sender}/{data}.json"); + } + + public static AWHttpService getWeb3jService() + { + OkHttpClient okClient = new OkHttpClient.Builder() + .connectTimeout(C.CONNECT_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(C.READ_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(C.LONG_WRITE_TIMEOUT, TimeUnit.SECONDS) + .retryOnConnectionFailure(true) + .build(); + return new AWHttpService("https://mainnet.infura.io/v3/" + TextUtils.rot(Inf), "https://main-rpc.linkpool.io", okClient, false); + } + + public static Web3j getWeb3j(AWHttpService service) + { + return Web3j.build(service); + } + + @Test + public void testResolve() throws Exception { + + assertEquals( + ensResolver.resolve("web3j.eth"), ("0x7bfd522dea355ddee2be3c01dfa4419451759310").toLowerCase()); + + assertEquals( + ensResolver.resolve("1.offchainexample.eth"), ("0x41563129cdbbd0c5d3e1c86cf9563926b243834d").toLowerCase()); + + assertEquals( + ensResolver.resolve("2.offchainexample.eth"), ("0x41563129cdbbd0c5d3e1c86cf9563926b243834d").toLowerCase()); + + assertEquals( + ensResolver.resolve("offchainexample.eth"), ("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045").toLowerCase()); + } + + @Test + public void testDASResolve() throws Exception { + assertEquals( + ensResolver.resolve("satoshi.bit"), ("0xee8738e3d3e80482526b33c91dd343caef68e41a").toLowerCase()); + + assertEquals( + ensResolver.resolve("ponzi.bit"), ("0x04e294283fb6c2974b59d15a0bc347f8d4d4bdcd").toLowerCase()); + } + + @Test + public void testAvatarResolve() throws Exception { + assertEquals( + ensResolver.resolveAvatar("alphaid.eth"), ("https://drive.google.com/a/alphawallet.com/file/d/129glXWa1Y2nOZQNwvx8sA5fR1KuGAW4m/view?usp=drivesdk")); + } + + @Test + public void testAvatarAddressResolve() throws Exception { + assertEquals( + ensResolver.resolveAvatarFromAddress("0xbc8dAfeacA658Ae0857C80D8Aa6dE4D487577c63"), ("eip155:1/erc721:0x222222222291749DE47895C0c0A9B17e4fcA8268/29")); + } + + @Test + public void testReverseResolve() throws Exception { + + assertEquals( + ensResolver.reverseResolve("0xd8da6bf26964af9d7eed9e03e53415d37aa96045"), + ("vitalik.eth")); + } + + @Test + public void testNameHash() { + assertEquals( + nameHash(""), + ("0x0000000000000000000000000000000000000000000000000000000000000000")); + + assertEquals( + nameHash("eth"), + ("0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae")); + + assertEquals( + nameHash("foo.eth"), + ("0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f")); + } + + +} diff --git a/app/src/test/java/com/alphawallet/app/TextUtils.java b/app/src/test/java/com/alphawallet/app/TextUtils.java index f333e422d3..0de6c5891e 100644 --- a/app/src/test/java/com/alphawallet/app/TextUtils.java +++ b/app/src/test/java/com/alphawallet/app/TextUtils.java @@ -8,4 +8,38 @@ class TextUtils public static boolean isEmpty(CharSequence str) { return str == null || str.length() == 0; } + + public static String rot(String input) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < input.length(); i++) + { + char c = input.charAt(i); + if (c >= 'a' && c <= 'm') c += 13; + else if (c >= 'A' && c <= 'M') c += 13; + else if (c >= 'n' && c <= 'z') c -= 13; + else if (c >= 'N' && c <= 'Z') c -= 13; + else if (c >= '1' && c <= '9') c -= 1; + else if (c == '0') c = '9'; + sb.append(c); + } + return sb.toString(); + } + + public static String rotEnc(String input) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < input.length(); i++) + { + char c = input.charAt(i); + if (c >= 'a' && c <= 'm') c += 13; + else if (c >= 'A' && c <= 'M') c += 13; + else if (c >= 'n' && c <= 'z') c -= 13; + else if (c >= 'N' && c <= 'Z') c -= 13; + else if (c >= '0' && c <= '8') c += 1; + else if (c == '9') c = '0'; + sb.append(c); + } + return sb.toString(); + } } From be738092bd7ab5de304c8c78d3e0653b6293f998 Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 22 Aug 2022 13:21:39 +1000 Subject: [PATCH 063/183] Update RPC --- .../com/alphawallet/app/repository/EthereumNetworkBase.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index f2f7b0236f..2baf9a4cdd 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -101,11 +101,11 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy private static final KeyProvider keyProvider = KeyProviderFactory.get(); public static final boolean usesProductionKey = !keyProvider.getInfuraKey().equals(DEFAULT_INFURA_KEY); - public static final String FREE_MAINNET_RPC_URL = "https://main-rpc.linkpool.io"; + public static final String FREE_MAINNET_RPC_URL = "https://rpc.ankr.com/eth"; public static final String FREE_POLYGON_RPC_URL = "https://polygon-rpc.com"; public static final String FREE_ARBITRUM_RPC_URL = "https://arbitrum.public-rpc.com"; - public static final String FREE_RINKEBY_RPC_URL = "https://rinkeby-light.eth.linkpool.io"; - public static final String FREE_GOERLI_RPC_URL = "https://goerli-light.eth.linkpool.io"; + public static final String FREE_RINKEBY_RPC_URL = "https://rpc.ankr.com/eth_rinkeby"; + public static final String FREE_GOERLI_RPC_URL = "https://rpc.ankr.com/eth_goerli"; public static final String FREE_MUMBAI_RPC_URL = "https://rpc-mumbai.maticvigil.com"; public static final String FREE_OPTIMISM_RPC_URL = "https://mainnet.optimism.io"; public static final String FREE_ARBITRUM_TEST_RPC_URL = "https://rinkeby.arbitrum.io/rpc"; From 4a3ff9bd0ff8dfa816b480dc4ecd1becad012961 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Mon, 22 Aug 2022 13:41:40 +0800 Subject: [PATCH 064/183] Transfer test against Ganache --- .../com/alphawallet/app/DappBrowserTest.java | 2 +- .../app/ImportWalletWithSeedPhraseTest.java | 52 ++++++++++++++++ .../alphawallet/app/ManageNetworkTest.java | 30 --------- .../com/alphawallet/app/TransferTest.java | 17 ++++-- .../java/com/alphawallet/app/steps/Steps.java | 61 ++++++++++++------- e2e.sh | 13 ++++ 6 files changed, 118 insertions(+), 57 deletions(-) create mode 100644 app/src/androidTest/java/com/alphawallet/app/ImportWalletWithSeedPhraseTest.java delete mode 100644 app/src/androidTest/java/com/alphawallet/app/ManageNetworkTest.java diff --git a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java index ae1f0e471e..47823c7115 100644 --- a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java @@ -25,7 +25,7 @@ public void should_switch_network() shouldSee("Ethereum"); Helper.wait(5); SnapshotUtil.take("1"); - selectTestNet(); + selectTestNet("Görli"); navigateToBrowser(); Helper.wait(3); pressBack(); diff --git a/app/src/androidTest/java/com/alphawallet/app/ImportWalletWithSeedPhraseTest.java b/app/src/androidTest/java/com/alphawallet/app/ImportWalletWithSeedPhraseTest.java new file mode 100644 index 0000000000..a309e4131d --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/ImportWalletWithSeedPhraseTest.java @@ -0,0 +1,52 @@ +package com.alphawallet.app; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withParent; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.alphawallet.app.steps.Steps.closeSecurityWarning; +import static com.alphawallet.app.steps.Steps.closeSelectNetworkPage; +import static com.alphawallet.app.steps.Steps.getWalletAddress; +import static com.alphawallet.app.util.Helper.click; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.junit.Assert.fail; + +import android.os.Build; + +import com.alphawallet.app.util.Helper; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class ImportWalletWithSeedPhraseTest extends BaseE2ETest { + private static final Map WALLETS = new HashMap() {{ + put("24", new String[]{"essence allow crisp figure tired task melt honey reduce planet twenty rookie", "0xD0c424B3016E9451109ED97221304DeC639b3F84"}); + put("30", new String[]{"deputy review citizen bacon measure combine bag dose chronic retreat attack fly", "0xD8790c1eA5D15F8149C97F80524AC87f56301204"}); + put("32", new String[]{"omit mobile upgrade warm flock two era hamster local cat wink virus", "0x32f6F38137a79EA8eA237718b0AFAcbB1c58ca2e"}); + }}; + + @Test + public void should_import_wallet_with_seed_phrase() { + int apiLevel = Build.VERSION.SDK_INT; + String[] array = WALLETS.get(String.valueOf(apiLevel)); + if (array == null) { + fail("Please config seed phrase and wallet address for this API level first."); + } + + String seedPhrase = array[0]; + String existedWalletAddress = array[1]; + + closeSecurityWarning(); + click(withText("I already have a Wallet")); + + onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_seed)))))).perform(replaceText(seedPhrase)); + Helper.wait(2); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis + click(withId(R.id.import_action)); + assertThat(getWalletAddress(), equalTo(existedWalletAddress)); + } +} diff --git a/app/src/androidTest/java/com/alphawallet/app/ManageNetworkTest.java b/app/src/androidTest/java/com/alphawallet/app/ManageNetworkTest.java deleted file mode 100644 index 9f51335361..0000000000 --- a/app/src/androidTest/java/com/alphawallet/app/ManageNetworkTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.alphawallet.app; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static com.alphawallet.app.assertions.Should.shouldSee; -import static com.alphawallet.app.steps.Steps.addNewNetwork; -import static com.alphawallet.app.steps.Steps.createNewWallet; -import static com.alphawallet.app.steps.Steps.gotoSettingsPage; -import static com.alphawallet.app.steps.Steps.toggleSwitch; -import static com.alphawallet.app.util.Helper.click; - -import androidx.test.espresso.action.ViewActions; - -import org.junit.Test; - -public class ManageNetworkTest extends BaseE2ETest -{ - @Test - public void should_add_custom_network() - { - createNewWallet(); - gotoSettingsPage(); - addNewNetwork("MyTestNet"); - toggleSwitch(R.id.mainnet_header); - click(withText(R.string.action_enable_testnet)); - shouldSee("MyTestNet"); - } -} diff --git a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java index 416a5753ea..cbf638cb4a 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java @@ -1,5 +1,7 @@ package com.alphawallet.app; +import static androidx.test.espresso.Espresso.pressBack; +import static com.alphawallet.app.steps.Steps.addNewNetwork; import static com.alphawallet.app.steps.Steps.assertBalanceIs; import static com.alphawallet.app.steps.Steps.createNewWallet; import static com.alphawallet.app.steps.Steps.ensureTransactionConfirmed; @@ -28,24 +30,31 @@ public class TransferTest extends BaseE2ETest { put("32", new String[]{"omit mobile upgrade warm flock two era hamster local cat wink virus", "0x32f6F38137a79EA8eA237718b0AFAcbB1c58ca2e"}); }}; + private static final Map WALLETS_ON_GANACHE = new HashMap() {{ + put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); + put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); + put("32", new String[]{"omit mobile upgrade warm flock two era hamster local cat wink virus", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); + }}; + @Test public void should_transfer_from_an_account_to_another() { int apiLevel = Build.VERSION.SDK_INT; - String[] array = WALLETS.get(String.valueOf(apiLevel)); + String[] array = WALLETS_ON_GANACHE.get(String.valueOf(apiLevel)); if (array == null) { fail("Please config seed phrase and wallet address for this API level first."); } - String seedPhrase = array[0]; + String privateKey = array[0]; String existedWalletAddress = array[1]; createNewWallet(); String newWalletAddress = getWalletAddress(); - importWalletFromSettingsPage(seedPhrase); + importWalletFromSettingsPage(privateKey); assertThat(getWalletAddress(), equalTo(existedWalletAddress)); - selectTestNet(); + addNewNetwork("Ganache"); + selectTestNet("Ganache"); sendBalanceTo(newWalletAddress, "0.001"); ensureTransactionConfirmed(); switchToWallet(newWalletAddress); diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index 2ead11d9f2..46739df9c3 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -5,7 +5,6 @@ import static androidx.test.espresso.action.ViewActions.pressImeActionButton; import static androidx.test.espresso.action.ViewActions.replaceText; import static androidx.test.espresso.action.ViewActions.scrollTo; -import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; import static androidx.test.espresso.matcher.ViewMatchers.isRoot; import static androidx.test.espresso.matcher.ViewMatchers.withHint; @@ -18,8 +17,6 @@ import static com.alphawallet.app.util.Helper.click; import static com.alphawallet.app.util.Helper.waitUntil; import static com.alphawallet.app.util.RootUtil.isDeviceRooted; - -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.core.StringStartsWith.startsWith; @@ -38,14 +35,24 @@ public class Steps { public static void createNewWallet() + { + closeSecurityWarning(); + click(withId(R.id.button_create)); + closeSelectNetworkPage(); + click(withText(R.string.action_close)); // works well locally but NOT work with GitHub actions + } + + public static void closeSecurityWarning() { if (isDeviceRooted()) { click(withText(R.string.ok)); } - click(withId(R.id.button_create)); - shouldSee("Select Active Networks"); + } + + public static void closeSelectNetworkPage() + { + Helper.wait(5); pressBack(); - click(withText(R.string.action_close)); // works well locally but NOT work with GitHub actions } public static void visit(String urlString) @@ -60,16 +67,14 @@ public static void navigateToBrowser() click(withId(R.id.nav_browser_text)); } - public static void selectTestNet() + public static void selectTestNet(String name) { gotoSettingsPage(); selectMenu("Select Active Networks"); toggleSwitch(R.id.mainnet_header); click(withText(R.string.action_enable_testnet)); click(withSubstring("Rinkeby")); // Deselect - click(withSubstring("Görli")); // Select -// onView(withId(R.id.test_list)).perform(actionOnItemAtPosition(1, ViewActions.click())); // Rinkeby -// onView(withId(R.id.test_list)).perform(actionOnItemAtPosition(3, ViewActions.click())); // Kovan + click(withSubstring(name)); // Select pressBack(); } @@ -104,8 +109,8 @@ public static void sendBalanceTo(String receiverAddress, String amountStr) { private static void ensureBalanceFetched() { - shouldSee("Görli (Test)"); - shouldNotSee("0 GöETH"); + shouldSee("Ganache"); + shouldNotSee("0 ETH"); } public static void switchToWallet(String address) { @@ -123,17 +128,27 @@ public static String getWalletAddress() { return getTextAction.getText().toString().replace(" ", ""); // The address show on 2 lines so there is a blank space } - public static void importWalletFromSettingsPage(String seedPhrase) { + public static void importWalletFromSettingsPage(String text) { gotoSettingsPage(); click(withText("Change / Add Wallet")); click(withId(R.id.action_add)); // SnapshotUtil.take("after-add"); click(withId(R.id.import_account_action)); - onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_seed)))))).perform(replaceText(seedPhrase)); + int textId; + int buttonId; + boolean isPrivateKey = text.startsWith("0x"); + if (isPrivateKey) { + click(withText("Private key")); + textId = R.id.input_private_key; + buttonId = R.id.import_action_pk; + } else { + textId = R.id.input_seed; + buttonId = R.id.import_action; + } + onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(textId)))))).perform(replaceText(text)); Helper.wait(2); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis - click(withId(R.id.import_action)); - shouldSee("Select Active Networks"); - pressBack(); + click(withId(buttonId)); + closeSelectNetworkPage(); } public static void gotoSettingsPage() { @@ -149,13 +164,15 @@ public static void addNewNetwork(String name) selectMenu("Select Active Networks"); click(withId(R.id.action_add)); input(R.id.input_network_name, name); - input(R.id.input_network_rpc_url,"http://xxx.yyy.zzz"); - input(R.id.input_network_chain_id, "123456"); - input(R.id.input_network_symbol, "MTNSYM"); - input(R.id.input_network_explorer_api, "http://xxx.yyy.zzz"); - input(R.id.input_network_block_explorer_url, "http://xxx.yyy.zzz"); + String url = "http://192.168.1.3:8545"; + input(R.id.input_network_rpc_url, url); + input(R.id.input_network_chain_id, "2"); + input(R.id.input_network_symbol, "ETH"); + input(R.id.input_network_explorer_api, url); + input(R.id.input_network_block_explorer_url, url); click(withId(R.id.checkbox_testnet)); click(withId(R.string.action_add_network)); + pressBack(); } private static void input(int id, String text) diff --git a/e2e.sh b/e2e.sh index 2d61913688..d95ad55eff 100755 --- a/e2e.sh +++ b/e2e.sh @@ -1,5 +1,13 @@ #!/bin/sh +function startGanache() { + ganache --chain.chainId 2 -h 0.0.0.0 -m "horse light surface bamboo combine item lumber tunnel choose acid mail feature" +} + +function stopGanache() { + kill -9 $(lsof -t -i:8545) +} + # disable animations or test may not stable adb shell settings put global window_animation_scale 0.0 adb shell settings put global transition_animation_scale 0.0 @@ -18,7 +26,10 @@ touch output/emulator.log # create log file chmod 666 output/emulator.log # allow writing to log file adb logcat >> output/emulator.log & +startGanache & + ./gradlew :app:uninstallAll :app:connectedNoAnalyticsDebugAndroidTest -x lint -PdisablePreDex + if [ "$?" != "0" ]; then adb pull /storage/emulated/0/DCIM/ output if [ "$1" != "--CI" ]; then @@ -27,3 +38,5 @@ if [ "$?" != "0" ]; then exit 1 fi + +stopGanache \ No newline at end of file From 86fae01666090eed6cc62f69faa32d173e2843dc Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Mon, 22 Aug 2022 14:09:19 +0800 Subject: [PATCH 065/183] Update badges --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ae8e2dccd8..163894f14c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ # AlphaWallet - Advanced, Open Source Ethereum Mobile Wallet & dApp Browser for Android -[![Build Status](https://api.travis-ci.com/AlphaWallet/alpha-wallet-android.svg?branch=master)](https://api.travis-ci.com/AlphaWallet/alpha-wallet-android.svg?branch=master) +[![Lint](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/lint.yml/badge.svg?branch=master)](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/lint.yml) +[![Unit Test](https://api.travis-ci.com/AlphaWallet/alpha-wallet-android.svg?branch=master)](https://api.travis-ci.com/AlphaWallet/alpha-wallet-android.svg?branch=master) +[![E2E Test](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/e2e.yml/badge.svg?branch=master)](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/e2e.yml) [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg )](https://github.com/AlphaWallet/alpha-wallet-android/graphs/commit-activity) ![GitHub contributors](https://img.shields.io/github/contributors/AlphaWallet/alpha-wallet-android.svg) [![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/AlphaWallet/alpha-wallet-android/blob/master/LICENSE) From 2c01c20305c21fe6ce6ef2773e3acae3a1f2b62f Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Mon, 22 Aug 2022 14:12:51 +0800 Subject: [PATCH 066/183] Update UT badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 163894f14c..940ca051e7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # AlphaWallet - Advanced, Open Source Ethereum Mobile Wallet & dApp Browser for Android [![Lint](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/lint.yml/badge.svg?branch=master)](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/lint.yml) -[![Unit Test](https://api.travis-ci.com/AlphaWallet/alpha-wallet-android.svg?branch=master)](https://api.travis-ci.com/AlphaWallet/alpha-wallet-android.svg?branch=master) +[![Unit test](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/ci.yml) [![E2E Test](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/e2e.yml/badge.svg?branch=master)](https://github.com/AlphaWallet/alpha-wallet-android/actions/workflows/e2e.yml) [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg )](https://github.com/AlphaWallet/alpha-wallet-android/graphs/commit-activity) ![GitHub contributors](https://img.shields.io/github/contributors/AlphaWallet/alpha-wallet-android.svg) From 4f9f797baccbe0191cd49b33ae2b07838d392a08 Mon Sep 17 00:00:00 2001 From: "Dev @ ApeNow" <111235011+apenowdev@users.noreply.github.com> Date: Mon, 22 Aug 2022 02:24:15 -0400 Subject: [PATCH 067/183] Add ApeNow to the Android dapps list (#2763) Looking to add ApeNow to the dapps list! --- app/src/main/assets/dapps_list.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/dapps_list.json b/app/src/main/assets/dapps_list.json index 7384e558d6..1518d345ef 100644 --- a/app/src/main/assets/dapps_list.json +++ b/app/src/main/assets/dapps_list.json @@ -87,5 +87,6 @@ {"name": "MetaPath", "description": "Assets can be routed across different blockchains", "url": "https://dapp.path.finance?source=alpha", "category": "Exchange"}, {"name": "SWFT", "description": "One Stop Cross-Chain swap, supporting 300+ tokens on 30+ chains", "url": "https://defi.swft.pro?sourceFlag=alpha", "category": "Exchange"}, {"name": "Swapzone", "description": "Swapzone is a custody-free cryptocurrency exchange aggregator with no registration needed.", "url": "https://swapzone.io/", "category": "Exchange"}, - {"name": "mail³", "description": "Decentralized mail system for web3 natives.", "url": "https://app.mail3.me/", "category": "Social Media"} + {"name": "mail³", "description": "Decentralized mail system for web3 natives.", "url": "https://app.mail3.me/", "category": "Social Media"}, + {"name": "ApeNow", "description": "Buy now, pay later marketplace for NFTs.", "url": "https://www.apenowpaylater.com/", "category": "Marketplace"} ] From c59026260eb6de9ccec7f4adf4112b2529437a5b Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 23 Aug 2022 08:10:14 +0800 Subject: [PATCH 068/183] Manually strat Ganache on CI server --- e2e.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e.sh b/e2e.sh index d95ad55eff..2e7d7a4146 100755 --- a/e2e.sh +++ b/e2e.sh @@ -26,7 +26,7 @@ touch output/emulator.log # create log file chmod 666 output/emulator.log # allow writing to log file adb logcat >> output/emulator.log & -startGanache & +#startGanache & # Manually start on CI server ./gradlew :app:uninstallAll :app:connectedNoAnalyticsDebugAndroidTest -x lint -PdisablePreDex From 34251a6b5cedaca111026205514cfacbc137b424 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 24 Aug 2022 15:59:43 +0800 Subject: [PATCH 069/183] Fix RPC IP --- app/src/androidTest/java/com/alphawallet/app/steps/Steps.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index 46739df9c3..913b26549d 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -164,7 +164,7 @@ public static void addNewNetwork(String name) selectMenu("Select Active Networks"); click(withId(R.id.action_add)); input(R.id.input_network_name, name); - String url = "http://192.168.1.3:8545"; + String url = "http://10.0.2.2:8545"; input(R.id.input_network_rpc_url, url); input(R.id.input_network_chain_id, "2"); input(R.id.input_network_symbol, "ETH"); From 583bd9865bc6ebce509c409d90650a8cf5e43902 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 24 Aug 2022 16:22:45 +0800 Subject: [PATCH 070/183] Clean codee --- .../java/com/alphawallet/app/TransferTest.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java index cbf638cb4a..4a0b05a2d7 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java @@ -1,6 +1,5 @@ package com.alphawallet.app; -import static androidx.test.espresso.Espresso.pressBack; import static com.alphawallet.app.steps.Steps.addNewNetwork; import static com.alphawallet.app.steps.Steps.assertBalanceIs; import static com.alphawallet.app.steps.Steps.createNewWallet; @@ -24,16 +23,10 @@ public class TransferTest extends BaseE2ETest { // On CI server, run tests on different API levels concurrently may cause failure: Replacement transaction underpriced. // Use different wallet to transfer token from can avoid this error - private static final Map WALLETS = new HashMap() {{ - put("24", new String[]{"essence allow crisp figure tired task melt honey reduce planet twenty rookie", "0xD0c424B3016E9451109ED97221304DeC639b3F84"}); - put("30", new String[]{"deputy review citizen bacon measure combine bag dose chronic retreat attack fly", "0xD8790c1eA5D15F8149C97F80524AC87f56301204"}); - put("32", new String[]{"omit mobile upgrade warm flock two era hamster local cat wink virus", "0x32f6F38137a79EA8eA237718b0AFAcbB1c58ca2e"}); - }}; - private static final Map WALLETS_ON_GANACHE = new HashMap() {{ put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); - put("32", new String[]{"omit mobile upgrade warm flock two era hamster local cat wink virus", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); + put("32", new String[]{"0x992b442eaa34de3c6ba0b61c75b2e4e0241d865443e313c4fa6ab8ba488a6957", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); }}; @Test From 2a1ab310dd4107549d1651db1fe781f589c1b1c4 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 24 Aug 2022 16:23:06 +0800 Subject: [PATCH 071/183] Start Ganache before testing --- e2e.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e.sh b/e2e.sh index 2e7d7a4146..d95ad55eff 100755 --- a/e2e.sh +++ b/e2e.sh @@ -26,7 +26,7 @@ touch output/emulator.log # create log file chmod 666 output/emulator.log # allow writing to log file adb logcat >> output/emulator.log & -#startGanache & # Manually start on CI server +startGanache & ./gradlew :app:uninstallAll :app:connectedNoAnalyticsDebugAndroidTest -x lint -PdisablePreDex From 7e0924253f5eab9de6751ec7d4bc9f3a9dd963ed Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 24 Aug 2022 16:30:38 +0800 Subject: [PATCH 072/183] Fix: ganache not found --- e2e.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e.sh b/e2e.sh index d95ad55eff..2cf0d84837 100755 --- a/e2e.sh +++ b/e2e.sh @@ -1,6 +1,7 @@ #!/bin/sh function startGanache() { + source ~/.zprofile ganache --chain.chainId 2 -h 0.0.0.0 -m "horse light surface bamboo combine item lumber tunnel choose acid mail feature" } From da5d8ef41fe021427a0bf69013d6d44b5aab7d17 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Fri, 26 Aug 2022 12:08:49 +0800 Subject: [PATCH 073/183] Refactor ens resolver (#2778) * Extract DASResolver * Extract CryptoResolver * Extract AvatarResolver * Extract interface Resolvable * Composition over inheritance --- .../app/interact/ImportWalletInteract.java | 2 +- .../app/repository/TokenRepository.java | 4 +- .../alphawallet/app/ui/MyAddressActivity.java | 6 +- .../app/ui/widget/entity/ENSHandler.java | 4 +- .../app/util/{ => ens}/AWEnsResolver.java | 179 +++--------------- .../app/util/ens/AvatarResolver.java | 56 ++++++ .../app/util/ens/CryptoResolver.java | 58 ++++++ .../alphawallet/app/util/ens/DASResolver.java | 62 ++++++ .../app/{web3j => util}/ens/EnsResolver.java | 26 ++- .../alphawallet/app/util/ens/Resolvable.java | 6 + .../app/viewmodel/HomeViewModel.java | 4 +- .../app/viewmodel/ImportWalletViewModel.java | 2 +- .../viewmodel/NameThisWalletViewModel.java | 7 +- .../app/viewmodel/WalletsViewModel.java | 4 +- .../alphawallet/app/widget/UserAvatar.java | 3 +- .../java/com/alphawallet/app/ENSTest.java | 56 ++---- 16 files changed, 260 insertions(+), 219 deletions(-) rename app/src/main/java/com/alphawallet/app/util/{ => ens}/AWEnsResolver.java (62%) create mode 100644 app/src/main/java/com/alphawallet/app/util/ens/AvatarResolver.java create mode 100644 app/src/main/java/com/alphawallet/app/util/ens/CryptoResolver.java create mode 100644 app/src/main/java/com/alphawallet/app/util/ens/DASResolver.java rename app/src/main/java/com/alphawallet/app/{web3j => util}/ens/EnsResolver.java (96%) create mode 100644 app/src/main/java/com/alphawallet/app/util/ens/Resolvable.java diff --git a/app/src/main/java/com/alphawallet/app/interact/ImportWalletInteract.java b/app/src/main/java/com/alphawallet/app/interact/ImportWalletInteract.java index da4cfc7d58..4fb65a751a 100644 --- a/app/src/main/java/com/alphawallet/app/interact/ImportWalletInteract.java +++ b/app/src/main/java/com/alphawallet/app/interact/ImportWalletInteract.java @@ -1,7 +1,7 @@ package com.alphawallet.app.interact; import com.alphawallet.app.repository.WalletRepositoryType; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; diff --git a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java index 4fd62fda5e..01e2bff1a0 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java @@ -28,7 +28,7 @@ import com.alphawallet.app.service.AWHttpService; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.TickerService; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.util.Utils; import com.alphawallet.token.entity.ContractAddress; import com.alphawallet.token.entity.MagicLinkData; @@ -355,7 +355,7 @@ public Token[] initNFTAssets(Wallet wallet, Token[] token) public Single resolveENS(long chainId, String ensName) { if (ensResolver == null) ensResolver = new AWEnsResolver(TokenRepository.getWeb3jService(MAINNET_ID), context); - return ensResolver.resolveENSAddress(ensName, true); + return ensResolver.resolveENSAddress(ensName); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/MyAddressActivity.java b/app/src/main/java/com/alphawallet/app/ui/MyAddressActivity.java index 0de37cd94c..e7637977d1 100644 --- a/app/src/main/java/com/alphawallet/app/ui/MyAddressActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/MyAddressActivity.java @@ -10,14 +10,12 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; -import android.widget.TextView; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.Nullable; import androidx.lifecycle.ViewModelProvider; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.entity.AddressMode; @@ -29,7 +27,7 @@ import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.ui.QRScanning.DisplayUtils; import com.alphawallet.app.ui.widget.entity.AmountReadyCallback; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.util.KeyboardUtils; import com.alphawallet.app.util.QRUtils; import com.alphawallet.app.viewmodel.MyAddressViewModel; @@ -41,8 +39,6 @@ import java.math.BigDecimal; -import javax.inject.Inject; - import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ENSHandler.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ENSHandler.java index 558b3ce4dc..44ce6ecf84 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ENSHandler.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ENSHandler.java @@ -18,7 +18,7 @@ import com.alphawallet.app.R; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.ui.widget.adapter.AutoCompleteAddressAdapter; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.util.Utils; import com.alphawallet.app.widget.InputAddress; import com.google.gson.Gson; @@ -225,7 +225,7 @@ else if (canBeENSName(to)) host.setWaitingSpinner(true); host.ENSName(to); - disposable = ensResolver.resolveENSAddress(to, performEnsSync) + disposable = ensResolver.resolveENSAddress(to) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(resolvedAddress -> onENSSuccess(resolvedAddress, to), this::onENSError); diff --git a/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java b/app/src/main/java/com/alphawallet/app/util/ens/AWEnsResolver.java similarity index 62% rename from app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java rename to app/src/main/java/com/alphawallet/app/util/ens/AWEnsResolver.java index 9dd8056406..383d8c8463 100644 --- a/app/src/main/java/com/alphawallet/app/util/AWEnsResolver.java +++ b/app/src/main/java/com/alphawallet/app/util/ens/AWEnsResolver.java @@ -1,4 +1,4 @@ -package com.alphawallet.app.util; +package com.alphawallet.app.util.ens; import android.content.Context; import android.text.TextUtils; @@ -8,25 +8,16 @@ import com.alphawallet.app.C; import com.alphawallet.app.entity.UnableToResolveENS; import com.alphawallet.app.service.OpenSeaService; -import com.alphawallet.app.util.das.DASBody; -import com.alphawallet.app.util.das.DASRecord; -import com.alphawallet.app.web3j.ens.EnsResolver; +import com.alphawallet.app.util.Utils; import com.alphawallet.token.tools.Numeric; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.json.JSONObject; -import org.web3j.abi.TypeReference; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Utf8String; -import org.web3j.ens.NameHash; import org.web3j.protocol.Web3j; -import org.web3j.protocol.http.HttpService; -import java.math.BigInteger; -import java.util.Arrays; import java.util.HashMap; +import java.util.Locale; import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; @@ -35,39 +26,33 @@ import io.reactivex.Single; import io.reactivex.schedulers.Schedulers; import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; import timber.log.Timber; /** * Created by James on 29/05/2019. * Stormbird in Sydney */ -public class AWEnsResolver extends EnsResolver +public class AWEnsResolver { - private static final long DEFAULT_SYNC_THRESHOLD = 1000 * 60 * 3; - private static final String DAS_LOOKUP = "https://indexer.da.systems/"; - private static final String DAS_NAME = "[DAS_NAME]"; - private static final String DAS_PAYLOAD = "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"das_searchAccount\",\"params\":[\"" + DAS_NAME + "\"]}"; private static final String OPENSEA_IMAGE_PREVIEW = "image_preview_url"; private static final String OPENSEA_IMAGE_ORIGINAL = "image_original_url"; //in case of SVG; Opensea breaks SVG compression - public static final String CRYPTO_RESOLVER = "0xD1E5b0FF1287aA9f9A268759062E4Ab08b9Dacbe"; - public static final String CRYPTO_ETH_KEY = "crypto.ETH.address"; private final Context context; private final OkHttpClient client; - + private HashMap resolvables; + private final EnsResolver ensResolver; + public AWEnsResolver(Web3j web3j, Context context) { - super(web3j); + this.ensResolver = new EnsResolver(web3j); this.context = context; this.client = setupClient(); - } - public AWEnsResolver(Web3j web3j) - { - super(web3j); - this.context = null; - this.client = setupClient(); + resolvables = new HashMap() { + { + put(".bit", new DASResolver(client)); + put(".crypto", new CryptoResolver(ensResolver)); + } + }; } /** @@ -84,7 +69,7 @@ public Single reverseResolveEns(String address) try { - ensName = reverseResolve(address); //no known ENS for this address, resolve from reverse resolver + ensName = ensResolver.reverseResolve(address); //no known ENS for this address, resolve from reverse resolver if (!TextUtils.isEmpty(ensName)) { //check ENS name integrity - it must point to the wallet address @@ -231,9 +216,9 @@ public String checkENSHistoryForAddress(String address) HashMap history = new Gson().fromJson(historyJson, new TypeToken>() { }.getType()); - if (history.containsKey(address.toLowerCase())) + if (history.containsKey(address.toLowerCase(Locale.ENGLISH))) { - ensName = history.get(address.toLowerCase()); + ensName = history.get(address.toLowerCase(Locale.ENGLISH)); } } @@ -251,11 +236,11 @@ private String fetchPreviouslyUsedENS(String address) HashMap history = new Gson().fromJson(historyJson, new TypeToken>() { }.getType()); - if (history.containsKey(address.toLowerCase())) + if (history.containsKey(address.toLowerCase(Locale.ENGLISH))) { - String previouslyUsedDomain = history.get(address.toLowerCase()); + String previouslyUsedDomain = history.get(address.toLowerCase(Locale.ENGLISH)); //perform an additional check, to ensure this ENS name is still valid, try this ENS name to see if it resolves to the address - ensName = resolveENSAddress(previouslyUsedDomain, true) + ensName = resolveENSAddress(previouslyUsedDomain) .map(resolvedAddress -> checkResolvedAddressMatches(resolvedAddress, address, previouslyUsedDomain)) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) @@ -284,13 +269,13 @@ private String checkResolvedAddressMatches(String resolvedAddress, String addres * @param ensName ensName to be resolved to address * @return Ethereum address or empty string */ - public Single resolveENSAddress(String ensName, boolean performNodeSync) + public Single resolveENSAddress(String ensName) { return Single.fromCallable(() -> { Timber.d("Verify: %s", ensName); String address = ""; - if (!isValidEnsName(ensName)) return ""; + if (!EnsResolver.isValidEnsName(ensName)) return ""; try { address = resolve(ensName); @@ -304,133 +289,29 @@ public Single resolveENSAddress(String ensName, boolean performNodeSync) }).onErrorReturnItem(""); } - @Override public String resolve(String ensName) throws Exception { if (TextUtils.isEmpty(ensName)) { return ""; } - if (ensName.endsWith(".bit")) - { - return resolveDAS(ensName); - } - else if (ensName.endsWith(".crypto")) //check crypto namespace - { - byte[] nameHash = NameHash.nameHashAsBytes(ensName); - BigInteger nameId = new BigInteger(nameHash); - String resolverAddress = getContractData(CRYPTO_RESOLVER, getResolverOf(nameId), ""); - if (!TextUtils.isEmpty(resolverAddress)) - { - return getContractData(resolverAddress, get(nameId), ""); - } - else - { - return ""; - } - } - else - { - return super.resolve(ensName); - } - } - - private String resolveDAS(String ensName) - { - String payload = DAS_PAYLOAD.replace(DAS_NAME, ensName); - - RequestBody requestBody = RequestBody.create(payload, HttpService.JSON_MEDIA_TYPE); - Request request = new Request.Builder() - .url(DAS_LOOKUP) - .post(requestBody) - .build(); - try (okhttp3.Response response = client.newCall(request).execute()) - { - //get result - String result = response.body() != null ? response.body().string() : ""; - - DASBody dasResult = new Gson().fromJson(result, DASBody.class); - dasResult.buildMap(); - - //find ethereum entry - DASRecord ethLookup = dasResult.records.get("address.eth"); - if (ethLookup != null) - { - return ethLookup.getAddress(); - } - else - { - return dasResult.getEthOwner(); - } - } - catch (Exception e) + Resolvable resolvable = resolvables.get(suffixOf(ensName)); + if (resolvable == null) { - Timber.tag("ENS").e(e); + resolvable = ensResolver; } - - return ""; - } - - private Function getResolverOf(BigInteger nameId) - { - return new Function("resolverOf", - Arrays.asList(new org.web3j.abi.datatypes.Uint(nameId)), - Arrays.asList(new TypeReference
() - { - })); - } - - private Function getAvatar(byte[] nameHash) - { - return new Function("text", - Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash), - new org.web3j.abi.datatypes.Utf8String("avatar")), - Arrays.asList(new TypeReference() - { - })); - } - - private Function getResolver(byte[] nameHash) - { - return new Function("resolver", - Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash)), - Arrays.asList(new TypeReference
() - { - })); + return resolvable.resolve(ensName); } - private Function get(BigInteger nameId) + private String suffixOf(String ensName) { - return new Function("get", - Arrays.asList(new org.web3j.abi.datatypes.Utf8String(CRYPTO_ETH_KEY), new org.web3j.abi.datatypes.generated.Uint256(nameId)), - Arrays.asList(new TypeReference() - { - })); + return ensName.substring(ensName.lastIndexOf(".")); } public String resolveAvatar(String ensName) { - if (isValidEnsName(ensName, addressLength)) - { - try - { - String resolverAddress = getResolverAddress(ensName); - if (!TextUtils.isEmpty(resolverAddress)) - { - byte[] nameHash = NameHash.nameHashAsBytes(ensName); - //now attempt to get the address of this ENS - return getContractData(resolverAddress, getAvatar(nameHash), ""); - } - } - catch (Exception e) - { - // - Timber.e(e); - } - } - - return ""; + return new AvatarResolver(ensResolver).resolve(ensName); } public String resolveAvatarFromAddress(String address) @@ -439,7 +320,7 @@ public String resolveAvatarFromAddress(String address) { try { - String ensName = reverseResolve(address); + String ensName = ensResolver.reverseResolve(address); return resolveAvatar(ensName); } catch (Exception e) diff --git a/app/src/main/java/com/alphawallet/app/util/ens/AvatarResolver.java b/app/src/main/java/com/alphawallet/app/util/ens/AvatarResolver.java new file mode 100644 index 0000000000..898d7a2919 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/ens/AvatarResolver.java @@ -0,0 +1,56 @@ +package com.alphawallet.app.util.ens; + +import android.text.TextUtils; + +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.Utf8String; +import org.web3j.ens.NameHash; + +import java.util.Arrays; + +import timber.log.Timber; + +public class AvatarResolver implements Resolvable +{ + private final EnsResolver ensResolver; + + public AvatarResolver(EnsResolver ensResolver) + { + this.ensResolver = ensResolver; + } + + public String resolve(String ensName) + { + if (ensResolver.validate(ensName)) + { + try + { + String resolverAddress = ensResolver.getResolverAddress(ensName); + if (!TextUtils.isEmpty(resolverAddress)) + { + byte[] nameHash = NameHash.nameHashAsBytes(ensName); + //now attempt to get the address of this ENS + return ensResolver.getContractData(resolverAddress, getAvatar(nameHash), ""); + } + } + catch (Exception e) + { + // + Timber.e(e); + } + } + + return ""; + } + + private Function getAvatar(byte[] nameHash) + { + return new Function("text", + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(nameHash), + new org.web3j.abi.datatypes.Utf8String("avatar")), + Arrays.asList(new TypeReference() + { + })); + } +} diff --git a/app/src/main/java/com/alphawallet/app/util/ens/CryptoResolver.java b/app/src/main/java/com/alphawallet/app/util/ens/CryptoResolver.java new file mode 100644 index 0000000000..1f9adc4d5b --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/ens/CryptoResolver.java @@ -0,0 +1,58 @@ +package com.alphawallet.app.util.ens; + +import android.text.TextUtils; + +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.Function; +import org.web3j.abi.datatypes.Utf8String; +import org.web3j.ens.NameHash; + +import java.math.BigInteger; +import java.util.Arrays; + +public class CryptoResolver implements Resolvable +{ + private static final String CRYPTO_RESOLVER = "0xD1E5b0FF1287aA9f9A268759062E4Ab08b9Dacbe"; + private static final String CRYPTO_ETH_KEY = "crypto.ETH.address"; + + private final EnsResolver ensResolver; + + public CryptoResolver(EnsResolver ensResolver) + { + this.ensResolver = ensResolver; + } + + public String resolve(String ensName) throws Exception + { + byte[] nameHash = NameHash.nameHashAsBytes(ensName); + BigInteger nameId = new BigInteger(nameHash); + String resolverAddress = ensResolver.getContractData(CRYPTO_RESOLVER, getResolverOf(nameId), ""); + if (!TextUtils.isEmpty(resolverAddress)) + { + return ensResolver.getContractData(resolverAddress, get(nameId), ""); + } + else + { + return ""; + } + } + + private Function get(BigInteger nameId) + { + return new Function("get", + Arrays.asList(new org.web3j.abi.datatypes.Utf8String(CRYPTO_ETH_KEY), new org.web3j.abi.datatypes.generated.Uint256(nameId)), + Arrays.asList(new TypeReference() + { + })); + } + + private Function getResolverOf(BigInteger nameId) + { + return new Function("resolverOf", + Arrays.asList(new org.web3j.abi.datatypes.Uint(nameId)), + Arrays.asList(new TypeReference
() + { + })); + } +} diff --git a/app/src/main/java/com/alphawallet/app/util/ens/DASResolver.java b/app/src/main/java/com/alphawallet/app/util/ens/DASResolver.java new file mode 100644 index 0000000000..a31c100099 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/ens/DASResolver.java @@ -0,0 +1,62 @@ +package com.alphawallet.app.util.ens; + +import com.alphawallet.app.util.das.DASBody; +import com.alphawallet.app.util.das.DASRecord; +import com.google.gson.Gson; + +import org.web3j.protocol.http.HttpService; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import timber.log.Timber; + +public class DASResolver implements Resolvable +{ + private static final String DAS_LOOKUP = "https://indexer.da.systems/"; + private static final String DAS_NAME = "[DAS_NAME]"; + private static final String DAS_PAYLOAD = "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"das_searchAccount\",\"params\":[\"" + DAS_NAME + "\"]}"; + private final OkHttpClient client; + + public DASResolver(OkHttpClient client) + { + this.client = client; + } + + public String resolve(String name) + { + String payload = DAS_PAYLOAD.replace(DAS_NAME, name); + + RequestBody requestBody = RequestBody.create(payload, HttpService.JSON_MEDIA_TYPE); + Request request = new Request.Builder() + .url(DAS_LOOKUP) + .post(requestBody) + .build(); + + try (okhttp3.Response response = client.newCall(request).execute()) + { + //get result + String result = response.body() != null ? response.body().string() : ""; + + DASBody dasResult = new Gson().fromJson(result, DASBody.class); + dasResult.buildMap(); + + //find ethereum entry + DASRecord ethLookup = dasResult.records.get("address.eth"); + if (ethLookup != null) + { + return ethLookup.getAddress(); + } + else + { + return dasResult.getEthOwner(); + } + } + catch (Exception e) + { + Timber.tag("ENS").e(e); + } + + return ""; + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolver.java b/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java similarity index 96% rename from app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolver.java rename to app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java index 89702abc08..5bdf7b9ac0 100644 --- a/app/src/main/java/com/alphawallet/app/web3j/ens/EnsResolver.java +++ b/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java @@ -10,7 +10,7 @@ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package com.alphawallet.app.web3j.ens; +package com.alphawallet.app.util.ens; import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; @@ -18,6 +18,13 @@ import com.alphawallet.app.entity.tokenscript.TokenscriptFunction; import com.alphawallet.app.util.Utils; +import com.alphawallet.app.web3j.ens.Contracts; +import com.alphawallet.app.web3j.ens.EnsGatewayRequestDTO; +import com.alphawallet.app.web3j.ens.EnsGatewayResponseDTO; +import com.alphawallet.app.web3j.ens.EnsResolutionException; +import com.alphawallet.app.web3j.ens.EnsUtils; +import com.alphawallet.app.web3j.ens.NameHash; +import com.alphawallet.app.web3j.ens.OffchainLookup; import com.alphawallet.token.entity.ContractAddress; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; @@ -42,8 +49,6 @@ import org.web3j.protocol.core.DefaultBlockParameterName; import org.web3j.protocol.core.methods.response.EthCall; import org.web3j.protocol.core.methods.response.NetVersion; -import org.web3j.tx.ClientTransactionManager; -import org.web3j.tx.TransactionManager; import org.web3j.utils.Numeric; import java.io.BufferedReader; @@ -62,11 +67,11 @@ import okhttp3.ResponseBody; /** Resolution logic for contract addresses. According to https://eips.ethereum.org/EIPS/eip-2544 */ -public class EnsResolver { +public class EnsResolver implements Resolvable +{ private static final Logger log = LoggerFactory.getLogger(EnsResolver.class); - public static final long DEFAULT_SYNC_THRESHOLD = 1000 * 60 * 3; public static final MediaType JSON = MediaType.parse("application/json"); // Permit number offchain calls for a single contract call. @@ -76,7 +81,6 @@ public class EnsResolver { private final Web3j web3j; protected final int addressLength; - private final TransactionManager transactionManager; protected final long chainId; private OkHttpClient client = new OkHttpClient(); @@ -86,7 +90,6 @@ public class EnsResolver { public EnsResolver(Web3j web3j, int addressLength) { this.web3j = web3j; - transactionManager = new ClientTransactionManager(web3j, null); // don't use empty string this.addressLength = addressLength; long chainId = 1; @@ -120,6 +123,7 @@ protected ContractAddress obtainOffchainResolverAddr(String ensName) throws Exce * @param ensName The specified node. * @return address of the resolver. */ + @Override public String resolve(String ensName) throws Exception { if (TextUtils.isEmpty(ensName) || (ensName.trim().length() == 1 && ensName.contains("."))) { @@ -384,7 +388,7 @@ private Function getResolver(byte[] nameHash) })); } - protected String getResolverAddress(String ensName) throws Exception + public String getResolverAddress(String ensName) throws Exception { String registryContract = Contracts.resolveRegistryContract(chainId); byte[] nameHash = NameHash.nameHashAsBytes(ensName); @@ -398,6 +402,10 @@ protected String getResolverAddress(String ensName) throws Exception return address; } + public boolean validate(String input) { + return isValidEnsName(input, addressLength); + } + public static boolean isValidEnsName(String input) { return isValidEnsName(input, Keys.ADDRESS_LENGTH_IN_HEX); } @@ -483,7 +491,7 @@ private String resolveName(byte[] node, String address) throws Exception return getContractData(address, function, ""); } - protected T getContractData(String address, Function function, T type) throws Exception + public T getContractData(String address, Function function, T type) throws Exception { String responseValue = callSmartContractFunction(function, address); diff --git a/app/src/main/java/com/alphawallet/app/util/ens/Resolvable.java b/app/src/main/java/com/alphawallet/app/util/ens/Resolvable.java new file mode 100644 index 0000000000..eb4611517d --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/ens/Resolvable.java @@ -0,0 +1,6 @@ +package com.alphawallet.app.util.ens; + +public interface Resolvable +{ + String resolve(String ensName) throws Exception; +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java index 1f9cf79837..f737f113e9 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java @@ -4,8 +4,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import android.app.Activity; -import android.app.DownloadManager; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -60,7 +58,7 @@ import com.alphawallet.app.ui.HomeActivity; import com.alphawallet.app.ui.ImportWalletActivity; import com.alphawallet.app.ui.SendActivity; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.util.QRParser; import com.alphawallet.app.util.RateApp; import com.alphawallet.app.util.Utils; diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/ImportWalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/ImportWalletViewModel.java index 4c061c71d3..fdb8e15623 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/ImportWalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/ImportWalletViewModel.java @@ -18,7 +18,7 @@ import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.KeyService; import com.alphawallet.app.ui.widget.OnSetWatchWalletListener; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import com.fasterxml.jackson.databind.ObjectMapper; import org.web3j.crypto.ECKeyPair; diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java index 5349c83bb4..e626daf0d4 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java @@ -13,7 +13,8 @@ import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.repository.WalletItem; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; +import com.alphawallet.app.util.ens.EnsResolver; import javax.annotation.Nullable; import javax.inject.Inject; @@ -102,10 +103,10 @@ public void setWalletName(String name, Realm.Transaction.OnSuccess onSuccess) public boolean checkEnsName(String newName, Realm.Transaction.OnSuccess onSuccess) { - if (!TextUtils.isEmpty(newName) && AWEnsResolver.isValidEnsName(newName)) + if (!TextUtils.isEmpty(newName) && EnsResolver.isValidEnsName(newName)) { //does this new name correspond to ENS? - ensResolver.resolveENSAddress(newName, true) + ensResolver.resolveENSAddress(newName) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(addr -> checkAddress(addr, newName, onSuccess)) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java index 41f43774c9..cfca2455a5 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java @@ -34,11 +34,9 @@ import com.alphawallet.app.service.KeyService; import com.alphawallet.app.service.TickerService; import com.alphawallet.app.service.TokensService; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; diff --git a/app/src/main/java/com/alphawallet/app/widget/UserAvatar.java b/app/src/main/java/com/alphawallet/app/widget/UserAvatar.java index 62c93b1a7a..34cee27d78 100644 --- a/app/src/main/java/com/alphawallet/app/widget/UserAvatar.java +++ b/app/src/main/java/com/alphawallet/app/widget/UserAvatar.java @@ -18,12 +18,11 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.R; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.ui.widget.entity.AvatarWriteCallback; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.util.Blockies; import com.bumptech.glide.Glide; import com.bumptech.glide.load.DataSource; diff --git a/app/src/test/java/com/alphawallet/app/ENSTest.java b/app/src/test/java/com/alphawallet/app/ENSTest.java index ac6268fc8a..613adb5a1b 100644 --- a/app/src/test/java/com/alphawallet/app/ENSTest.java +++ b/app/src/test/java/com/alphawallet/app/ENSTest.java @@ -7,16 +7,13 @@ import static org.junit.Assert.assertEquals; import com.alphawallet.app.service.AWHttpService; -import com.alphawallet.app.util.AWEnsResolver; +import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.web3j.ens.Contracts; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; import org.junit.Test; -import org.web3j.protocol.ObjectMapperFactory; import org.web3j.protocol.Web3j; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; @@ -25,39 +22,16 @@ public class ENSTest { - @Test - public void testResolveRegistryContract() { - assertEquals(Contracts.resolveRegistryContract(MAINNET_ID), (Contracts.MAINNET)); - assertEquals(Contracts.resolveRegistryContract(ROPSTEN_ID), (Contracts.ROPSTEN)); - assertEquals(Contracts.resolveRegistryContract(RINKEBY_ID), (Contracts.RINKEBY)); - } - - private final AWHttpService web3jService; - private final Web3j web3j; - private final AWEnsResolver ensResolver; - - private ObjectMapper om = ObjectMapperFactory.getObjectMapper(); - - private static List urls = new ArrayList<>(); - - private String sender = "0x226159d592E2b063810a10Ebf6dcbADA94Ed68b8"; - private static String Inf = "p8qs5p30583q5q65n40s8nn89s257964"; - - private String data = "0x00112233"; + private AWEnsResolver ensResolver; - public static String LOOKUP_HEX = - "0x556f1830000000000000000000000000c1735677a60884abbcf72295e88d47764beda28200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000160f4d4d2f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004768747470733a2f2f6f6666636861696e2d7265736f6c7665722d6578616d706c652e75632e722e61707073706f742e636f6d2f7b73656e6465727d2f7b646174617d2e6a736f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e49061b92300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001701310f6f6666636861696e6578616d706c65036574680000000000000000000000000000000000000000000000000000000000000000000000000000000000243b3b57de1c9fb8c1fe76f464ccec6d2c003169598fdfcbcb6bbddf6af9c097a39fa0048c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e49061b92300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001701310f6f6666636861696e6578616d706c65036574680000000000000000000000000000000000000000000000000000000000000000000000000000000000243b3b57de1c9fb8c1fe76f464ccec6d2c003169598fdfcbcb6bbddf6af9c097a39fa0048c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + private static final String Inf = "p8qs5p30583q5q65n40s8nn89s257964"; - public static String RESOLVED_NAME_HEX = - "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000041563129cdbbd0c5d3e1c86cf9563926b243834d"; - - public ENSTest() + @Before + public void setUp() { - web3jService = getWeb3jService(); - web3j = getWeb3j(web3jService); - ensResolver = new AWEnsResolver(web3j); - urls.add("https://example-1.com/gateway/{sender}/{data}.json"); - urls.add("https://example-2.com/gateway/{sender}/{data}.json"); + AWHttpService web3jService = getWeb3jService(); + Web3j web3j = getWeb3j(web3jService); + ensResolver = new AWEnsResolver(web3j, null); } public static AWHttpService getWeb3jService() @@ -76,6 +50,13 @@ public static Web3j getWeb3j(AWHttpService service) return Web3j.build(service); } + @Test + public void testResolveRegistryContract() { + assertEquals(Contracts.resolveRegistryContract(MAINNET_ID), (Contracts.MAINNET)); + assertEquals(Contracts.resolveRegistryContract(ROPSTEN_ID), (Contracts.ROPSTEN)); + assertEquals(Contracts.resolveRegistryContract(RINKEBY_ID), (Contracts.RINKEBY)); + } + @Test public void testResolve() throws Exception { @@ -115,9 +96,8 @@ public void testAvatarAddressResolve() throws Exception { @Test public void testReverseResolve() throws Exception { - assertEquals( - ensResolver.reverseResolve("0xd8da6bf26964af9d7eed9e03e53415d37aa96045"), + ensResolver.reverseResolveEns("0xd8da6bf26964af9d7eed9e03e53415d37aa96045").blockingGet(), ("vitalik.eth")); } @@ -135,6 +115,4 @@ public void testNameHash() { nameHash("foo.eth"), ("0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f")); } - - } From ac1259f4da89a5ee18d8fa231fa2f9ccea7857c4 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 30 Aug 2022 08:31:26 +0800 Subject: [PATCH 074/183] Add AirCash (#2783) --- app/src/main/assets/dapps_list.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/dapps_list.json b/app/src/main/assets/dapps_list.json index 1518d345ef..4c139107da 100644 --- a/app/src/main/assets/dapps_list.json +++ b/app/src/main/assets/dapps_list.json @@ -88,5 +88,6 @@ {"name": "SWFT", "description": "One Stop Cross-Chain swap, supporting 300+ tokens on 30+ chains", "url": "https://defi.swft.pro?sourceFlag=alpha", "category": "Exchange"}, {"name": "Swapzone", "description": "Swapzone is a custody-free cryptocurrency exchange aggregator with no registration needed.", "url": "https://swapzone.io/", "category": "Exchange"}, {"name": "mail³", "description": "Decentralized mail system for web3 natives.", "url": "https://app.mail3.me/", "category": "Social Media"}, - {"name": "ApeNow", "description": "Buy now, pay later marketplace for NFTs.", "url": "https://www.apenowpaylater.com/", "category": "Marketplace"} + {"name": "ApeNow", "description": "Buy now, pay later marketplace for NFTs.", "url": "https://www.apenowpaylater.com/", "category": "Marketplace"}, + {"name": "AirCash", "description": "AirCash is the first and largest decentralized OTC platform in the galaxy.", "url": "https://aircash.finance", "category": "Exchange"} ] From 045a95a503912b0c90867fd1ec19b1f0a0b2233b Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 30 Aug 2022 12:23:07 +1000 Subject: [PATCH 075/183] Key diagnostics (#2786) * key correction * first commit * Update code * Encode string * Remove unused code * Deduplicate * Update wallet data * Add unit test * key correction * first commit * Update code * Encode string * Remove unused code * Deduplicate * Update wallet data * Add unit test * Pass * Fix test * Fix test * Fix test * Remove test key dump and move into separate function * Add description * Set timeout for e2e test CI job * Close security warning before every tests * Clean code * Close ANR dialog if exists Co-authored-by: Seaborn Lee --- .github/workflows/e2e.yml | 1 + .../java/com/alphawallet/app/BaseE2ETest.java | 27 +- .../app/ImportWalletWithSeedPhraseTest.java | 1 - .../com/alphawallet/app/KeyServiceTest.java | 70 +++ .../java/com/alphawallet/app/steps/Steps.java | 32 +- app/src/main/AndroidManifest.xml | 4 + .../app/repository/WalletDataRealmSource.java | 93 +++- .../alphawallet/app/service/KeyService.java | 200 +++++--- .../app/service/KeystoreAccountService.java | 25 +- .../app/service/LegacyKeystore.java | 29 +- .../app/ui/ImportSeedFragment.java | 3 +- .../app/ui/WalletActionsActivity.java | 19 +- .../app/ui/WalletDiagnosticActivity.java | 477 ++++++++++++++++++ .../app/viewmodel/BackupKeyViewModel.java | 20 +- app/src/main/res/drawable/ic_key_status.xml | 5 + .../res/layout/activity_wallet_diagnostic.xml | 148 ++++++ app/src/main/res/menu/menu_wallet_manage.xml | 12 + app/src/main/res/values-es/strings.xml | 11 + app/src/main/res/values-fr/strings.xml | 11 + app/src/main/res/values-my/strings.xml | 11 + app/src/main/res/values-vi/strings.xml | 11 + app/src/main/res/values-zh/strings.xml | 11 + app/src/main/res/values/strings.xml | 11 + 23 files changed, 1095 insertions(+), 137 deletions(-) create mode 100644 app/src/androidTest/java/com/alphawallet/app/KeyServiceTest.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/WalletDiagnosticActivity.java create mode 100644 app/src/main/res/drawable/ic_key_status.xml create mode 100644 app/src/main/res/layout/activity_wallet_diagnostic.xml create mode 100644 app/src/main/res/menu/menu_wallet_manage.xml diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index f788da8fe3..26e3a470e9 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,6 +7,7 @@ on: jobs: test: runs-on: self-hosted + timeout-minutes: 5 strategy: matrix: api-level: [30] diff --git a/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java b/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java index 0fa415d678..5785d38362 100644 --- a/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java +++ b/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java @@ -2,14 +2,23 @@ import static androidx.test.espresso.Espresso.setFailureHandler; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static com.alphawallet.app.steps.Steps.closeSecurityWarning; import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; import com.alphawallet.app.ui.SplashActivity; import com.alphawallet.app.util.CustomFailureHandler; +import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.rules.TestWatcher; @@ -22,11 +31,27 @@ public abstract class BaseE2ETest @Rule public TestRule watcher = new TestWatcher() { protected void starting(Description description) { - setFailureHandler(new CustomFailureHandler(description.getMethodName(), InstrumentationRegistry.getInstrumentation().getTargetContext())); + setFailureHandler(new CustomFailureHandler(description.getMethodName(), getInstrumentation().getTargetContext())); } }; @Rule public ActivityScenarioRule activityScenarioRule = new ActivityScenarioRule<>(SplashActivity.class); + + @BeforeClass + public static void dismissANRSystemDialog() throws UiObjectNotFoundException + { + UiDevice device = UiDevice.getInstance(getInstrumentation()); + UiObject waitButton = device.findObject(new UiSelector().textContains("wait")); + if (waitButton.exists()) { + waitButton.click(); + } + } + + @Before + public void setUp() + { + closeSecurityWarning(); + } } diff --git a/app/src/androidTest/java/com/alphawallet/app/ImportWalletWithSeedPhraseTest.java b/app/src/androidTest/java/com/alphawallet/app/ImportWalletWithSeedPhraseTest.java index a309e4131d..79b9f16143 100644 --- a/app/src/androidTest/java/com/alphawallet/app/ImportWalletWithSeedPhraseTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/ImportWalletWithSeedPhraseTest.java @@ -41,7 +41,6 @@ public void should_import_wallet_with_seed_phrase() { String seedPhrase = array[0]; String existedWalletAddress = array[1]; - closeSecurityWarning(); click(withText("I already have a Wallet")); onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_seed)))))).perform(replaceText(seedPhrase)); diff --git a/app/src/androidTest/java/com/alphawallet/app/KeyServiceTest.java b/app/src/androidTest/java/com/alphawallet/app/KeyServiceTest.java new file mode 100644 index 0000000000..7e9be38e7d --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/KeyServiceTest.java @@ -0,0 +1,70 @@ +package com.alphawallet.app; + +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.alphawallet.app.assertions.Should.shouldSee; +import static com.alphawallet.app.steps.Steps.closeSecurityWarning; +import static com.alphawallet.app.steps.Steps.createNewWallet; +import static com.alphawallet.app.steps.Steps.gotoSettingsPage; +import static com.alphawallet.app.steps.Steps.importKSWalletFromFrontPage; +import static com.alphawallet.app.util.Helper.click; +import static org.junit.Assert.fail; + +import android.os.Build; + +import com.alphawallet.app.util.Helper; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class KeyServiceTest extends BaseE2ETest { + private static final String keystore = "{\"address\":\"f9c883c8dca140ebbdc87a225fe6e330be5d25ef\",\"id\":\"5648908b-1862-4f3e-b425-d1ba0790a601\",\"version\":3,\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"bcbfcffb52f42e9d149b97a8512d4c49\"},\"ciphertext\":\"967d3cd0db82445e4e74a6d5e537c799632e91cf0ca6f9fec17c769812e9454f\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"084c44b6e76e2b879257520ac00bb59c93e17321ce4a029f9b8294e304defc7a\"},\"mac\":\"0e4a74746d0c3e2739653200bcffb92716e77677d41f84c1184a4eb2054963c6\"}}\n"; + private static final String password = "hellohello"; + + @Test + public void cipher_integrity_test() { + createNewWallet(); + gotoSettingsPage(); + + click(withText("Change / Add Wallet")); + click(withId(R.id.manage_wallet_btn)); + click(withId(R.id.action_key_status)); + + click(withText("Run Key Diagnostic")); + + Helper.wait(1); + + //now check the key is decoded correctly + shouldSee("Key found"); + shouldSee("Unlocked"); + shouldSee("Seed Phrase detected public key"); + shouldSee("HDKEY"); + } + + @Test + public void cipher_integrity_test_keystore() { + importKSWalletFromFrontPage(keystore, password); + + gotoSettingsPage(); + click(withText("Change / Add Wallet")); + Helper.wait(1); + click(withId(R.id.manage_wallet_btn)); + Helper.wait(1); + + click(withId(R.id.action_key_status)); + + Helper.wait(1); + + click(withText("Run Key Diagnostic")); + + Helper.wait(1); + + //now check the key is decoded correctly + shouldSee("Key found"); + shouldSee("Unlocked"); + shouldSee("Decoded Keystore public key"); + shouldSee("KEYSTORE"); + } +} diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index 913b26549d..d2aba1c16d 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -36,10 +36,9 @@ public class Steps { public static void createNewWallet() { - closeSecurityWarning(); click(withId(R.id.button_create)); closeSelectNetworkPage(); - click(withText(R.string.action_close)); // works well locally but NOT work with GitHub actions + click(withText(R.string.action_close)); } public static void closeSecurityWarning() @@ -151,6 +150,35 @@ public static void importWalletFromSettingsPage(String text) { closeSelectNetworkPage(); } + public static void importKSWalletFromFrontPage(String keystore, String password) { + click(withText("I already have a Wallet")); + click(withText("Keystore")); + Helper.wait(1); + onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_keystore)))))).perform(replaceText(keystore)); + Helper.wait(1); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis + click(withText("Continue")); + onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_password)))))).perform(replaceText(password)); + click(withText("Continue")); + Helper.wait(5); + } + + public static void importKSWalletFromSettingsPage(String keystore, String password) { + gotoSettingsPage(); + click(withText("Change / Add Wallet")); + click(withId(R.id.action_add)); + click(withId(R.id.import_account_action)); + click(withText("Keystore")); + Helper.wait(1); + onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_keystore)))))).perform(replaceText(keystore)); + Helper.wait(1); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis + click(withText("Continue")); + onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_password)))))).perform(replaceText(password)); + click(withText("Continue")); + Helper.wait(5); + shouldSee("Select Active Networks"); + pressBack(); + } + public static void gotoSettingsPage() { click(withId(R.id.nav_settings_text)); } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4d03b063d3..953d3be20a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -311,6 +311,10 @@ android:name=".ui.NodeStatusActivity" android:label="@string/action_node_status" /> + + populateWalletData(Wallet[] keystoreWallets, KeyService Map walletList; try (Realm realm = realmManager.getWalletDataRealmInstance()) { - walletList = loadOrCreateKeyRealmDB(realm, keystoreWallets); //call has action on upgrade to new UX + walletList = loadOrCreateKeyRealmDB(realm, keystoreWallets, keyService); //call has action on upgrade to new UX //Add additional - non critical wallet data. This database can be voided for upgrade if required for (Wallet wallet : walletList.values()) { @@ -53,19 +54,16 @@ public Single populateWalletData(Wallet[] keystoreWallets, KeyService composeWallet(wallet, data); } - - //TODO: Make this a manual process. - //recoverLostWallets(realm, keystoreWallets, walletList, keyService); } - migrateWalletTypeData(walletList); + migrateWalletTypeData(walletList, keyService); Timber.tag("RealmDebug").d("populate %s", walletList.size()); return walletList.values().toArray(new Wallet[0]); }); } - private Map loadOrCreateKeyRealmDB(Realm realm, Wallet[] wallets) + private Map loadOrCreateKeyRealmDB(Realm realm, Wallet[] wallets, KeyService keyService) { Map walletList = new HashMap<>(); List keyStoreList = walletArrayToAddressList(wallets); @@ -75,6 +73,8 @@ private Map loadOrCreateKeyRealmDB(Realm realm, Wallet[] wallets .sort("dateAdded", Sort.ASCENDING) .findAll(); + List walletUpdates = new ArrayList<>(); + if (realmKeyTypes.size() > 0) { //Load fixed wallet data: wallet type, creation and backup times @@ -87,23 +87,39 @@ private Map loadOrCreateKeyRealmDB(Realm realm, Wallet[] wallets continue; } + if (w.type == WalletType.KEYSTORE_LEGACY && !testLegacyCipher(w, keyService)) + { + w.type = WalletType.KEYSTORE; + walletUpdates.add(w); + } + walletList.put(w.address.toLowerCase(), w); } } else //only zero on upgrade from v2.01.3 and lower (pre-HD key) { - realm.executeTransaction(r -> { - for (Wallet wallet : wallets) + for (Wallet wallet : wallets) + { + wallet.authLevel = KeyService.AuthenticationLevel.TEE_NO_AUTHENTICATION; + if (testLegacyCipher(wallet, keyService)) { - wallet.authLevel = KeyService.AuthenticationLevel.TEE_NO_AUTHENTICATION; wallet.type = WalletType.KEYSTORE_LEGACY; - storeKeyData(wallet, r); - walletList.put(wallet.address.toLowerCase(), wallet); } - }); + else + { + wallet.type = WalletType.KEYSTORE; + } + walletList.put(wallet.address.toLowerCase(), wallet); + walletUpdates.add(wallet); + } } - Timber.tag("RealmDebug").d("loadorcreate " + walletList.size()); + if (walletUpdates.size() > 0) + { + storeWallets(realm, walletUpdates.toArray(new Wallet[0])); + } + + Timber.tag("RealmDebug").d("loadorcreate %s", walletList.size()); return walletList; } @@ -147,23 +163,32 @@ private String balance(RealmWalletData data) else return value; } - public Single storeWallets(Wallet[] wallets) { + public Single storeWallets(Wallet[] wallets) + { return Single.fromCallable(() -> { - try (Realm realm = realmManager.getWalletDataRealmInstance()) { - - realm.executeTransaction(r -> { - for (Wallet wallet : wallets) - { - storeKeyData(wallet, r); - } - }); - } catch (Exception e) { + try (Realm realm = realmManager.getWalletDataRealmInstance()) + { + storeWallets(realm, wallets); + } + catch (Exception e) + { Timber.e(e, "storeWallets: %s", e.getMessage()); } return wallets; }); } + private void storeWallets(Realm realm, Wallet[] wallets) + { + realm.executeTransaction(r -> { + for (Wallet wallet : wallets) + { + storeKeyData(wallet, r); + storeWalletData(wallet, r); + } + }); + } + public Single storeWallet(Wallet wallet) { return deleteWallet(wallet) //refresh data .flatMap(deletedWallet -> Single.fromCallable(() -> { @@ -180,7 +205,7 @@ public void updateWalletData(Wallet wallet, Realm.Transaction.OnSuccess onSucces realm.executeTransactionAsync(r -> { storeKeyData(wallet, r); storeWalletData(wallet, r); - Timber.tag("RealmDebug").d("storedKeydata " + wallet.address); + Timber.tag("RealmDebug").d("storedKeydata %s", wallet.address); }, onSuccess); } catch (Exception e) @@ -219,7 +244,7 @@ public void updateWalletItem(Wallet wallet, WalletItem item, Realm.Transaction.O r.insertOrUpdate(walletData); } - Timber.tag("RealmDebug").d("storedKeydata " + wallet.address); + Timber.tag("RealmDebug").d("storedKeydata %s", wallet.address); }, onSuccess); } @@ -483,9 +508,16 @@ private void storeWalletData(Wallet wallet, Realm r) r.insertOrUpdate(item); } + private boolean testLegacyCipher(Wallet w, KeyService service) + { + //test for legacy cipher, any failure we know it's a KEYSTORE + Pair cipherTest = service.testCipher(w.address, KeyService.LEGACY_CIPHER_ALGORITHM); + return cipherTest.first == KeyService.KeyExceptionType.SUCCESSFUL_DECODE; + } + //One-time removal of the WalletTypeRealmInstance usage - this extra database was a // workaround for an issue that has since been fixed correctly. - private void migrateWalletTypeData(Map walletList) + private void migrateWalletTypeData(Map walletList, KeyService service) { Map walletTypeData = new HashMap<>(); @@ -498,7 +530,14 @@ private void migrateWalletTypeData(Map walletList) for (RealmKeyType rk : rr) { Wallet w = composeKeyType(rk); - if (w != null) walletTypeData.put(w.address.toLowerCase(), w); + if (w != null) + { + walletTypeData.put(w.address.toLowerCase(), w); + if (w.type == WalletType.KEYSTORE_LEGACY && !testLegacyCipher(w, service)) + { + w.type = WalletType.KEYSTORE; + } + } } } diff --git a/app/src/main/java/com/alphawallet/app/service/KeyService.java b/app/src/main/java/com/alphawallet/app/service/KeyService.java index 0f9ed0eaba..49852f4774 100644 --- a/app/src/main/java/com/alphawallet/app/service/KeyService.java +++ b/app/src/main/java/com/alphawallet/app/service/KeyService.java @@ -23,6 +23,7 @@ import android.security.keystore.KeyProperties; import android.security.keystore.StrongBoxUnavailableException; import android.security.keystore.UserNotAuthenticatedException; +import android.util.Pair; import android.widget.Toast; import androidx.annotation.RequiresApi; @@ -53,7 +54,6 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -66,6 +66,7 @@ import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; +import java.security.spec.AlgorithmParameterSpec; import java.util.Enumeration; import javax.crypto.Cipher; @@ -75,6 +76,7 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.IvParameterSpec; import timber.log.Timber; import wallet.core.jni.CoinType; @@ -87,12 +89,14 @@ public class KeyService implements AuthenticationCallback, PinAuthenticationCallbackInterface { private static final String TAG = "HDWallet"; - private static final String ANDROID_KEY_STORE = "AndroidKeyStore"; - private static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM; - private static final String PADDING = KeyProperties.ENCRYPTION_PADDING_NONE; - private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; private static final int AUTHENTICATION_DURATION_SECONDS = 30; public static final String FAILED_SIGNATURE = "00000000000000000000000000000000000000000000000000000000000000000"; + private static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM; + private static final String PADDING = KeyProperties.ENCRYPTION_PADDING_NONE; + + public static final String ANDROID_KEY_STORE = "AndroidKeyStore"; + public static final String LEGACY_CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding"; + public static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; //This value determines the time interval between the user swiping away the backup warning notice and it re-appearing public static final long TIME_BETWEEN_BACKUP_WARNING_MILLIS = 1000L * 60L * 60L * 24L * 30L; //30 days //1000 * 60 * 3; //3 minutes for testing @@ -510,6 +514,60 @@ private synchronized String unpackMnemonic() throws KeyServiceException, UserNot } } + public Pair testCipher(String walletAddress, String cipherAlgorithm) + { + KeyExceptionType retVal = KeyExceptionType.UNKNOWN; + String keyData = null; + try + { + String encryptedDataFilePath = KeyService.getFilePath(context, walletAddress); + String keyIv = KeyService.getFilePath(context, walletAddress + "iv"); + boolean ivExists = new File(keyIv).exists(); + boolean aliasExists = new File(encryptedDataFilePath).exists(); + + if (!ivExists) + { + retVal = KeyExceptionType.IV_NOT_FOUND; + throw new Exception("iv file doesn't exist"); + } + if (!aliasExists) + { + retVal = KeyExceptionType.ENCRYPTED_FILE_NOT_FOUND; + throw new Exception("Key file doesn't exist"); + } + + //test legacy key + byte[] iv = KeyService.readBytesFromFile(keyIv); + + KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE); + keyStore.load(null); + SecretKey secretKey = (SecretKey) keyStore.getKey(walletAddress, null); + + Cipher outCipher = Cipher.getInstance(cipherAlgorithm); + final AlgorithmParameterSpec spec = cipherAlgorithm.equals(CIPHER_ALGORITHM) ? new GCMParameterSpec(128, iv) : new IvParameterSpec(iv); + outCipher.init(Cipher.DECRYPT_MODE, secretKey, spec); + CipherInputStream cipherInputStream = new CipherInputStream(new FileInputStream(encryptedDataFilePath), outCipher); + byte[] keyBytes = KeyService.readBytesFromStream(cipherInputStream); + keyData = new String(keyBytes); + retVal = KeyExceptionType.SUCCESSFUL_DECODE; + } + catch (UserNotAuthenticatedException e) + { + retVal = KeyExceptionType.REQUIRES_AUTH; + } + catch (InvalidKeyException e) + { + //Wrong spec + retVal = KeyExceptionType.INVALID_CIPHER; + } + catch (Exception e) + { + // Other + } + + return new Pair<>(retVal, keyData); + } + private void createHDKey() { HDWallet newWallet = new HDWallet(DEFAULT_KEY_STRENGTH, ""); @@ -1100,14 +1158,12 @@ private synchronized SignatureFromKey signWithKeystore(byte[] transactionBytes) Utility methods */ - static byte[] readBytesFromFile(String path) + public static byte[] readBytesFromFile(String path) { byte[] bytes = null; - FileInputStream fin; - try + File file = new File(path); + try (FileInputStream fin = new FileInputStream(file)) { - File file = new File(path); - fin = new FileInputStream(file); bytes = readBytesFromStream(fin); } catch (IOException e) @@ -1117,6 +1173,22 @@ static byte[] readBytesFromFile(String path) return bytes; } + public static byte[] readBytesFromStream(InputStream in) throws IOException + { + ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); + int bufferSize = 2048; + byte[] buffer = new byte[bufferSize]; + + int len; + while ((len = in.read(buffer)) != -1) + { + byteBuffer.write(buffer, 0, len); + } + + byteBuffer.close(); + return byteBuffer.toByteArray(); + } + /** * Finds matching key in keystore regardless of case * @@ -1148,7 +1220,7 @@ private String findMatchingAddrInKeyStore(String keyAddress) return keyAddress; } - synchronized static String getFilePath(Context context, String fileName) + public synchronized static String getFilePath(Context context, String fileName) { //check for matching file File check = new File(context.getFilesDir(), fileName); @@ -1174,85 +1246,18 @@ synchronized static String getFilePath(Context context, String fileName) private boolean writeBytesToFile(String path, byte[] data) { - FileOutputStream fos = null; - try + File file = new File(path); + try (FileOutputStream fos = new FileOutputStream(file)) { - File file = new File(path); - fos = new FileOutputStream(file); - // Writes bytes from the specified byte array to this file output stream fos.write(data); - return true; - } - catch (FileNotFoundException e) - { - Timber.d("File not found" + e); - } - catch (IOException ioe) - { - Timber.d(ioe, "Exception while writing file "); - } - finally - { - // close the streams using close method - try - { - if (fos != null) - { - fos.close(); - } - } - catch (IOException ioe) - { - Timber.d("Error while closing stream: " + ioe); - } - } - return false; - } - - static byte[] readBytesFromStream(InputStream in) - { - // this dynamically extends to take the bytes you read - ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); - // this is storage overwritten on each iteration with bytes - int bufferSize = 1024; - byte[] buffer = new byte[bufferSize]; - // we need to know how may bytes were read to write them to the byteBuffer - int len; - try - { - while ((len = in.read(buffer)) != -1) - { - byteBuffer.write(buffer, 0, len); - } } catch (IOException e) { - e.printStackTrace(); - } - finally - { - try - { - byteBuffer.close(); - } - catch (IOException e) - { - e.printStackTrace(); - } - if (in != null) - { - try - { - in.close(); - } - catch (IOException e) - { - e.printStackTrace(); - } - } + Timber.d(e, "Exception while writing file "); + return false; } - // and then we can return your byte array. - return byteBuffer.toByteArray(); + + return true; } /** @@ -1388,4 +1393,31 @@ private void vibrate() } } } + + public boolean hasKeystore(String walletAddress) + { + try + { + KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE); + keyStore.load(null); + String matchingAddr = findMatchingAddrInKeyStore(walletAddress); + return keyStore.containsAlias(matchingAddr); + } + catch (KeyStoreException|NoSuchAlgorithmException|CertificateException|IOException e) + { + Timber.e(e); + } + + return false; + } + + static boolean hasStrongbox() + { + return securityStatus == SecurityStatus.HAS_STRONGBOX; + } + + public enum KeyExceptionType + { + UNKNOWN, REQUIRES_AUTH, INVALID_CIPHER, SUCCESSFUL_DECODE, IV_NOT_FOUND, ENCRYPTED_FILE_NOT_FOUND + } } diff --git a/app/src/main/java/com/alphawallet/app/service/KeystoreAccountService.java b/app/src/main/java/com/alphawallet/app/service/KeystoreAccountService.java index 1044355545..fa494e0af4 100644 --- a/app/src/main/java/com/alphawallet/app/service/KeystoreAccountService.java +++ b/app/src/main/java/com/alphawallet/app/service/KeystoreAccountService.java @@ -1,9 +1,9 @@ package com.alphawallet.app.service; +import static com.alphawallet.app.entity.CryptoFunctions.sigFromByteArray; + import android.text.TextUtils; -import android.util.Log; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; @@ -48,8 +48,6 @@ import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static com.alphawallet.app.entity.CryptoFunctions.sigFromByteArray; - public class KeystoreAccountService implements AccountKeystoreService { public static final String KEYSTORE_FOLDER = "keystore/keystore"; @@ -325,6 +323,25 @@ public static Credentials getCredentials(File keyFolder, String address, String return credentials; } + public static Credentials getCredentialsWithThrow(File keyFolder, String address, String password) throws Exception + { + Credentials credentials = null; + + address = Numeric.cleanHexPrefix(address); + File[] contents = keyFolder.listFiles(); + for (File f : contents) + { + if (f.getName().contains(address)) + { + credentials = WalletUtils.loadCredentials(password, f); + break; + } + } + + Timber.tag("RealmDebug").d("gotcredentials + %s", address); + return credentials; + } + @Override public Single signTransactionFast(Wallet signer, String signerPassword, byte[] message, long chainId) { return Single.fromCallable(() -> { diff --git a/app/src/main/java/com/alphawallet/app/service/LegacyKeystore.java b/app/src/main/java/com/alphawallet/app/service/LegacyKeystore.java index 44f51a3ae9..ea3c3d3c6d 100644 --- a/app/src/main/java/com/alphawallet/app/service/LegacyKeystore.java +++ b/app/src/main/java/com/alphawallet/app/service/LegacyKeystore.java @@ -1,30 +1,33 @@ package com.alphawallet.app.service; +import static com.alphawallet.app.entity.ServiceErrorException.ServiceErrorCode; +import static com.alphawallet.app.entity.ServiceErrorException.ServiceErrorCode.KEY_IS_GONE; + import android.content.Context; import android.security.keystore.UserNotAuthenticatedException; import com.alphawallet.app.R; import com.alphawallet.app.entity.ServiceErrorException; -import javax.crypto.Cipher; -import javax.crypto.CipherInputStream; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.security.*; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; -import static com.alphawallet.app.entity.ServiceErrorException.*; -import static com.alphawallet.app.entity.ServiceErrorException.ServiceErrorCode.KEY_IS_GONE; +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; public class LegacyKeystore { - private static final String LEGACY_CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding"; - private static final String ANDROID_KEY_STORE = "AndroidKeyStore"; - public static synchronized byte[] getLegacyPassword( final Context context, String keyName) @@ -34,7 +37,7 @@ public static synchronized byte[] getLegacyPassword( String encryptedDataFilePath = KeyService.getFilePath(context, keyName); try { - keyStore = KeyStore.getInstance(ANDROID_KEY_STORE); + keyStore = KeyStore.getInstance(KeyService.ANDROID_KEY_STORE); keyStore.load(null); SecretKey secretKey = (SecretKey) keyStore.getKey(keyName, null); if (secretKey == null) @@ -64,7 +67,7 @@ public static synchronized byte[] getLegacyPassword( { throw new NullPointerException(context.getString(R.string.cannot_read_encrypt_file)); } - Cipher outCipher = Cipher.getInstance(LEGACY_CIPHER_ALGORITHM); + Cipher outCipher = Cipher.getInstance(KeyService.LEGACY_CIPHER_ALGORITHM); outCipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv)); CipherInputStream cipherInputStream = new CipherInputStream(new FileInputStream(encryptedDataFilePath), outCipher); return KeyService.readBytesFromStream(cipherInputStream); diff --git a/app/src/main/java/com/alphawallet/app/ui/ImportSeedFragment.java b/app/src/main/java/com/alphawallet/app/ui/ImportSeedFragment.java index e88c59c334..8c9182b645 100644 --- a/app/src/main/java/com/alphawallet/app/ui/ImportSeedFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/ImportSeedFragment.java @@ -36,7 +36,8 @@ @AndroidEntryPoint public class ImportSeedFragment extends ImportFragment implements OnSuggestionClickListener { private static final OnImportSeedListener dummyOnImportSeedListener = (s, c) -> {}; - private static final String validator = "[^a-z^A-Z^ ]"; + + public static final String validator = "[^a-z^A-Z^ ]"; private PasswordInputView seedPhrase; private Button importButton; diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletActionsActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletActionsActivity.java index 972cebf510..17fa5680a5 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletActionsActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletActionsActivity.java @@ -10,6 +10,7 @@ import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; +import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; @@ -36,8 +37,6 @@ import com.alphawallet.app.widget.SettingsItemView; import com.alphawallet.app.widget.UserAvatar; -import javax.inject.Inject; - import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint @@ -105,6 +104,14 @@ private void initViewModel() { } } + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + getMenuInflater().inflate(R.menu.menu_wallet_manage, menu); + + return super.onCreateOptionsMenu(menu); + } + private void onTaskStatusChanged(Boolean isTaskRunning) { } @@ -123,6 +130,14 @@ public boolean onOptionsItemSelected(MenuItem item) onBackPressed(); return true; } + else if (item.getItemId() == R.id.action_key_status) + { + //show the key status + Intent intent = new Intent(this, WalletDiagnosticActivity.class); + intent.putExtra("wallet", wallet); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + startActivity(intent); + } return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletDiagnosticActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletDiagnosticActivity.java new file mode 100644 index 0000000000..511ee1c784 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/WalletDiagnosticActivity.java @@ -0,0 +1,477 @@ +package com.alphawallet.app.ui; + +import static com.alphawallet.app.service.KeystoreAccountService.KEYSTORE_FOLDER; +import static com.alphawallet.app.widget.AWalletAlertDialog.ERROR; +import static com.alphawallet.app.widget.AWalletAlertDialog.WARNING; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.util.Pair; +import android.view.MenuItem; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.AuthenticationCallback; +import com.alphawallet.app.entity.AuthenticationFailType; +import com.alphawallet.app.entity.Operation; +import com.alphawallet.app.entity.StandardFunctionInterface; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.WalletType; +import com.alphawallet.app.service.KeyService; +import com.alphawallet.app.service.KeystoreAccountService; +import com.alphawallet.app.viewmodel.BackupKeyViewModel; +import com.alphawallet.app.widget.AWalletAlertDialog; +import com.alphawallet.app.widget.FunctionButtonBar; +import com.alphawallet.app.widget.SignTransactionDialog; +import com.alphawallet.token.tools.Numeric; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.web3j.crypto.Credentials; +import org.web3j.crypto.ECKeyPair; +import org.web3j.crypto.WalletFile; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import dagger.hilt.android.AndroidEntryPoint; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; +import wallet.core.jni.CoinType; +import wallet.core.jni.HDWallet; +import wallet.core.jni.PrivateKey; + +/** + * Created by JB on 24/08/2022. + * + * NB: do not use any of this code anywhere else in the wallet! This is purely for key diagnostics to help support diagnose issues with keys + */ +@AndroidEntryPoint +public class WalletDiagnosticActivity extends BaseActivity implements StandardFunctionInterface +{ + private BackupKeyViewModel viewModel; + private AWalletAlertDialog dialog; + + private Wallet wallet; + + private boolean isLegacyKeystore = false; + private boolean isKeyStore = false; + private boolean isSeedPhrase = false; + private boolean isLocked = false; + + private final Handler handler = new Handler(Looper.getMainLooper()); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_wallet_diagnostic); + toolbar(); + setTitle(getString(R.string.key_diagnostic)); + + FunctionButtonBar functionBar = findViewById(R.id.layoutButtons); + functionBar.setupFunctions(this, new ArrayList<>(Collections.singletonList(R.string.run_key_diagnostic))); + functionBar.revealButtons(); + + if (getIntent() != null) + { + wallet = (Wallet) getIntent().getExtras().get("wallet"); + } + else + { + finish(); + } + + initViewModel(); + startKeyDiagnostic(); + } + + @Override + public void handleClick(String action, int actionId) + { + //test cipher + doUnlock(new UnlockCallback() + { + @Override + public void carryOn(boolean passed) + { + Pair res = viewModel.testCipher(wallet.address, KeyService.LEGACY_CIPHER_ALGORITHM); + switch (res.first) + { + case UNKNOWN: + case REQUIRES_AUTH: + showError("Unknown Failure"); + break; + case INVALID_CIPHER: + isLegacyKeystore = false; + break; + case SUCCESSFUL_DECODE: + isLegacyKeystore = true; + evaluateKey(); + break; + case IV_NOT_FOUND: + showError("IV File not found"); + return; + case ENCRYPTED_FILE_NOT_FOUND: + showError("Encrypted Data File not found"); + return; + } + + testKeyStore(); + } + }); + } + + private void startKeyDiagnostic() + { + LinearLayout successOverlay = findViewById(R.id.layout_success_overlay); + if (successOverlay != null) successOverlay.setVisibility(View.GONE); + + setCurrentKeyType(); + boolean hasKey = scanForKey(); + + if (hasKey) + { + unlockKeyIfRequired(); + } + else + { + showError("Unable to find enclave key for this wallet. Is it a watch wallet?"); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) + { + if (item.getItemId() == android.R.id.home) + { + onBackPressed(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this) + .get(BackupKeyViewModel.class); + } + + private boolean scanForKey() + { + TextView status = findViewById(R.id.key_in_enclave); + if (viewModel.hasKey(wallet.address)) + { + status.setText(R.string.key_found); + status.setTextColor(getColor(R.color.green)); + return true; + } + else + { + status.setText(R.string.key_not_found); + status.setTextColor(getColor(R.color.danger)); + return false; + } + } + + private void setCurrentKeyType() + { + TextView status = findViewById(R.id.key_type); + String walletType = wallet.type.toString(); + status.setText(walletType); + } + + private void unlockKeyIfRequired() + { + TextView lockedState = findViewById(R.id.key_is_locked); + //first test key to see if it's unlocked + if (!isLocked) + { + Pair res = viewModel.testCipher(wallet.address, KeyService.LEGACY_CIPHER_ALGORITHM); + + isLocked = (res.first == KeyService.KeyExceptionType.REQUIRES_AUTH); + lockedState.setText(isLocked ? "Locked" : "Unlocked"); + lockedState.setTextColor(isLocked ? getColor(R.color.green) : getColor(R.color.danger)); + } + } + + // Finally, test if key matches up with what's stored in the database + private void evaluateKey() + { + WalletType actualType = getActualKeyType(); + if (actualType == WalletType.NOT_DEFINED) return; + + switch (wallet.type) + { + case WATCH: + case NOT_DEFINED: + case TEXT_MARKER: + case LARGE_TITLE: + break; + case KEYSTORE: + if (!isKeyStore) + { + suggestCorrectWallet("Database says Keystore but tests show: " + actualType.toString(), actualType); + } + else + { + showSuccess(); + } + break; + case HDKEY: + if (!isSeedPhrase) + { + suggestCorrectWallet("Database says Seed Phrase but tests show: " + actualType.toString(), actualType); + } + else + { + showSuccess(); + } + break; + case KEYSTORE_LEGACY: + if (!isLegacyKeystore) + { + suggestCorrectWallet("Database says Keystore Legacy but tests show: " + actualType.toString(), actualType); + } + else + { + showSuccess(); + } + break; + } + } + + private WalletType getActualKeyType() + { + if (isLegacyKeystore) + { + return WalletType.KEYSTORE_LEGACY; + } + else if (isSeedPhrase) + { + return WalletType.HDKEY; + } + else if (isKeyStore) + { + return WalletType.KEYSTORE; + } + else + { + return WalletType.NOT_DEFINED; + } + } + + private void suggestCorrectWallet(String suggest, WalletType type) + { + if (dialog != null && dialog.isShowing()) dialog.dismiss(); + dialog = new AWalletAlertDialog(this); + dialog.setTitle(R.string.key_status); + dialog.setMessage("Database keytype mismatch. " + suggest); + dialog.setIcon(WARNING); + dialog.setButtonText(R.string.fix_key_state); + dialog.setButtonListener(v -> { + updateKeyState(type); + }); + dialog.setSecondaryButtonText(R.string.action_cancel); + dialog.setSecondaryButtonListener(v -> { + dialog.dismiss(); + }); + dialog.show(); + } + + private void updateKeyState(WalletType type) + { + wallet.type = type; + viewModel.storeWallet(wallet) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe(this::completeUpdate, error -> showError(error.getMessage())) + .isDisposed(); + } + + private void completeUpdate(Wallet wallet) + { + LinearLayout successOverlay = findViewById(R.id.layout_success_overlay); + if (successOverlay != null) successOverlay.setVisibility(View.VISIBLE); + //restart key scan + handler.postDelayed(this::startKeyDiagnostic, 1000); + } + + private void showSuccess() + { + final LinearLayout successOverlay = findViewById(R.id.layout_success_overlay); + if (successOverlay != null) successOverlay.setVisibility(View.VISIBLE); + //restart key scan + handler.postDelayed(() -> { + if (successOverlay != null) successOverlay.setVisibility(View.GONE); + }, 1000); + } + + //Now test if this is a v2 keystore + private void testKeyStore() + { + Pair res = viewModel.testCipher(wallet.address, KeyService.CIPHER_ALGORITHM); + switch (res.first) + { + case UNKNOWN: + case REQUIRES_AUTH: + showError("Unknown Failure"); + break; + case INVALID_CIPHER: + isKeyStore = false; + showError("Key Failure: Invalid Cipher"); + break; + case SUCCESSFUL_DECODE: + //may or may not be a keystore, could be a seed phrase + boolean testKey = testKeyType(res.second); + if (testKey) evaluateKey(); + break; + case IV_NOT_FOUND: + showError("IV File not found"); + return; + case ENCRYPTED_FILE_NOT_FOUND: + showError("Encrypted Data File not found"); + return; + } + } + + private boolean testKeyType(String keyData) + { + //could either be a seed phrase or a keystore + Pattern pattern = Pattern.compile(ImportSeedFragment.validator, Pattern.MULTILINE); + TextView status = findViewById(R.id.status_txt); + + //first check for seed phrase + final Matcher matcher = pattern.matcher(keyData); + if (!matcher.find()) + { + int wordCount = wordCount(keyData); + + if (wordCount == 12 || wordCount == 18 || wordCount == 24) + { + //is valid seed phrase + HDWallet newWallet = new HDWallet(keyData, ""); + PrivateKey pk = newWallet.getKeyForCoin(CoinType.ETHEREUM); + + status.setText(getString(R.string.seed_phrase_public_key, Numeric.toHexString(pk.getPublicKeySecp256k1(false).data()))); + status.setTextColor(getColor(R.color.green)); + isSeedPhrase = true; + return true; + } + } + + if (!isSeedPhrase) + { + //attempt to recover the key + File keyFolder = new File(getFilesDir(), KEYSTORE_FOLDER); + try + { + Credentials credentials = KeystoreAccountService.getCredentialsWithThrow(keyFolder, wallet.address, keyData); + + if (credentials == null) + { + showError("Unable to find Keystore File"); + } + else + { + status.setText(getString(R.string.keystore_public_key, credentials.getEcKeyPair().getPublicKey().toString(16))); + isKeyStore = true; + return true; + } + } + catch (Exception e) + { + showError("Keystore decode error: " + e.getMessage()); + } + } + + return false; + } + + private int wordCount(String value) + { + if (value == null || value.length() == 0) return 0; + String[] split = value.split("\\s+"); + return split.length; + } + + // DO NOT use this style of key authentication in any other code. It's here like this only for key diagnostics + // Always use the ActionSheet + implement ActionSheetCallback as per SendActivity, NFTAssetDetailActivity etc + private void doUnlock(UnlockCallback cb) + { + SignTransactionDialog unlockTx = new SignTransactionDialog(this); + unlockTx.getAuthentication(new AuthenticationCallback() + { + @Override + public void authenticatePass(Operation callbackId) + { + cb.carryOn(true); + } + + @Override + public void authenticateFail(String fail, AuthenticationFailType failType, Operation callbackId) + { + cb.carryOn(false); + } + + @Override + public void legacyAuthRequired(Operation callbackId, String dialogTitle, String desc) + { + // not interested + } + }, this, Operation.FETCH_MNEMONIC); + } + + //This function could be useful for future, in case this is needed + @SuppressWarnings("unused") + private String dumpKeystoreFromSeedPhrase(String seedPhrase, String keystorePassword) + { + HDWallet newWallet = new HDWallet(seedPhrase, ""); + PrivateKey pk = newWallet.getKeyForCoin(CoinType.ETHEREUM); + ECKeyPair keyPair = ECKeyPair.create(pk.data()); + + try + { + WalletFile wf = org.web3j.crypto.Wallet.createLight(keystorePassword, keyPair); + return objectMapper.writeValueAsString(wf); + } + catch (Exception e) + { + e.printStackTrace(); + } + + return ""; + } + + private void showError(String error) + { + TextView statusTxt = findViewById(R.id.status_txt); + statusTxt.setText(error); + statusTxt.setTextColor(getColor(R.color.danger)); + if (dialog != null && dialog.isShowing()) dialog.dismiss(); + dialog = new AWalletAlertDialog(this); + dialog.setTitle(R.string.title_dialog_error); + dialog.setMessage(error); + dialog.setIcon(ERROR); + dialog.setButtonText(R.string.button_ok); + dialog.setButtonListener(v -> { + dialog.dismiss(); + }); + dialog.show(); + } + + private interface UnlockCallback + { + default void carryOn(boolean passed) { }; + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/BackupKeyViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/BackupKeyViewModel.java index f88f656007..b5aa7569ed 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/BackupKeyViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/BackupKeyViewModel.java @@ -1,11 +1,12 @@ package com.alphawallet.app.viewmodel; import android.app.Activity; +import android.text.TextUtils; +import android.util.Pair; + import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import android.text.TextUtils; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.entity.CreateWalletCallbackInterface; import com.alphawallet.app.entity.ErrorEnvelope; @@ -171,5 +172,20 @@ public void failedAuthentication(Operation taskCode) { keyService.failedAuthentication(taskCode); } + + public boolean hasKey(String address) + { + return keyService.hasKeystore(address); + } + + public Single storeWallet(Wallet wallet) + { + return fetchWalletsInteract.storeWallet(wallet); + } + + public Pair testCipher(String walletAddress, String cipherAlgorithm) + { + return keyService.testCipher(walletAddress, cipherAlgorithm); + } } diff --git a/app/src/main/res/drawable/ic_key_status.xml b/app/src/main/res/drawable/ic_key_status.xml new file mode 100644 index 0000000000..1339fb3b8b --- /dev/null +++ b/app/src/main/res/drawable/ic_key_status.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_wallet_diagnostic.xml b/app/src/main/res/layout/activity_wallet_diagnostic.xml new file mode 100644 index 0000000000..b668d0b21a --- /dev/null +++ b/app/src/main/res/layout/activity_wallet_diagnostic.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_wallet_manage.xml b/app/src/main/res/menu/menu_wallet_manage.xml new file mode 100644 index 0000000000..90d225d8c8 --- /dev/null +++ b/app/src/main/res/menu/menu_wallet_manage.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index c7dca28e90..0327fa5267 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -932,4 +932,15 @@ Provider Delete Empty Delete All + Key Status + Fix Key State + Run Key Diagnostic + Key Diagnostic + Key found + Unable to find Key + Seed Phrase detected public key: %1$s + Decoded Keystore public key: %1$s + Locked + Key type in Database + Key Entry in Secure Enclave diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 54aa90901b..4210ddc32c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -949,4 +949,15 @@ Provider Delete Empty Delete All + Key Status + Fix Key State + Run Key Diagnostic + Key Diagnostic + Key found + Unable to find Key + Seed Phrase detected public key: %1$s + Decoded Keystore public key: %1$s + Locked + Key type in Database + Key Entry in Secure Enclave diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index ecab2907a9..40a1fd8dfc 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -974,4 +974,15 @@ Provider Delete Empty Delete All + Key Status + Fix Key State + Run Key Diagnostic + Key Diagnostic + Key found + Unable to find Key + Seed Phrase detected public key: %1$s + Decoded Keystore public key: %1$s + Locked + Key type in Database + Key Entry in Secure Enclave diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 636c373c15..c6b78246a2 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -951,4 +951,15 @@ Provider Delete Empty Delete All + Key Status + Fix Key State + Run Key Diagnostic + Key Diagnostic + Key found + Unable to find Key + Seed Phrase detected public key: %1$s + Decoded Keystore public key: %1$s + Locked + Key type in Database + Key Entry in Secure Enclave diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 37d428ad5a..5199c6dec6 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -932,4 +932,15 @@ Provider Delete Empty Delete All + Key Status + Fix Key State + Run Key Diagnostic + Key Diagnostic + Key found + Unable to find Key + Seed Phrase detected public key: %1$s + Decoded Keystore public key: %1$s + Locked + Key type in Database + Key Entry in Secure Enclave diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 468ecff621..452ad3de51 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -973,4 +973,15 @@ Provider Delete Empty Delete All + Key Status + Fix Key State + Run Key Diagnostic + Key Diagnostic + Key found + Unable to find Key + Seed Phrase detected public key: %1$s + Decoded Keystore public key: %1$s + Locked + Key type in Database + Key Entry in Secure Enclave From 29f9ba8e52f961aca32cbeecd26930757efc4059 Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 30 Aug 2022 20:48:15 +1000 Subject: [PATCH 076/183] Upgrade Function Decoder (#2791) * Upgrade function decoder * Refactor unit test Co-authored-by: Seaborn Lee --- .../alphawallet/app/entity/FunctionData.java | 8 +- .../app/entity/TransactionDecoder.java | 69 +- .../app/entity/TransactionInput.java | 52 +- .../app/widget/TransactionDetailWidget.java | 2 +- .../app/TransactionDecodingTest.java | 1810 +++++++++-------- .../transaction-decoding-baseline.txt | 834 ++++++++ 6 files changed, 1847 insertions(+), 928 deletions(-) create mode 100644 app/src/test/resources/transaction-decoding-baseline.txt diff --git a/app/src/main/java/com/alphawallet/app/entity/FunctionData.java b/app/src/main/java/com/alphawallet/app/entity/FunctionData.java index a042435363..d82f6bed9d 100644 --- a/app/src/main/java/com/alphawallet/app/entity/FunctionData.java +++ b/app/src/main/java/com/alphawallet/app/entity/FunctionData.java @@ -1,14 +1,14 @@ package com.alphawallet.app.entity; -import com.alphawallet.app.C; -import com.alphawallet.app.widget.FunctionButtonBar; +import static com.alphawallet.app.entity.ContractType.CREATION; +import static com.alphawallet.app.entity.ContractType.ERC20; +import static com.alphawallet.app.entity.ContractType.ERC875; +import static com.alphawallet.app.entity.ContractType.ERC875_LEGACY; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static com.alphawallet.app.entity.ContractType.*; - /** * Created by James on 2/02/2018. */ diff --git a/app/src/main/java/com/alphawallet/app/entity/TransactionDecoder.java b/app/src/main/java/com/alphawallet/app/entity/TransactionDecoder.java index 53bae51983..2a22edb640 100644 --- a/app/src/main/java/com/alphawallet/app/entity/TransactionDecoder.java +++ b/app/src/main/java/com/alphawallet/app/entity/TransactionDecoder.java @@ -1,6 +1,8 @@ package com.alphawallet.app.entity; -import com.alphawallet.app.BuildConfig; +import static com.alphawallet.app.entity.TransactionDecoder.ReadState.ARGS; +import static org.web3j.crypto.Keys.ADDRESS_LENGTH_IN_HEX; + import com.alphawallet.app.web3.entity.Web3Transaction; import org.web3j.crypto.Hash; @@ -13,9 +15,6 @@ import java.util.List; import java.util.Map; -import static com.alphawallet.app.entity.TransactionDecoder.ReadState.ARGS; -import static org.web3j.crypto.Keys.ADDRESS_LENGTH_IN_HEX; - import timber.log.Timber; /** @@ -29,7 +28,6 @@ * input. */ -// TODO: Should be a factory class that emits an object containing transaction interpretation public class TransactionDecoder { public static final int FUNCTION_LENGTH = 10; @@ -43,7 +41,7 @@ public class TransactionDecoder private FunctionData getUnknownFunction() { - return new FunctionData("N/A", ContractType.OTHER); + return new FunctionData("Contract Call", ContractType.OTHER); } public TransactionDecoder() @@ -63,9 +61,12 @@ public TransactionInput decodeInput(String input) return thisData; } - try { - while (parseIndex < input.length() && !(parseState == ParseStage.FINISH)) { - switch (parseState) { + try + { + while (parseIndex < input.length() && !(parseState == ParseStage.FINISH)) + { + switch (parseState) + { case PARSE_FUNCTION: //get function parseState = setFunction(thisData, readBytes(input, FUNCTION_LENGTH), input.length()); break; @@ -107,7 +108,8 @@ public TransactionInput decodeInput(Web3Transaction web3Tx, long chainId, String return thisData; } - private ParseStage setFunction(TransactionInput thisData, String input, int length) { + private ParseStage setFunction(TransactionInput thisData, String input, int length) + { //first get expected arg list: FunctionData data = functionList.get(input); @@ -136,7 +138,8 @@ enum ReadState SIGNATURE } - private ParseStage getParams(TransactionInput thisData, String input) { + private ParseStage getParams(TransactionInput thisData, String input) + { state = ARGS; BigInteger count; StringBuilder sb = new StringBuilder(); @@ -152,26 +155,33 @@ private ParseStage getParams(TransactionInput thisData, String input) { sb.setLength(0); argData = read256bits(input); BigInteger dataCount = Numeric.toBigInt(argData); - String stuff = readBytes(input, dataCount.intValue()); - thisData.miscData.add(stuff); + String hexBytes = readBytes(input, dataCount.intValue()); + thisData.miscData.add(hexBytes); + thisData.hexArgs.add("0x" + hexBytes); break; case "string": count = new BigInteger(argData, 16); sb.setLength(0); argData = read256bits(input); - if (count.intValue() > argData.length()) count = BigInteger.valueOf(argData.length()); - for (int index = 0; index < (count.intValue()*2); index += 2) + if (count.intValue() > argData.length()) + count = BigInteger.valueOf(argData.length()); + for (int index = 0; index < (count.intValue() * 2); index += 2) { - int v = Integer.parseInt(argData.substring(index, index+2), 16); - char c = (char)v; + int v = Integer.parseInt(argData.substring(index, index + 2), 16); + char c = (char) v; sb.append(c); } thisData.miscData.add(Numeric.cleanHexPrefix(sb.toString())); + + //Should be ASCII, try to convert + thisData.hexArgs.add(new String(Numeric.hexStringToByteArray(sb.toString()))); break; case "address": if (argData.length() >= 64 - ADDRESS_LENGTH_IN_HEX) { - thisData.addresses.add("0x" + argData.substring(64 - ADDRESS_LENGTH_IN_HEX)); + String addr = "0x" + argData.substring(64 - ADDRESS_LENGTH_IN_HEX); + thisData.addresses.add(addr); + thisData.hexArgs.add(addr); } break; case "bytes32": @@ -181,17 +191,21 @@ private ParseStage getParams(TransactionInput thisData, String input) { case "uint16[]": case "uint256[]": count = new BigInteger(argData, 16); - for (int i = 0; i < count.intValue(); i++) { + for (int i = 0; i < count.intValue(); i++) + { String inputData = read256bits(input); thisData.arrayValues.add(new BigInteger(inputData, 16)); + thisData.hexArgs.add(inputData); if (inputData.equals("0")) break; } break; case "uint256": + case "uint": addArg(thisData, argData); break; case "uint8": //In our standards, we will put uint8 as the signature marker - if (thisData.functionData.hasSig) { + if (thisData.functionData.hasSig) + { state = ReadState.SIGNATURE; sigCount = 0; } @@ -200,6 +214,11 @@ private ParseStage getParams(TransactionInput thisData, String input) { case "nodata": //no need to store this data - eg placeholder to indicate presence of a vararg break; + case "bool": + //zero or one? + BigInteger val = new BigInteger(argData, 16); + thisData.hexArgs.add(val.longValue() == 0 ? "false" : "true"); + break; default: break; } @@ -225,13 +244,14 @@ private void addArg(TransactionInput thisData, String input) if (++sigCount == 3) state = ARGS; break; } + thisData.hexArgs.add(input); } private String readBytes(String input, int bytes) { if ((parseIndex + bytes) <= input.length()) { - String value = input.substring(parseIndex, parseIndex+bytes); + String value = input.substring(parseIndex, parseIndex + bytes); parseIndex += bytes; return value; } @@ -245,7 +265,7 @@ private String read256bits(String input) { if ((parseIndex + 64) <= input.length()) { - String value = input.substring(parseIndex, parseIndex+64); + String value = input.substring(parseIndex, parseIndex + 64); parseIndex += 64; return value; } @@ -452,7 +472,7 @@ public int[] getIndices(TransactionInput data) if (data != null && data.arrayValues != null) { indices = new int[data.arrayValues.size()]; - for (int i = 0; i < data.arrayValues.size() ; i++) + for (int i = 0; i < data.arrayValues.size(); i++) { indices[i] = data.arrayValues.get(i).intValue(); } @@ -461,7 +481,8 @@ public int[] getIndices(TransactionInput data) return indices; } - public static String buildMethodId(String methodSignature) { + public static String buildMethodId(String methodSignature) + { byte[] input = methodSignature.getBytes(); byte[] hash = Hash.sha3(input); return Numeric.toHexString(hash).substring(0, 10); diff --git a/app/src/main/java/com/alphawallet/app/entity/TransactionInput.java b/app/src/main/java/com/alphawallet/app/entity/TransactionInput.java index 69eee3cdf3..03ecb925e3 100644 --- a/app/src/main/java/com/alphawallet/app/entity/TransactionInput.java +++ b/app/src/main/java/com/alphawallet/app/entity/TransactionInput.java @@ -1,5 +1,9 @@ package com.alphawallet.app.entity; +import static com.alphawallet.app.C.BURN_ADDRESS; +import static com.alphawallet.app.C.ETHER_DECIMALS; +import static com.alphawallet.app.ui.widget.holder.TransactionHolder.TRANSACTION_BALANCE_PRECISION; + import android.content.Context; import android.text.TextUtils; @@ -23,11 +27,6 @@ import java.util.ArrayList; import java.util.List; -import static com.alphawallet.app.C.BURN_ADDRESS; -import static com.alphawallet.app.C.ETHER_DECIMALS; -import static com.alphawallet.app.entity.tokenscript.TokenscriptFunction.ZERO_ADDRESS; -import static com.alphawallet.app.ui.widget.holder.TransactionHolder.TRANSACTION_BALANCE_PRECISION; - /** * Created by James on 4/03/2018. * @@ -47,6 +46,7 @@ public class TransactionInput public List arrayValues; public List sigData; public List miscData; + public List hexArgs; public String tradeAddress; public TransactionType type; @@ -59,6 +59,7 @@ public TransactionInput() addresses = new ArrayList<>(); sigData = new ArrayList<>(); miscData = new ArrayList<>(); + hexArgs = new ArrayList<>(); } //Addresses are in 256bit format @@ -815,4 +816,45 @@ public boolean isSendOrReceive(Transaction tx) return !tx.value.equals("0"); } } + + public String buildFunctionCallText() + { + StringBuilder sb = new StringBuilder(); + sb.append(functionData.functionName); + sb.append("("); + boolean firstArg = true; + for (String arg : hexArgs) + { + if (!firstArg) sb.append(", "); + if (arg.startsWith("0")) + { + sb.append(truncateValue(arg)); + } + else + { + sb.append(arg); + } + firstArg = false; + } + + sb.append(")"); + + return sb.toString(); + } + + private String truncateValue(String arg) + { + String retVal = arg; + try + { + BigInteger argVal = new BigInteger(arg, 16); + retVal = argVal.toString(16); + } + catch (Exception e) + { + // + } + + return retVal; + } } diff --git a/app/src/main/java/com/alphawallet/app/widget/TransactionDetailWidget.java b/app/src/main/java/com/alphawallet/app/widget/TransactionDetailWidget.java index c1fa06df23..6def42d43b 100644 --- a/app/src/main/java/com/alphawallet/app/widget/TransactionDetailWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/TransactionDetailWidget.java @@ -55,7 +55,7 @@ public void setupTransaction(Web3Transaction w3tx, long chainId, String walletAd else { TransactionInput transactionInput = Transaction.decoder.decodeInput(w3tx, chainId, walletAddress); - textTransactionSummary.setText(transactionInput.getOperationTitle(getContext())); + textTransactionSummary.setText(transactionInput.buildFunctionCallText()); } layoutHolder.setOnClickListener(v -> { diff --git a/app/src/test/java/com/alphawallet/app/TransactionDecodingTest.java b/app/src/test/java/com/alphawallet/app/TransactionDecodingTest.java index 7b9e6673a5..611b7d97fe 100644 --- a/app/src/test/java/com/alphawallet/app/TransactionDecodingTest.java +++ b/app/src/test/java/com/alphawallet/app/TransactionDecodingTest.java @@ -1,924 +1,946 @@ package com.alphawallet.app; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertEquals; + +import androidx.annotation.NonNull; + import com.alphawallet.app.entity.TransactionDecoder; import com.alphawallet.app.entity.TransactionInput; -import static org.junit.Assert.assertEquals; +import com.alphawallet.app.entity.TransactionType; +import com.google.common.io.Resources; + import org.junit.Test; + +import java.io.IOException; import java.math.BigInteger; +import java.net.URL; +import java.nio.charset.StandardCharsets; /** * Created by weiwu on 7/3/18. */ -public class TransactionDecodingTest { +public class TransactionDecodingTest +{ - String transfer_transaction = "0xa6fb475f000000000000000000000000951c19daead668bfa8391c94286f8ce7cbda2fe3000000000000000000000000879230570f360424bc5baa99906d5f640a75551e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004"; - /* James has the following test transaction input without signature. */ - // String transaction_from_james_2 = "0 000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"; - String trade_transaction = "0x696ecc55" + //trade(uint,[],v,r,s) - "000000000000000000000000000000000000000000000000000000005a9a00e2" + // expiry - "00000000000000000000000000000000000000000000000000000000000000a0" + // var args declaration - "000000000000000000000000000000000000000000000000000000000000001b" + // 27: v - "c59d6718734043600a49ec2419e566fa03676058e88326ff1161c579c6b8e799" + // R - "51d22461ab6f27bedd72d6b56c1fecf9f4cbb79a7728c510022617a9e42782ea" + // S - "000000000000000000000000000000000000000000000000000000000000000a" + - "0000000000000000000000000000000000000000000000000000000000000009" + - "000000000000000000000000000000000000000000000000000000000000000a" + - "000000000000000000000000000000000000000000000000000000000000000b" + - "000000000000000000000000000000000000000000000000000000000000000c" + - "000000000000000000000000000000000000000000000000000000000000000d" + - "000000000000000000000000000000000000000000000000000000000000000e" + - "000000000000000000000000000000000000000000000000000000000000000f" + - "0000000000000000000000000000000000000000000000000000000000000010" + - "0000000000000000000000000000000000000000000000000000000000000011" + - "0000000000000000000000000000000000000000000000000000000000000012"; + @Test + public void testDecodeTransferTransaction() + { + String input = "0xa6fb475f000000000000000000000000951c19daead668bfa8391c94286f8ce7cbda2fe3000000000000000000000000879230570f360424bc5baa99906d5f640a75551e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004"; + TransactionInput transactionInput = new TransactionDecoder().decodeInput(input); + assertThat(transactionInput.getFirstAddress(), equalTo("0x951c19daead668bfa8391c94286f8ce7cbda2fe3")); + assertThat(transactionInput.getDestinationAddress(), equalTo("0x879230570f360424bc5baa99906d5f640a75551e")); + assertThat(transactionInput.getRawValue().doubleValue(), equalTo(4.0)); + } @Test - public void TransactionInputCanBeDecoded() { - TransactionInput i; - TransactionDecoder t = new TransactionDecoder(); - i = t.decodeInput(transfer_transaction); - assertEquals("0x951c19daead668bfa8391c94286f8ce7cbda2fe3", i.getFirstAddress()); - i = t.decodeInput(trade_transaction); - assertEquals(BigInteger.valueOf(0x1b), new BigInteger(i.sigData.get(0), 16)); + public void testDecodeTradeTransaction() + { + TransactionInput transactionInput = new TransactionDecoder().decodeInput("0x696ecc55" + //trade(uint,[],v,r,s) + "000000000000000000000000000000000000000000000000000000005a9a00e2" + // expiry + "00000000000000000000000000000000000000000000000000000000000000a0" + // var args declaration + "000000000000000000000000000000000000000000000000000000000000001b" + // 27: v + "c59d6718734043600a49ec2419e566fa03676058e88326ff1161c579c6b8e799" + // R + "51d22461ab6f27bedd72d6b56c1fecf9f4cbb79a7728c510022617a9e42782ea" + // S + "000000000000000000000000000000000000000000000000000000000000000a" + + "0000000000000000000000000000000000000000000000000000000000000009" + + "000000000000000000000000000000000000000000000000000000000000000a" + + "000000000000000000000000000000000000000000000000000000000000000b" + + "000000000000000000000000000000000000000000000000000000000000000c" + + "000000000000000000000000000000000000000000000000000000000000000d" + + "000000000000000000000000000000000000000000000000000000000000000e" + + "000000000000000000000000000000000000000000000000000000000000000f" + + "0000000000000000000000000000000000000000000000000000000000000010" + + "0000000000000000000000000000000000000000000000000000000000000011" + + "0000000000000000000000000000000000000000000000000000000000000012"); + assertThat(transactionInput.type, equalTo(TransactionType.MAGICLINK_TRANSFER)); + assertEquals(BigInteger.valueOf(0x1b), new BigInteger(transactionInput.sigData.get(0), 16)); + assertThat(transactionInput.sigData.get(1), equalTo("c59d6718734043600a49ec2419e566fa03676058e88326ff1161c579c6b8e799")); + assertThat(transactionInput.sigData.get(2), equalTo("51d22461ab6f27bedd72d6b56c1fecf9f4cbb79a7728c510022617a9e42782ea")); } /** * Transaction soak test - checks through a lot of inputs */ @Test - public void TransactionTest() { - TransactionInput i; - try { - TransactionDecoder t = new TransactionDecoder(); - for (String testInput : inputTestList) { - i = t.decodeInput(testInput); - if (i != null && i.functionData != null) { - switch (i.functionData.functionName) { - case "trade": - assertEquals(3, i.sigData.size()); - assertEquals(0, i.addresses.size()); - break; - case "transferFrom": - assertEquals(2, i.addresses.size()); - assertEquals(0, i.sigData.size()); - break; - case "transfer": - assertEquals(1, i.addresses.size()); - assertEquals(0, i.sigData.size()); - break; - case "Contract Creation": - assertEquals(0, i.addresses.size()); - assertEquals(0, i.sigData.size()); - break; - default: - break; - } + public void testBuildFunctionCallText() throws IOException + { + StringBuilder stringBuilder = new StringBuilder(); + for (String testInput : inputTestList) + { + TransactionInput transactionInput = new TransactionDecoder().decodeInput(testInput); + if (transactionInput.functionData != null) + { + switch (transactionInput.functionData.functionName) + { + case "trade": + assertEquals(3, transactionInput.sigData.size()); + assertEquals(0, transactionInput.addresses.size()); + break; + case "transferFrom": + assertEquals(2, transactionInput.addresses.size()); + assertEquals(0, transactionInput.sigData.size()); + break; + case "transfer": + assertEquals(1, transactionInput.addresses.size()); + assertEquals(0, transactionInput.sigData.size()); + break; + case "Contract Creation": + assertEquals(0, transactionInput.addresses.size()); + assertEquals(0, transactionInput.sigData.size()); + break; + default: + break; } + stringBuilder.append(transactionInput.buildFunctionCallText()).append("\n"); } - } catch (Exception e) { - e.printStackTrace(); - assertEquals("fail", "test fails"); - return; } + assertThat(stringBuilder.toString(), equalTo(getBaseline())); } - + @NonNull + private String getBaseline() throws IOException + { + URL url = Resources.getResource("transaction-decoding-baseline.txt"); + return Resources.toString(url, StandardCharsets.UTF_8); + } String[] inputTestList = {"0x696ecc55000000000000000000000000000000000000000000000000000000005aab55ba00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b3b001a70e389356e7bb9dcf89ae132771fbebb0aadc84d2da54083a9f84a52c379d0ba25d819da836204269eb742e777fe27e3364220bc07bb7ebb8f3b55260a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000024" - ,"0xdb0ec968000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b9" - ,"0xa9059cbb000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000de0b6b3a7640000" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001c" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000e" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" - ,"0xa6fb475f000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0xdb0ec968000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000d2" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001bf9cadbff0499fbd2afb4c25289c8fc17518bd22060526b619d4645fcc4c94c5357dcccf6e3e9f20533b6343e7d0e88fa37e9e23790e0ecbc57b4b85a3b421d1f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d" - ,"0xa6fb475f000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e" - ,"0xa6fb475f000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000d6" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000bf" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000bf" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xdb0ec968000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x" - ,"0x" - ,"0x" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060065534156200003357600080fd5b60405162001a3a38038062001a3a83398101604052808051820191906020018051820191906020018051906020019091908051820191905050835160008190555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000c9929190620001aa565b508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600890805190602001906200016b9291906200025b565b508260079080519060200190620001849291906200025b565b506001600960006101000a81548160ff021916908315150217905550505050506200033e565b82805482825590600052602060002090600f01601090048101928215620002485791602002820160005b838211156200021657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001d4565b8015620002465782816101000a81549061ffff021916905560020160208160010104928301926001030262000216565b505b509050620002579190620002e2565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200029e57805160ff1916838001178555620002cf565b82800160010185558215620002cf579182015b82811115620002ce578251825591602001919060010190620002b1565b5b509050620002de919062000316565b5090565b6200031391905b808211156200030f57600081816101000a81549061ffff021916905550600101620002e9565b5090565b90565b6200033b91905b80821115620003375760008160009055506001016200031d565b5090565b90565b6116ec806200034e6000396000f3006060604052600436106100e6576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100f657806318160ddd14610184578063313ce567146101ad57806332a2c5d0146101dc5780634f452b9a1461023157806358089fc61461025e578063696ecc551461028b57806370a082311461030957806372c5cb631461039757806395d89b41146103c0578063a6fb475f1461044e578063bb6e7de9146104e6578063c2532c3d146104fb578063db0ec9681461059a578063ea8b5ca314610613578063f0141d8414610640575b34156100f157600080fd5b600080fd5b341561010157600080fd5b610109610669565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014957808201518184015260208101905061012e565b50505050905090810190601f1680156101765780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018f57600080fd5b610197610711565b6040518082815260200191505060405180910390f35b34156101b857600080fd5b6101c061071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101e757600080fd5b6101ef61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023c57600080fd5b610244610727565b604051808215151515815260200191505060405180910390f35b341561026957600080fd5b61027161073e565b604051808215151515815260200191505060405180910390f35b61030760048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610751565b005b341561031457600080fd5b610340600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a7e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610383578082015181840152602081019050610368565b505050509050019250505060405180910390f35b34156103a257600080fd5b6103aa610b43565b6040518082815260200191505060405180910390f35b34156103cb57600080fd5b6103d3610b4d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104135780820151818401526020810190506103f8565b50505050905090810190601f1680156104405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561045957600080fd5b6104e4600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bf5565b005b34156104f157600080fd5b6104f9610e7e565b005b341561050657600080fd5b61059860048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f14565b005b34156105a557600080fd5b610611600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506110eb565b005b341561061e57600080fd5b6106266112d2565b604051808215151515815260200191505060405180910390f35b341561064b57600080fd5b6106536112ef565b6040518082815260200191505060405180910390f35b610671611625565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107075780601f106106dc57610100808354040283529160200191610707565b820191906000526020600020905b8154815290600101906020018083116106ea57829003601f168201915b5050505050905090565b60008054905090565b600081565b600030905090565b6000600960009054906101000a900460ff16905090565b600960009054906101000a900460ff1681565b600080600080428911806107655750600089145b151561077057600080fd5b61077b348a8a6112fa565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107fb57600080fd5b5050602060405103519250600091505b8751821015610a3357878281518110151561082257fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561088057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161115156108b457600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816109059190611639565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561096857fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109f757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff160217905550818060010192505061080b565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a7357600080fd5b505050505050505050565b610a86611673565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b3757602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610afe5790505b50505050509050919050565b6000600654905090565b610b55611625565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610beb5780601f10610bc057610100808354040283529160200191610beb565b820191906000526020600020905b815481529060010190602001808311610bce57829003601f168201915b5050505050905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c5357600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ca357600080fd5b600090505b8151811015610e7857600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d029190611639565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610d6657fe5b9060200190602002015161ffff16815481101515610d8057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610e1057fe5b9060200190602002015161ffff16815481101515610e2a57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506006600081548092919060010191905055508080600101915050610ca8565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f0f57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f256000808a6112fa565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610fc257600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561102957600080fd5b600090505b87518110156110e157600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110889190611639565b91600052602060002090601091828204019190066002028a848151811015156110ad57fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061102e565b5050505050505050565b60008090505b81518161ffff1610156112cd57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161114f9190611639565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff168151811015156111b757fe5b9060200190602002015161ffff168154811015156111d157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561126557fe5b9060200190602002015161ffff1681548110151561127f57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060066000815480929190600101919050555080806001019150506110f1565b505050565b60006003544211156112e757600190506112ec565b600090505b90565b60008060ff16905090565b6000611304611687565b600080600285510260540160405180591061131c5750595b9080825280601f01601f1916602001820160405250925061133b61071f565b9150600090505b60208110156113a35780600802879060020a02600102838281518110151561136657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611342565b600090505b602081101561140c5780600802869060020a0260010283602083018151811015156113cf57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506113a8565b600090505b60148110156114905780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561145357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611411565b600090505b84518110156115b657600885828151811015156114ae57fe5b9060200190602002015161ffff169060020a90047f01000000000000000000000000000000000000000000000000000000000000000283600283026054018151811015156114f857fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561153657fe5b906020019060200201517f010000000000000000000000000000000000000000000000000000000000000002836001600284026054010181518110151561157957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611495565b826040518082805190602001908083835b6020831015156115ec57805182526020820191506020810190506020830392506115c7565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b81548183558181151161166e57600f016010900481600f0160109004836000526020600020918201910161166d919061169b565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b6116bd91905b808211156116b95760008160009055506001016116a1565b5090565b905600a165627a7a723058201e8c8b879a2027fbce1df4eec16e8d9a2f206c5e7be2868a1878154ebf6e277a002900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000001c4000000000000000000000000000000000000000000000000000000000000000db0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000105000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000001070000000000000000000000000000000000000000000000000000000000000108000000000000000000000000000000000000000000000000000000000000010900000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000000010030000000000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000000000000000000000000000100500000000000000000000000000000000000000000000000000000000000010060000000000000000000000000000000000000000000000000000000000001007000000000000000000000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000010090000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000108100000000000000000000000000000000000000000000000000000000000010820000000000000000000000000000000000000000000000000000000000001083000000000000000000000000000000000000000000000000000000000000108400000000000000000000000000000000000000000000000000000000000010850000000000000000000000000000000000000000000000000000000000001086000000000000000000000000000000000000000000000000000000000000108700000000000000000000000000000000000000000000000000000000000010880000000000000000000000000000000000000000000000000000000000001089000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000011010000000000000000000000000000000000000000000000000000000000001102000000000000000000000000000000000000000000000000000000000000110300000000000000000000000000000000000000000000000000000000000011040000000000000000000000000000000000000000000000000000000000001105000000000000000000000000000000000000000000000000000000000000110600000000000000000000000000000000000000000000000000000000000011070000000000000000000000000000000000000000000000000000000000001108000000000000000000000000000000000000000000000000000000000000110900000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000000000000000000000000000000000000000000200200000000000000000000000000000000000000000000000000000000000020030000000000000000000000000000000000000000000000000000000000002004000000000000000000000000000000000000000000000000000000000000200500000000000000000000000000000000000000000000000000000000000020060000000000000000000000000000000000000000000000000000000000002007000000000000000000000000000000000000000000000000000000000000200800000000000000000000000000000000000000000000000000000000000020090000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000208100000000000000000000000000000000000000000000000000000000000020820000000000000000000000000000000000000000000000000000000000002083000000000000000000000000000000000000000000000000000000000000208400000000000000000000000000000000000000000000000000000000000020850000000000000000000000000000000000000000000000000000000000002086000000000000000000000000000000000000000000000000000000000000208700000000000000000000000000000000000000000000000000000000000020880000000000000000000000000000000000000000000000000000000000002089000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021010000000000000000000000000000000000000000000000000000000000002102000000000000000000000000000000000000000000000000000000000000210300000000000000000000000000000000000000000000000000000000000021040000000000000000000000000000000000000000000000000000000000002105000000000000000000000000000000000000000000000000000000000000210600000000000000000000000000000000000000000000000000000000000021070000000000000000000000000000000000000000000000000000000000002108000000000000000000000000000000000000000000000000000000000000210900000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003001000000000000000000000000000000000000000000000000000000000000300200000000000000000000000000000000000000000000000000000000000030030000000000000000000000000000000000000000000000000000000000003004000000000000000000000000000000000000000000000000000000000000300500000000000000000000000000000000000000000000000000000000000030060000000000000000000000000000000000000000000000000000000000003007000000000000000000000000000000000000000000000000000000000000300800000000000000000000000000000000000000000000000000000000000030090000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000308100000000000000000000000000000000000000000000000000000000000030820000000000000000000000000000000000000000000000000000000000003083000000000000000000000000000000000000000000000000000000000000308400000000000000000000000000000000000000000000000000000000000030850000000000000000000000000000000000000000000000000000000000003086000000000000000000000000000000000000000000000000000000000000308700000000000000000000000000000000000000000000000000000000000030880000000000000000000000000000000000000000000000000000000000003089000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031010000000000000000000000000000000000000000000000000000000000003102000000000000000000000000000000000000000000000000000000000000310300000000000000000000000000000000000000000000000000000000000031040000000000000000000000000000000000000000000000000000000000003105000000000000000000000000000000000000000000000000000000000000310600000000000000000000000000000000000000000000000000000000000031070000000000000000000000000000000000000000000000000000000000003108000000000000000000000000000000000000000000000000000000000000310900000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004001000000000000000000000000000000000000000000000000000000000000400200000000000000000000000000000000000000000000000000000000000040030000000000000000000000000000000000000000000000000000000000004004000000000000000000000000000000000000000000000000000000000000400500000000000000000000000000000000000000000000000000000000000040060000000000000000000000000000000000000000000000000000000000004007000000000000000000000000000000000000000000000000000000000000400800000000000000000000000000000000000000000000000000000000000040090000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000408100000000000000000000000000000000000000000000000000000000000040820000000000000000000000000000000000000000000000000000000000004083000000000000000000000000000000000000000000000000000000000000408400000000000000000000000000000000000000000000000000000000000040850000000000000000000000000000000000000000000000000000000000004086000000000000000000000000000000000000000000000000000000000000408700000000000000000000000000000000000000000000000000000000000040880000000000000000000000000000000000000000000000000000000000004089000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004102000000000000000000000000000000000000000000000000000000000000410300000000000000000000000000000000000000000000000000000000000041040000000000000000000000000000000000000000000000000000000000004105000000000000000000000000000000000000000000000000000000000000410600000000000000000000000000000000000000000000000000000000000041070000000000000000000000000000000000000000000000000000000000004108000000000000000000000000000000000000000000000000000000000000410900000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005001000000000000000000000000000000000000000000000000000000000000500200000000000000000000000000000000000000000000000000000000000050030000000000000000000000000000000000000000000000000000000000005004000000000000000000000000000000000000000000000000000000000000500500000000000000000000000000000000000000000000000000000000000050060000000000000000000000000000000000000000000000000000000000005007000000000000000000000000000000000000000000000000000000000000500800000000000000000000000000000000000000000000000000000000000050090000000000000000000000000000000000000000000000000000000000005080000000000000000000000000000000000000000000000000000000000000508100000000000000000000000000000000000000000000000000000000000050820000000000000000000000000000000000000000000000000000000000005083000000000000000000000000000000000000000000000000000000000000508400000000000000000000000000000000000000000000000000000000000050850000000000000000000000000000000000000000000000000000000000005086000000000000000000000000000000000000000000000000000000000000508700000000000000000000000000000000000000000000000000000000000050880000000000000000000000000000000000000000000000000000000000005089000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000051010000000000000000000000000000000000000000000000000000000000005102000000000000000000000000000000000000000000000000000000000000510300000000000000000000000000000000000000000000000000000000000051040000000000000000000000000000000000000000000000000000000000005105000000000000000000000000000000000000000000000000000000000000510600000000000000000000000000000000000000000000000000000000000051070000000000000000000000000000000000000000000000000000000000005108000000000000000000000000000000000000000000000000000000000000510900000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006001000000000000000000000000000000000000000000000000000000000000600200000000000000000000000000000000000000000000000000000000000060030000000000000000000000000000000000000000000000000000000000006004000000000000000000000000000000000000000000000000000000000000600500000000000000000000000000000000000000000000000000000000000060060000000000000000000000000000000000000000000000000000000000006007000000000000000000000000000000000000000000000000000000000000600800000000000000000000000000000000000000000000000000000000000060090000000000000000000000000000000000000000000000000000000000006080000000000000000000000000000000000000000000000000000000000000608100000000000000000000000000000000000000000000000000000000000060820000000000000000000000000000000000000000000000000000000000006083000000000000000000000000000000000000000000000000000000000000608400000000000000000000000000000000000000000000000000000000000060850000000000000000000000000000000000000000000000000000000000006086000000000000000000000000000000000000000000000000000000000000608700000000000000000000000000000000000000000000000000000000000060880000000000000000000000000000000000000000000000000000000000006089000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061010000000000000000000000000000000000000000000000000000000000006102000000000000000000000000000000000000000000000000000000000000610300000000000000000000000000000000000000000000000000000000000061040000000000000000000000000000000000000000000000000000000000006105000000000000000000000000000000000000000000000000000000000000610600000000000000000000000000000000000000000000000000000000000061070000000000000000000000000000000000000000000000000000000000006108000000000000000000000000000000000000000000000000000000000000610900000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007001000000000000000000000000000000000000000000000000000000000000700200000000000000000000000000000000000000000000000000000000000070030000000000000000000000000000000000000000000000000000000000007004000000000000000000000000000000000000000000000000000000000000700500000000000000000000000000000000000000000000000000000000000070060000000000000000000000000000000000000000000000000000000000007007000000000000000000000000000000000000000000000000000000000000700800000000000000000000000000000000000000000000000000000000000070090000000000000000000000000000000000000000000000000000000000000015576f726c6420536572696573204261736562616c6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000035753420000000000000000000000000000000000000000000000000000000000" - ,"0x00" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000ec" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000be" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000be" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b7" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b7" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e7" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c7" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b6" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000009" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000008" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000008" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b5" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b4" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b3" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" - ,"0xdb0ec968000000000000000000000000cc5490a4b584ef7450492d45022ff017da5a35cc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000021" - ,"0x00" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000bd" - ,"0x" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001c15f77da29e4cfb5ff799df4e952958333647d0c33d815690a5f0982877e29d754e78ee4110d069f3218808affd075a5bb98a475bcfcbcf48e5f55e4d402a72bd000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000ae" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000ea" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e8" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a6" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000053" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000008f0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000a3" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0xdb0ec968000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004f" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001e3838038062001e388339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b508160099080519060200190620001999291906200026f565b508360089080519060200190620001b29291906200026f565b50505050505062000352565b82805482825590600052602060002090600f016010900481019282156200025c5791602002820160005b838211156200022a57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025a5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022a565b505b5090506200026b9190620002f6565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b257805160ff1916838001178555620002e3565b82800160010185558215620002e3579182015b82811115620002e2578251825591602001919060010190620002c5565b5b509050620002f291906200032a565b5090565b6200032791905b808211156200032357600081816101000a81549061ffff021916905550600101620002fd565b5090565b90565b6200034f91905b808211156200034b57600081600090555060010162000331565b5090565b90565b611ad680620003626000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063696ecc551461022a57806370a08231146102a857806372c5cb631461033657806395d89b411461035f578063a6fb475f146103ed578063bb6e7de914610485578063c2532c3d1461049a578063c9116b6914610539578063db0ec968146105a3578063ea8b5ca31461061c578063f0141d8414610649575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b6102a660048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610730565b005b34156102b357600080fd5b6102df600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b07565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610322578082015181840152602081019050610307565b505050509050019250505060405180910390f35b341561034157600080fd5b610349610bcc565b6040518082815260200191505060405180910390f35b341561036a57600080fd5b610372610bd6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103b2578082015181840152602081019050610397565b50505050905090810190601f1680156103df5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103f857600080fd5b610483600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610c7e565b005b341561049057600080fd5b61049861100d565b005b34156104a557600080fd5b61053760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506110a3565b005b341561054457600080fd5b61054c611324565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058f578082015181840152602081019050610574565b505050509050019250505060405180910390f35b34156105ae57600080fd5b61061a600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506113e7565b005b341561062757600080fd5b61062f6116bc565b604051808215151515815260200191505060405180910390f35b341561065457600080fd5b61065c6116d9565b6040518082815260200191505060405180910390f35b61067a611a0f565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b600080600080428911806107445750600089145b151561074f57600080fd5b61075a348a8a6116e4565b9350600184888888604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af115156107cd57600080fd5b5050602060405103519250600091505b8751821015610a055787828151811015156107f457fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561085257fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff1611151561088657600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108d79190611a23565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561093a57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109c957fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506107dd565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a4557600080fd5b8760405180828051906020019060200280838360005b83811015610a76578082015181840152602081019050610a5b565b5050505090500191505060405180910390208373ffffffffffffffffffffffffffffffffffffffff167fec67368df72865aef2c3748b4627cbcc0b539079709e3a6fbcaea909f4c68353898989604051808460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390a3505050505050505050565b610b0f611a5d565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610bc057602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610b875790505b50505050509050919050565b6000600754905090565b610bde611a0f565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c745780601f10610c4957610100808354040283529160200191610c74565b820191906000526020600020905b815481529060010190602001808311610c5757829003601f168201915b5050505050905090565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610cdf57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610f68576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610d8e57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff16141580610dc05750825b1515610dcb57600080fd5b8382815181101515610dd957fe5b9060200190602002015161ffff169050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610e3a9190611a23565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610e9d57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610f2c57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055508180600101925050610d37565b8360405180828051906020019060200280838360005b83811015610f99578082015181840152602081019050610f7e565b5050505090500191505060405180910390208573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f2dc84a69caf5a654b181a8d5cbc2194f4e4cab204443797dd13dff734279ee0660405160405180910390a4505050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561109e57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b60008060006110b46000808a6116e4565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1151561114457600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415156111ab57600080fd5b600090505b875181101561126357600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161120a9190611a23565b91600052602060002090601091828204019190066002028a8481518110151561122f57fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff1602179055505080806001019150506111b0565b8373ffffffffffffffffffffffffffffffffffffffff168860405180828051906020019060200280838360005b838110156112ab578082015181840152602081019050611290565b5050505090500191505060405180910390207f4490f02c64b562efdc9d14a196182a17381fdb62142db3a2117519102a151ea9898989604051808460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390a35050505050505050565b61132c611a5d565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156113dd57602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116113a45790505b5050505050905090565b6000806003544211156113f957600080fd5b600091505b8251821015611627576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110151561145557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161415151561148a57600080fd5b828281518110151561149857fe5b9060200190602002015161ffff169050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816114f99190611a23565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561155c57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156115eb57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506113fe565b8373ffffffffffffffffffffffffffffffffffffffff167f746c5afa194dd33ab23937c67f9e99800eb78b625176eb271c3dec182f57dbc1846040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156116a3578082015181840152602081019050611688565b505050509050019250505060405180910390a250505050565b60006003544211156116d157600190506116d6565b600090505b90565b60008060ff16905090565b60006116ee611a71565b60008060028551026054016040518059106117065750595b9080825280601f01601f1916602001820160405250925061172561071f565b9150600090505b602081101561178d5780600802879060020a02600102838281518110151561175057fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061172c565b600090505b60208110156117f65780600802869060020a0260010283602083018151811015156117b957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611792565b600090505b601481101561187a5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561183d57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506117fb565b600090505b84518110156119a0576008858281518110151561189857fe5b9060200190602002015161ffff169060020a90047f01000000000000000000000000000000000000000000000000000000000000000283600283026054018151811015156118e257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561192057fe5b906020019060200201517f010000000000000000000000000000000000000000000000000000000000000002836001600284026054010181518110151561196357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061187f565b826040518082805190602001908083835b6020831015156119d657805182526020820191506020810190506020830392506119b1565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b815481835581811511611a5857600f016010900481600f01601090048360005260206000209182019101611a579190611a85565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b611aa791905b80821115611aa3576000816000905550600101611a8b565b5090565b905600a165627a7a7230582014dd7212dadd7dc9b4e03b4efe24138115abc9c57e46d495b9379ae5a3d17fe3002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000b4d4a20636f6d656261636b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d4a430000000000000000000000000000000000000000000000000000000000" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f0000000000000000000000004b0b2389900d2638b684f037d6ec8efa61cf3ec9000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000004a" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000ac" - ,"0xdb0ec9680000000000000000000000004b0b2389900d2638b684f037d6ec8efa61cf3ec90000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000048" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000046" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000045" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000041" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e2" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000d5" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e6" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003e" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e5" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003a" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000005a9d16ba00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b607bc2ebbbc0ef7a3b1f520f5f5eea7a5a0dd3959e7013588020d2732d0cfc5647990dae807d0d1509186a0e4f4773d7569d906abe97829a3925350e62f6f116000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012" - ,"0xdb0ec96800000000000000000000000021acfd9f199fa91213a23193c9504f10cac2f0630000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000036" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001f" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003d" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000034" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000e4" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000030" - ,"0xdb0ec96800000000000000000000000021acfd9f199fa91213a23193c9504f10cac2f06300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002d" - ,"0xdb0ec968000000000000000000000000f8523f7cae2254d27efb50be22c118b31b79056200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a" - ,"0xdb0ec968000000000000000000000000f8523f7cae2254d27efb50be22c118b31b79056200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c" - ,"0xa6fb475f000000000000000000000000c830f48cf39419f0d01a125396ebf8dc6b61b65f000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001e" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001d" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000024" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000025" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000018" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a" - ,"0xdb0ec968000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000032" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001c" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001b" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000005a9a00e200000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001bc59d6718734043600a49ec2419e566fa03676058e88326ff1161c579c6b8e79951d22461ab6f27bedd72d6b56c1fecf9f4cbb79a7728c510022617a9e42782ea000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000005a9a001f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001c8ee5c1b644deba36a536a9ba32ca200af2914e212d725b6c2b4837bc9fdcb81f1658bfa9f6e7a8ea82a14efaa84bb1cf079b5ca5595f2dcd6a2adb5b89012c78000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000007a" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000019" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000017" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000014" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001a" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000020" - ,"0xdb0ec96800000000000000000000000021acfd9f199fa91213a23193c9504f10cac2f063000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000096" - ,"0xdb0ec968000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000095" - ,"0xdb0ec968000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000df" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000019" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c6" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000018" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000017" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000db" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000e1" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000de" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007" - ,"0x63877ab800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" - ,"0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c2" - ,"0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000089" - ,"0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000005a916f4300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b16e9d2a4a45ec33193fc04d3ffc4786b5d636f7b63127a81c4b9ae87109abc02798aeb53b47c30ab8ac1eb6231fc2990a2f2bc21dfecc698e5cdb6de1bd0ff060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000005a9002c000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b7e92d67d8443d0cf548be4ab6c29ae910b7996b248d876687d79bd5df9786cbd34797d008f639ce56189ad26555ee18ab16bf23b9a0cb9e3a0d60bbb4556770d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000005a8ff7b300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b929cbfe005791c7fba07d03b27f5b7ecf712ab0744cda025d2782590b78770d406e828ae6f3217ea3a0c9cd4a77a443cb3de037aa5ba7dd205b56a04aa341bbd000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x696ecc55000000000000000000000000000000000000000000000000000000005a8ff7b300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b929cbfe005791c7fba07d03b27f5b7ecf712ab0744cda025d2782590b78770d406e828ae6f3217ea3a0c9cd4a77a443cb3de037aa5ba7dd205b56a04aa341bbd000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x" - ,"0xdb0ec9680000000000000000000000009b9d498ce067f4dc2a971f2abd533182c309bf71000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xa9059cbb000000000000000000000000e56c880c8e0f8869f7fcb2f7f774d923578f9f5d0000000000000000000000000000000000000000000000000000000000000064" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060065534156200003357600080fd5b60405162001a3a38038062001a3a83398101604052808051820191906020018051820191906020018051906020019091908051820191905050835160008190555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000c9929190620001aa565b508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600890805190602001906200016b9291906200025b565b508260079080519060200190620001849291906200025b565b506001600960006101000a81548160ff021916908315150217905550505050506200033e565b82805482825590600052602060002090600f01601090048101928215620002485791602002820160005b838211156200021657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001d4565b8015620002465782816101000a81549061ffff021916905560020160208160010104928301926001030262000216565b505b509050620002579190620002e2565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200029e57805160ff1916838001178555620002cf565b82800160010185558215620002cf579182015b82811115620002ce578251825591602001919060010190620002b1565b5b509050620002de919062000316565b5090565b6200031391905b808211156200030f57600081816101000a81549061ffff021916905550600101620002e9565b5090565b90565b6200033b91905b80821115620003375760008160009055506001016200031d565b5090565b90565b6116ec806200034e6000396000f3006060604052600436106100e6576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100f657806318160ddd14610184578063313ce567146101ad57806332a2c5d0146101dc5780634f452b9a1461023157806358089fc61461025e578063696ecc551461028b57806370a082311461030957806372c5cb631461039757806395d89b41146103c0578063a6fb475f1461044e578063bb6e7de9146104e6578063c2532c3d146104fb578063db0ec9681461059a578063ea8b5ca314610613578063f0141d8414610640575b34156100f157600080fd5b600080fd5b341561010157600080fd5b610109610669565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014957808201518184015260208101905061012e565b50505050905090810190601f1680156101765780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018f57600080fd5b610197610711565b6040518082815260200191505060405180910390f35b34156101b857600080fd5b6101c061071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101e757600080fd5b6101ef61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023c57600080fd5b610244610727565b604051808215151515815260200191505060405180910390f35b341561026957600080fd5b61027161073e565b604051808215151515815260200191505060405180910390f35b61030760048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610751565b005b341561031457600080fd5b610340600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a7e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610383578082015181840152602081019050610368565b505050509050019250505060405180910390f35b34156103a257600080fd5b6103aa610b43565b6040518082815260200191505060405180910390f35b34156103cb57600080fd5b6103d3610b4d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104135780820151818401526020810190506103f8565b50505050905090810190601f1680156104405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561045957600080fd5b6104e4600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bf5565b005b34156104f157600080fd5b6104f9610e7e565b005b341561050657600080fd5b61059860048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f14565b005b34156105a557600080fd5b610611600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506110eb565b005b341561061e57600080fd5b6106266112d2565b604051808215151515815260200191505060405180910390f35b341561064b57600080fd5b6106536112ef565b6040518082815260200191505060405180910390f35b610671611625565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107075780601f106106dc57610100808354040283529160200191610707565b820191906000526020600020905b8154815290600101906020018083116106ea57829003601f168201915b5050505050905090565b60008054905090565b600081565b600030905090565b6000600960009054906101000a900460ff16905090565b600960009054906101000a900460ff1681565b600080600080428911806107655750600089145b151561077057600080fd5b61077b348a8a6112fa565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107fb57600080fd5b5050602060405103519250600091505b8751821015610a3357878281518110151561082257fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561088057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161115156108b457600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816109059190611639565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561096857fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109f757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff160217905550818060010192505061080b565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a7357600080fd5b505050505050505050565b610a86611673565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b3757602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610afe5790505b50505050509050919050565b6000600654905090565b610b55611625565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610beb5780601f10610bc057610100808354040283529160200191610beb565b820191906000526020600020905b815481529060010190602001808311610bce57829003601f168201915b5050505050905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c5357600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ca357600080fd5b600090505b8151811015610e7857600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d029190611639565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610d6657fe5b9060200190602002015161ffff16815481101515610d8057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610e1057fe5b9060200190602002015161ffff16815481101515610e2a57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506006600081548092919060010191905055508080600101915050610ca8565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f0f57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f256000808a6112fa565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610fc257600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561102957600080fd5b600090505b87518110156110e157600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110889190611639565b91600052602060002090601091828204019190066002028a848151811015156110ad57fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061102e565b5050505050505050565b60008090505b81518161ffff1610156112cd57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161114f9190611639565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff168151811015156111b757fe5b9060200190602002015161ffff168154811015156111d157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561126557fe5b9060200190602002015161ffff1681548110151561127f57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060066000815480929190600101919050555080806001019150506110f1565b505050565b60006003544211156112e757600190506112ec565b600090505b90565b60008060ff16905090565b6000611304611687565b600080600285510260540160405180591061131c5750595b9080825280601f01601f1916602001820160405250925061133b61071f565b9150600090505b60208110156113a35780600802879060020a02600102838281518110151561136657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611342565b600090505b602081101561140c5780600802869060020a0260010283602083018151811015156113cf57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506113a8565b600090505b60148110156114905780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561145357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611411565b600090505b84518110156115b657600885828151811015156114ae57fe5b9060200190602002015161ffff169060020a90047f01000000000000000000000000000000000000000000000000000000000000000283600283026054018151811015156114f857fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561153657fe5b906020019060200201517f010000000000000000000000000000000000000000000000000000000000000002836001600284026054010181518110151561157957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611495565b826040518082805190602001908083835b6020831015156115ec57805182526020820191506020810190506020830392506115c7565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b81548183558181151161166e57600f016010900481600f0160109004836000526020600020918201910161166d919061169b565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b6116bd91905b808211156116b95760008160009055506001016116a1565b5090565b905600a165627a7a72305820ebc7638bd4c8a42df0b8c70cc5a2d8005a57765ef68320b29e3793dcb9ba3d0800290000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - ,"0xdb0ec968000000000000000000000000a2845ed453b15beb7aaf3f01adabf69e79270838000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016" - ,"0xdb0ec9680000000000000000000000009f75b16cfb79f0bc11dacf149e342637864d89c80000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000d4" - ,"0xdb0ec9680000000000000000000000009f75b16cfb79f0bc11dacf149e342637864d89c800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000d2" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004b" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000004c" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000028" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003f" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060065534156200003357600080fd5b60405162001a3a38038062001a3a83398101604052808051820191906020018051820191906020018051906020019091908051820191905050835160008190555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000c9929190620001aa565b508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600890805190602001906200016b9291906200025b565b508260079080519060200190620001849291906200025b565b506001600960006101000a81548160ff021916908315150217905550505050506200033e565b82805482825590600052602060002090600f01601090048101928215620002485791602002820160005b838211156200021657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001d4565b8015620002465782816101000a81549061ffff021916905560020160208160010104928301926001030262000216565b505b509050620002579190620002e2565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200029e57805160ff1916838001178555620002cf565b82800160010185558215620002cf579182015b82811115620002ce578251825591602001919060010190620002b1565b5b509050620002de919062000316565b5090565b6200031391905b808211156200030f57600081816101000a81549061ffff021916905550600101620002e9565b5090565b90565b6200033b91905b80821115620003375760008160009055506001016200031d565b5090565b90565b6116ec806200034e6000396000f3006060604052600436106100e6576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100f657806318160ddd14610184578063313ce567146101ad57806332a2c5d0146101dc5780634f452b9a1461023157806358089fc61461025e578063696ecc551461028b57806370a082311461030957806372c5cb631461039757806395d89b41146103c0578063a6fb475f1461044e578063bb6e7de9146104e6578063c2532c3d146104fb578063db0ec9681461059a578063ea8b5ca314610613578063f0141d8414610640575b34156100f157600080fd5b600080fd5b341561010157600080fd5b610109610669565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014957808201518184015260208101905061012e565b50505050905090810190601f1680156101765780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018f57600080fd5b610197610711565b6040518082815260200191505060405180910390f35b34156101b857600080fd5b6101c061071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101e757600080fd5b6101ef61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023c57600080fd5b610244610727565b604051808215151515815260200191505060405180910390f35b341561026957600080fd5b61027161073e565b604051808215151515815260200191505060405180910390f35b61030760048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610751565b005b341561031457600080fd5b610340600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a7e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610383578082015181840152602081019050610368565b505050509050019250505060405180910390f35b34156103a257600080fd5b6103aa610b43565b6040518082815260200191505060405180910390f35b34156103cb57600080fd5b6103d3610b4d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104135780820151818401526020810190506103f8565b50505050905090810190601f1680156104405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561045957600080fd5b6104e4600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bf5565b005b34156104f157600080fd5b6104f9610e7e565b005b341561050657600080fd5b61059860048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f14565b005b34156105a557600080fd5b610611600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506110eb565b005b341561061e57600080fd5b6106266112d2565b604051808215151515815260200191505060405180910390f35b341561064b57600080fd5b6106536112ef565b6040518082815260200191505060405180910390f35b610671611625565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107075780601f106106dc57610100808354040283529160200191610707565b820191906000526020600020905b8154815290600101906020018083116106ea57829003601f168201915b5050505050905090565b60008054905090565b600081565b600030905090565b6000600960009054906101000a900460ff16905090565b600960009054906101000a900460ff1681565b600080600080428911806107655750600089145b151561077057600080fd5b61077b348a8a6112fa565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107fb57600080fd5b5050602060405103519250600091505b8751821015610a3357878281518110151561082257fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561088057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161115156108b457600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816109059190611639565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561096857fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109f757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff160217905550818060010192505061080b565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a7357600080fd5b505050505050505050565b610a86611673565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b3757602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610afe5790505b50505050509050919050565b6000600654905090565b610b55611625565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610beb5780601f10610bc057610100808354040283529160200191610beb565b820191906000526020600020905b815481529060010190602001808311610bce57829003601f168201915b5050505050905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c5357600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ca357600080fd5b600090505b8151811015610e7857600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d029190611639565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610d6657fe5b9060200190602002015161ffff16815481101515610d8057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610e1057fe5b9060200190602002015161ffff16815481101515610e2a57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506006600081548092919060010191905055508080600101915050610ca8565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f0f57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f256000808a6112fa565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610fc257600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561102957600080fd5b600090505b87518110156110e157600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110889190611639565b91600052602060002090601091828204019190066002028a848151811015156110ad57fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061102e565b5050505050505050565b60008090505b81518161ffff1610156112cd57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161114f9190611639565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff168151811015156111b757fe5b9060200190602002015161ffff168154811015156111d157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561126557fe5b9060200190602002015161ffff1681548110151561127f57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060066000815480929190600101919050555080806001019150506110f1565b505050565b60006003544211156112e757600190506112ec565b600090505b90565b60008060ff16905090565b6000611304611687565b600080600285510260540160405180591061131c5750595b9080825280601f01601f1916602001820160405250925061133b61071f565b9150600090505b60208110156113a35780600802879060020a02600102838281518110151561136657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611342565b600090505b602081101561140c5780600802869060020a0260010283602083018151811015156113cf57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506113a8565b600090505b60148110156114905780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561145357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611411565b600090505b84518110156115b657600885828151811015156114ae57fe5b9060200190602002015161ffff169060020a90047f01000000000000000000000000000000000000000000000000000000000000000283600283026054018151811015156114f857fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561153657fe5b906020019060200201517f010000000000000000000000000000000000000000000000000000000000000002836001600284026054010181518110151561157957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611495565b826040518082805190602001908083835b6020831015156115ec57805182526020820191506020810190506020830392506115c7565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b81548183558181151161166e57600f016010900481600f0160109004836000526020600020918201910161166d919061169b565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b6116bd91905b808211156116b95760008160009055506001016116a1565b5090565b905600a165627a7a723058207037e0229a2aef420f84573dc598a79fea426da8415b9fb6124bfbce4c0ac507002900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000001c4000000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001081000000000000000000000000000000000000000000000000000000000000108200000000000000000000000000000000000000000000000000000000000010830000000000000000000000000000000000000000000000000000000000001084000000000000000000000000000000000000000000000000000000000000108500000000000000000000000000000000000000000000000000000000000010860000000000000000000000000000000000000000000000000000000000001087000000000000000000000000000000000000000000000000000000000000108800000000000000000000000000000000000000000000000000000000000010890000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110100000000000000000000000000000000000000000000000000000000000011020000000000000000000000000000000000000000000000000000000000001103000000000000000000000000000000000000000000000000000000000000110400000000000000000000000000000000000000000000000000000000000011050000000000000000000000000000000000000000000000000000000000001106000000000000000000000000000000000000000000000000000000000000110700000000000000000000000000000000000000000000000000000000000011080000000000000000000000000000000000000000000000000000000000001109000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020010000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000200300000000000000000000000000000000000000000000000000000000000020040000000000000000000000000000000000000000000000000000000000002005000000000000000000000000000000000000000000000000000000000000200600000000000000000000000000000000000000000000000000000000000020070000000000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000200900000000000000000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000002081000000000000000000000000000000000000000000000000000000000000208200000000000000000000000000000000000000000000000000000000000020830000000000000000000000000000000000000000000000000000000000002084000000000000000000000000000000000000000000000000000000000000208500000000000000000000000000000000000000000000000000000000000020860000000000000000000000000000000000000000000000000000000000002087000000000000000000000000000000000000000000000000000000000000208800000000000000000000000000000000000000000000000000000000000020890000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000210100000000000000000000000000000000000000000000000000000000000021020000000000000000000000000000000000000000000000000000000000002103000000000000000000000000000000000000000000000000000000000000210400000000000000000000000000000000000000000000000000000000000021050000000000000000000000000000000000000000000000000000000000002106000000000000000000000000000000000000000000000000000000000000210700000000000000000000000000000000000000000000000000000000000021080000000000000000000000000000000000000000000000000000000000002109000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030010000000000000000000000000000000000000000000000000000000000003002000000000000000000000000000000000000000000000000000000000000300300000000000000000000000000000000000000000000000000000000000030040000000000000000000000000000000000000000000000000000000000003005000000000000000000000000000000000000000000000000000000000000300600000000000000000000000000000000000000000000000000000000000030070000000000000000000000000000000000000000000000000000000000003008000000000000000000000000000000000000000000000000000000000000300900000000000000000000000000000000000000000000000000000000000030800000000000000000000000000000000000000000000000000000000000003081000000000000000000000000000000000000000000000000000000000000308200000000000000000000000000000000000000000000000000000000000030830000000000000000000000000000000000000000000000000000000000003084000000000000000000000000000000000000000000000000000000000000308500000000000000000000000000000000000000000000000000000000000030860000000000000000000000000000000000000000000000000000000000003087000000000000000000000000000000000000000000000000000000000000308800000000000000000000000000000000000000000000000000000000000030890000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000310100000000000000000000000000000000000000000000000000000000000031020000000000000000000000000000000000000000000000000000000000003103000000000000000000000000000000000000000000000000000000000000310400000000000000000000000000000000000000000000000000000000000031050000000000000000000000000000000000000000000000000000000000003106000000000000000000000000000000000000000000000000000000000000310700000000000000000000000000000000000000000000000000000000000031080000000000000000000000000000000000000000000000000000000000003109000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040010000000000000000000000000000000000000000000000000000000000004002000000000000000000000000000000000000000000000000000000000000400300000000000000000000000000000000000000000000000000000000000040040000000000000000000000000000000000000000000000000000000000004005000000000000000000000000000000000000000000000000000000000000400600000000000000000000000000000000000000000000000000000000000040070000000000000000000000000000000000000000000000000000000000004008000000000000000000000000000000000000000000000000000000000000400900000000000000000000000000000000000000000000000000000000000040800000000000000000000000000000000000000000000000000000000000004081000000000000000000000000000000000000000000000000000000000000408200000000000000000000000000000000000000000000000000000000000040830000000000000000000000000000000000000000000000000000000000004084000000000000000000000000000000000000000000000000000000000000408500000000000000000000000000000000000000000000000000000000000040860000000000000000000000000000000000000000000000000000000000004087000000000000000000000000000000000000000000000000000000000000408800000000000000000000000000000000000000000000000000000000000040890000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000410100000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004103000000000000000000000000000000000000000000000000000000000000410400000000000000000000000000000000000000000000000000000000000041050000000000000000000000000000000000000000000000000000000000004106000000000000000000000000000000000000000000000000000000000000410700000000000000000000000000000000000000000000000000000000000041080000000000000000000000000000000000000000000000000000000000004109000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050010000000000000000000000000000000000000000000000000000000000005002000000000000000000000000000000000000000000000000000000000000500300000000000000000000000000000000000000000000000000000000000050040000000000000000000000000000000000000000000000000000000000005005000000000000000000000000000000000000000000000000000000000000500600000000000000000000000000000000000000000000000000000000000050070000000000000000000000000000000000000000000000000000000000005008000000000000000000000000000000000000000000000000000000000000500900000000000000000000000000000000000000000000000000000000000050800000000000000000000000000000000000000000000000000000000000005081000000000000000000000000000000000000000000000000000000000000508200000000000000000000000000000000000000000000000000000000000050830000000000000000000000000000000000000000000000000000000000005084000000000000000000000000000000000000000000000000000000000000508500000000000000000000000000000000000000000000000000000000000050860000000000000000000000000000000000000000000000000000000000005087000000000000000000000000000000000000000000000000000000000000508800000000000000000000000000000000000000000000000000000000000050890000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000510100000000000000000000000000000000000000000000000000000000000051020000000000000000000000000000000000000000000000000000000000005103000000000000000000000000000000000000000000000000000000000000510400000000000000000000000000000000000000000000000000000000000051050000000000000000000000000000000000000000000000000000000000005106000000000000000000000000000000000000000000000000000000000000510700000000000000000000000000000000000000000000000000000000000051080000000000000000000000000000000000000000000000000000000000005109000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060010000000000000000000000000000000000000000000000000000000000006002000000000000000000000000000000000000000000000000000000000000600300000000000000000000000000000000000000000000000000000000000060040000000000000000000000000000000000000000000000000000000000006005000000000000000000000000000000000000000000000000000000000000600600000000000000000000000000000000000000000000000000000000000060070000000000000000000000000000000000000000000000000000000000006008000000000000000000000000000000000000000000000000000000000000600900000000000000000000000000000000000000000000000000000000000060800000000000000000000000000000000000000000000000000000000000006081000000000000000000000000000000000000000000000000000000000000608200000000000000000000000000000000000000000000000000000000000060830000000000000000000000000000000000000000000000000000000000006084000000000000000000000000000000000000000000000000000000000000608500000000000000000000000000000000000000000000000000000000000060860000000000000000000000000000000000000000000000000000000000006087000000000000000000000000000000000000000000000000000000000000608800000000000000000000000000000000000000000000000000000000000060890000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000610100000000000000000000000000000000000000000000000000000000000061020000000000000000000000000000000000000000000000000000000000006103000000000000000000000000000000000000000000000000000000000000610400000000000000000000000000000000000000000000000000000000000061050000000000000000000000000000000000000000000000000000000000006106000000000000000000000000000000000000000000000000000000000000610700000000000000000000000000000000000000000000000000000000000061080000000000000000000000000000000000000000000000000000000000006109000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070010000000000000000000000000000000000000000000000000000000000007002000000000000000000000000000000000000000000000000000000000000700300000000000000000000000000000000000000000000000000000000000070040000000000000000000000000000000000000000000000000000000000007005000000000000000000000000000000000000000000000000000000000000700600000000000000000000000000000000000000000000000000000000000070070000000000000000000000000000000000000000000000000000000000007008000000000000000000000000000000000000000000000000000000000000700900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0xbb6e7de9" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060055534156200003357600080fd5b60405162000fd038038062000fd083398101604052808051820191906020018051820191906020018051906020019091908051820191905050835160008190555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000c992919062000169565b508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600790805190602001906200012a9291906200021a565b508260069080519060200190620001439291906200021a565b506001600860006101000a81548160ff02191690831515021790555050505050620002fd565b82805482825590600052602060002090600f01601090048101928215620002075791602002820160005b83821115620001d557835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030262000193565b8015620002055782816101000a81549061ffff0219169055600201602081600101049283019260010302620001d5565b505b509050620002169190620002a1565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025d57805160ff19168380011785556200028e565b828001600101855582156200028e579182015b828111156200028d57825182559160200191906001019062000270565b5b5090506200029d9190620002d5565b5090565b620002d291905b80821115620002ce57600081816101000a81549061ffff021916905550600101620002a8565b5090565b90565b620002fa91905b80821115620002f6576000816000905550600101620002dc565b5090565b90565b610cc3806200030d6000396000f3006060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100ca57806318160ddd14610158578063313ce567146101815780634f452b9a146101b057806370a08231146101dd57806372c5cb631461026b57806395d89b4114610294578063a6fb475f14610322578063bb6e7de9146103ba578063db0ec968146103cf578063ea8b5ca314610448578063f0141d8414610475575b34156100c557600080fd5b600080fd5b34156100d557600080fd5b6100dd61049e565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561011d578082015181840152602081019050610102565b50505050905090810190601f16801561014a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561016357600080fd5b61016b610546565b6040518082815260200191505060405180910390f35b341561018c57600080fd5b61019461054f565b604051808260ff1660ff16815260200191505060405180910390f35b34156101bb57600080fd5b6101c3610554565b604051808215151515815260200191505060405180910390f35b34156101e857600080fd5b610214600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061056b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561025757808201518184015260208101905061023c565b505050509050019250505060405180910390f35b341561027657600080fd5b61027e610630565b6040518082815260200191505060405180910390f35b341561029f57600080fd5b6102a761063a565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102e75780820151818401526020810190506102cc565b50505050905090810190601f1680156103145780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561032d57600080fd5b6103b8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506106e2565b005b34156103c557600080fd5b6103cd61096b565b005b34156103da57600080fd5b610446600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610a01565b005b341561045357600080fd5b61045b610be8565b604051808215151515815260200191505060405180910390f35b341561048057600080fd5b610488610c05565b6040518082815260200191505060405180910390f35b6104a6610c10565b60068054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561053c5780601f106105115761010080835404028352916020019161053c565b820191906000526020600020905b81548152906001019060200180831161051f57829003601f168201915b5050505050905090565b60008054905090565b600081565b6000600860009054906101000a900460ff16905090565b610573610c24565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561062457602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116105eb5790505b50505050509050919050565b6000600554905090565b610642610c10565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106d85780601f106106ad576101008083540402835291602001916106d8565b820191906000526020600020905b8154815290600101906020018083116106bb57829003601f168201915b5050505050905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561074057600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050101561079057600080fd5b600090505b815181101561096557600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816107ef9190610c38565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858581518110151561085357fe5b9060200190602002015161ffff1681548110151561086d57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083838151811015156108fd57fe5b9060200190602002015161ffff1681548110151561091757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506005600081548092919060010191905055508080600101915050610795565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156109fc57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b60008090505b81518161ffff161015610be357600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610a659190610c38565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff16815181101515610acd57fe5b9060200190602002015161ffff16815481101515610ae757fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff16815181101515610b7b57fe5b9060200190602002015161ffff16815481101515610b9557fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506005600081548092919060010191905055508080600101915050610a07565b505050565b6000600354421115610bfd5760019050610c02565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b815481835581811511610c6d57600f016010900481600f01601090048360005260206000209182019101610c6c9190610c72565b5b505050565b610c9491905b80821115610c90576000816000905550600101610c78565b5090565b905600a165627a7a72305820212b7b59296e18695c347b474d7d655c250fd94e27f00f051ef88cb281d6632a002900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000001c4000000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001081000000000000000000000000000000000000000000000000000000000000108200000000000000000000000000000000000000000000000000000000000010830000000000000000000000000000000000000000000000000000000000001084000000000000000000000000000000000000000000000000000000000000108500000000000000000000000000000000000000000000000000000000000010860000000000000000000000000000000000000000000000000000000000001087000000000000000000000000000000000000000000000000000000000000108800000000000000000000000000000000000000000000000000000000000010890000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110100000000000000000000000000000000000000000000000000000000000011020000000000000000000000000000000000000000000000000000000000001103000000000000000000000000000000000000000000000000000000000000110400000000000000000000000000000000000000000000000000000000000011050000000000000000000000000000000000000000000000000000000000001106000000000000000000000000000000000000000000000000000000000000110700000000000000000000000000000000000000000000000000000000000011080000000000000000000000000000000000000000000000000000000000001109000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020010000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000200300000000000000000000000000000000000000000000000000000000000020040000000000000000000000000000000000000000000000000000000000002005000000000000000000000000000000000000000000000000000000000000200600000000000000000000000000000000000000000000000000000000000020070000000000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000200900000000000000000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000002081000000000000000000000000000000000000000000000000000000000000208200000000000000000000000000000000000000000000000000000000000020830000000000000000000000000000000000000000000000000000000000002084000000000000000000000000000000000000000000000000000000000000208500000000000000000000000000000000000000000000000000000000000020860000000000000000000000000000000000000000000000000000000000002087000000000000000000000000000000000000000000000000000000000000208800000000000000000000000000000000000000000000000000000000000020890000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000210100000000000000000000000000000000000000000000000000000000000021020000000000000000000000000000000000000000000000000000000000002103000000000000000000000000000000000000000000000000000000000000210400000000000000000000000000000000000000000000000000000000000021050000000000000000000000000000000000000000000000000000000000002106000000000000000000000000000000000000000000000000000000000000210700000000000000000000000000000000000000000000000000000000000021080000000000000000000000000000000000000000000000000000000000002109000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030010000000000000000000000000000000000000000000000000000000000003002000000000000000000000000000000000000000000000000000000000000300300000000000000000000000000000000000000000000000000000000000030040000000000000000000000000000000000000000000000000000000000003005000000000000000000000000000000000000000000000000000000000000300600000000000000000000000000000000000000000000000000000000000030070000000000000000000000000000000000000000000000000000000000003008000000000000000000000000000000000000000000000000000000000000300900000000000000000000000000000000000000000000000000000000000030800000000000000000000000000000000000000000000000000000000000003081000000000000000000000000000000000000000000000000000000000000308200000000000000000000000000000000000000000000000000000000000030830000000000000000000000000000000000000000000000000000000000003084000000000000000000000000000000000000000000000000000000000000308500000000000000000000000000000000000000000000000000000000000030860000000000000000000000000000000000000000000000000000000000003087000000000000000000000000000000000000000000000000000000000000308800000000000000000000000000000000000000000000000000000000000030890000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000310100000000000000000000000000000000000000000000000000000000000031020000000000000000000000000000000000000000000000000000000000003103000000000000000000000000000000000000000000000000000000000000310400000000000000000000000000000000000000000000000000000000000031050000000000000000000000000000000000000000000000000000000000003106000000000000000000000000000000000000000000000000000000000000310700000000000000000000000000000000000000000000000000000000000031080000000000000000000000000000000000000000000000000000000000003109000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040010000000000000000000000000000000000000000000000000000000000004002000000000000000000000000000000000000000000000000000000000000400300000000000000000000000000000000000000000000000000000000000040040000000000000000000000000000000000000000000000000000000000004005000000000000000000000000000000000000000000000000000000000000400600000000000000000000000000000000000000000000000000000000000040070000000000000000000000000000000000000000000000000000000000004008000000000000000000000000000000000000000000000000000000000000400900000000000000000000000000000000000000000000000000000000000040800000000000000000000000000000000000000000000000000000000000004081000000000000000000000000000000000000000000000000000000000000408200000000000000000000000000000000000000000000000000000000000040830000000000000000000000000000000000000000000000000000000000004084000000000000000000000000000000000000000000000000000000000000408500000000000000000000000000000000000000000000000000000000000040860000000000000000000000000000000000000000000000000000000000004087000000000000000000000000000000000000000000000000000000000000408800000000000000000000000000000000000000000000000000000000000040890000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000410100000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004103000000000000000000000000000000000000000000000000000000000000410400000000000000000000000000000000000000000000000000000000000041050000000000000000000000000000000000000000000000000000000000004106000000000000000000000000000000000000000000000000000000000000410700000000000000000000000000000000000000000000000000000000000041080000000000000000000000000000000000000000000000000000000000004109000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050010000000000000000000000000000000000000000000000000000000000005002000000000000000000000000000000000000000000000000000000000000500300000000000000000000000000000000000000000000000000000000000050040000000000000000000000000000000000000000000000000000000000005005000000000000000000000000000000000000000000000000000000000000500600000000000000000000000000000000000000000000000000000000000050070000000000000000000000000000000000000000000000000000000000005008000000000000000000000000000000000000000000000000000000000000500900000000000000000000000000000000000000000000000000000000000050800000000000000000000000000000000000000000000000000000000000005081000000000000000000000000000000000000000000000000000000000000508200000000000000000000000000000000000000000000000000000000000050830000000000000000000000000000000000000000000000000000000000005084000000000000000000000000000000000000000000000000000000000000508500000000000000000000000000000000000000000000000000000000000050860000000000000000000000000000000000000000000000000000000000005087000000000000000000000000000000000000000000000000000000000000508800000000000000000000000000000000000000000000000000000000000050890000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000510100000000000000000000000000000000000000000000000000000000000051020000000000000000000000000000000000000000000000000000000000005103000000000000000000000000000000000000000000000000000000000000510400000000000000000000000000000000000000000000000000000000000051050000000000000000000000000000000000000000000000000000000000005106000000000000000000000000000000000000000000000000000000000000510700000000000000000000000000000000000000000000000000000000000051080000000000000000000000000000000000000000000000000000000000005109000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060010000000000000000000000000000000000000000000000000000000000006002000000000000000000000000000000000000000000000000000000000000600300000000000000000000000000000000000000000000000000000000000060040000000000000000000000000000000000000000000000000000000000006005000000000000000000000000000000000000000000000000000000000000600600000000000000000000000000000000000000000000000000000000000060070000000000000000000000000000000000000000000000000000000000006008000000000000000000000000000000000000000000000000000000000000600900000000000000000000000000000000000000000000000000000000000060800000000000000000000000000000000000000000000000000000000000006081000000000000000000000000000000000000000000000000000000000000608200000000000000000000000000000000000000000000000000000000000060830000000000000000000000000000000000000000000000000000000000006084000000000000000000000000000000000000000000000000000000000000608500000000000000000000000000000000000000000000000000000000000060860000000000000000000000000000000000000000000000000000000000006087000000000000000000000000000000000000000000000000000000000000608800000000000000000000000000000000000000000000000000000000000060890000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000610100000000000000000000000000000000000000000000000000000000000061020000000000000000000000000000000000000000000000000000000000006103000000000000000000000000000000000000000000000000000000000000610400000000000000000000000000000000000000000000000000000000000061050000000000000000000000000000000000000000000000000000000000006106000000000000000000000000000000000000000000000000000000000000610700000000000000000000000000000000000000000000000000000000000061080000000000000000000000000000000000000000000000000000000000006109000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070010000000000000000000000000000000000000000000000000000000000007002000000000000000000000000000000000000000000000000000000000000700300000000000000000000000000000000000000000000000000000000000070040000000000000000000000000000000000000000000000000000000000007005000000000000000000000000000000000000000000000000000000000000700600000000000000000000000000000000000000000000000000000000000070070000000000000000000000000000000000000000000000000000000000007008000000000000000000000000000000000000000000000000000000000000700900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0x4f452b9a" - ,"0xbb6e7de9" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b" - ,"0x4f452b9a" - ,"0x4f452b9a" - ,"0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b604051620015043803806200150483398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191905050845160008190555084600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000d29291906200015f565b508260048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160068190555080600990805190602001906200013a92919062000210565b5083600890805190602001906200015392919062000210565b505050505050620002f3565b82805482825590600052602060002090600f01601090048101928215620001fd5791602002820160005b83821115620001cb57835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030262000189565b8015620001fb5782816101000a81549061ffff0219169055600201602081600101049283019260010302620001cb565b505b5090506200020c919062000297565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025357805160ff191683800117855562000284565b8280016001018555821562000284579182015b828111156200028357825182559160200191906001019062000266565b5b509050620002939190620002cb565b5090565b620002c891905b80821115620002c457600081816101000a81549061ffff0219169055506001016200029e565b5090565b90565b620002f091905b80821115620002ec576000816000905550600101620002d2565b5090565b90565b61120180620003036000396000f3006060604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100e05780630e1c2d461461016e57806318160ddd146101c8578063313ce567146101f15780634f452b9a1461022057806370a082311461024d57806372c5cb63146102db57806395d89b4114610304578063a6fb475f14610392578063bb6e7de91461042a578063c2bf17b01461043f578063db0ec968146104ed578063ea8b5ca314610566578063f0141d8414610593575b34156100db57600080fd5b600080fd5b34156100eb57600080fd5b6100f36105bc565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610133578082015181840152602081019050610118565b50505050905090810190601f1680156101605780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101ae60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610664565b604051808215151515815260200191505060405180910390f35b34156101d357600080fd5b6101db6107f1565b6040518082815260200191505060405180910390f35b34156101fc57600080fd5b6102046107fa565b604051808260ff1660ff16815260200191505060405180910390f35b341561022b57600080fd5b6102336107ff565b604051808215151515815260200191505060405180910390f35b341561025857600080fd5b610284600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610808565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102c75780820151818401526020810190506102ac565b505050509050019250505060405180910390f35b34156102e657600080fd5b6102ee6108cd565b6040518082815260200191505060405180910390f35b341561030f57600080fd5b6103176108d7565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561035757808201518184015260208101905061033c565b50505050905090810190601f1680156103845780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561039d57600080fd5b610428600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061097f565b005b341561043557600080fd5b61043d610c76565b005b341561044a57600080fd5b61048a60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610d0c565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156104f857600080fd5b610564600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610e80565b005b341561057157600080fd5b610579611126565b604051808215151515815260200191505060405180910390f35b341561059e57600080fd5b6105a6611143565b6040518082815260200191505060405180910390f35b6105c461114e565b60088054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561065a5780601f1061062f5761010080835404028352916020019161065a565b820191906000526020600020905b81548152906001019060200180831161063d57829003601f168201915b5050505050905090565b60008060008060008060008061067c8c8c8c8c610d0c565b96509650965096508561ffff168502925083801561069957508234145b156107dd57600654348115156106ab57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156106f357600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050151561075557600080fd5b60076000815480929190600101919050555085600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550600197506107e2565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b60006001905090565b610810611162565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156108c157602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116108885790505b50505050509050919050565b6000600754905090565b6108df61114e565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109755780601f1061094a57610100808354040283529160200191610975565b820191906000526020600020905b81548152906001019060200180831161095857829003601f168201915b5050505050905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156109dd57600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610a2d57600080fd5b600090505b8151811015610c0257600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610a8c9190611176565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610af057fe5b9060200190602002015161ffff16815481101515610b0a57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610b9a57fe5b9060200190602002015161ffff16815481101515610bb457fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610a32565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555050505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610d0757600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610dbb57600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff16600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050031015610e705760009050610e75565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ed257600080fd5b600090505b81518161ffff1610156110b357600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610f359190611176565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff16815181101515610f9d57fe5b9060200190602002015161ffff16815481101515610fb757fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561104b57fe5b9060200190602002015161ffff1681548110151561106557fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610ed7565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550505050565b600060045442111561113b5760019050611140565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b8154818355818115116111ab57600f016010900481600f016010900483600052602060002091820191016111aa91906111b0565b5b505050565b6111d291905b808211156111ce5760008160009055506001016111b6565b5090565b905600a165627a7a72305820da22677d7b59f2e0bfb17b922124b5c626653f72e3fbf15e60ff47e0065dbcee002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000001c20000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000001c6000000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001081000000000000000000000000000000000000000000000000000000000000108200000000000000000000000000000000000000000000000000000000000010830000000000000000000000000000000000000000000000000000000000001084000000000000000000000000000000000000000000000000000000000000108500000000000000000000000000000000000000000000000000000000000010860000000000000000000000000000000000000000000000000000000000001087000000000000000000000000000000000000000000000000000000000000108800000000000000000000000000000000000000000000000000000000000010890000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110100000000000000000000000000000000000000000000000000000000000011020000000000000000000000000000000000000000000000000000000000001103000000000000000000000000000000000000000000000000000000000000110400000000000000000000000000000000000000000000000000000000000011050000000000000000000000000000000000000000000000000000000000001106000000000000000000000000000000000000000000000000000000000000110700000000000000000000000000000000000000000000000000000000000011080000000000000000000000000000000000000000000000000000000000001109000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020010000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000200300000000000000000000000000000000000000000000000000000000000020040000000000000000000000000000000000000000000000000000000000002005000000000000000000000000000000000000000000000000000000000000200600000000000000000000000000000000000000000000000000000000000020070000000000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000200900000000000000000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000002081000000000000000000000000000000000000000000000000000000000000208200000000000000000000000000000000000000000000000000000000000020830000000000000000000000000000000000000000000000000000000000002084000000000000000000000000000000000000000000000000000000000000208500000000000000000000000000000000000000000000000000000000000020860000000000000000000000000000000000000000000000000000000000002087000000000000000000000000000000000000000000000000000000000000208800000000000000000000000000000000000000000000000000000000000020890000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000210100000000000000000000000000000000000000000000000000000000000021020000000000000000000000000000000000000000000000000000000000002103000000000000000000000000000000000000000000000000000000000000210400000000000000000000000000000000000000000000000000000000000021050000000000000000000000000000000000000000000000000000000000002106000000000000000000000000000000000000000000000000000000000000210700000000000000000000000000000000000000000000000000000000000021080000000000000000000000000000000000000000000000000000000000002109000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030010000000000000000000000000000000000000000000000000000000000003002000000000000000000000000000000000000000000000000000000000000300300000000000000000000000000000000000000000000000000000000000030040000000000000000000000000000000000000000000000000000000000003005000000000000000000000000000000000000000000000000000000000000300600000000000000000000000000000000000000000000000000000000000030070000000000000000000000000000000000000000000000000000000000003008000000000000000000000000000000000000000000000000000000000000300900000000000000000000000000000000000000000000000000000000000030800000000000000000000000000000000000000000000000000000000000003081000000000000000000000000000000000000000000000000000000000000308200000000000000000000000000000000000000000000000000000000000030830000000000000000000000000000000000000000000000000000000000003084000000000000000000000000000000000000000000000000000000000000308500000000000000000000000000000000000000000000000000000000000030860000000000000000000000000000000000000000000000000000000000003087000000000000000000000000000000000000000000000000000000000000308800000000000000000000000000000000000000000000000000000000000030890000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000310100000000000000000000000000000000000000000000000000000000000031020000000000000000000000000000000000000000000000000000000000003103000000000000000000000000000000000000000000000000000000000000310400000000000000000000000000000000000000000000000000000000000031050000000000000000000000000000000000000000000000000000000000003106000000000000000000000000000000000000000000000000000000000000310700000000000000000000000000000000000000000000000000000000000031080000000000000000000000000000000000000000000000000000000000003109000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040010000000000000000000000000000000000000000000000000000000000004002000000000000000000000000000000000000000000000000000000000000400300000000000000000000000000000000000000000000000000000000000040040000000000000000000000000000000000000000000000000000000000004005000000000000000000000000000000000000000000000000000000000000400600000000000000000000000000000000000000000000000000000000000040070000000000000000000000000000000000000000000000000000000000004008000000000000000000000000000000000000000000000000000000000000400900000000000000000000000000000000000000000000000000000000000040800000000000000000000000000000000000000000000000000000000000004081000000000000000000000000000000000000000000000000000000000000408200000000000000000000000000000000000000000000000000000000000040830000000000000000000000000000000000000000000000000000000000004084000000000000000000000000000000000000000000000000000000000000408500000000000000000000000000000000000000000000000000000000000040860000000000000000000000000000000000000000000000000000000000004087000000000000000000000000000000000000000000000000000000000000408800000000000000000000000000000000000000000000000000000000000040890000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000410100000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004103000000000000000000000000000000000000000000000000000000000000410400000000000000000000000000000000000000000000000000000000000041050000000000000000000000000000000000000000000000000000000000004106000000000000000000000000000000000000000000000000000000000000410700000000000000000000000000000000000000000000000000000000000041080000000000000000000000000000000000000000000000000000000000004109000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050010000000000000000000000000000000000000000000000000000000000005002000000000000000000000000000000000000000000000000000000000000500300000000000000000000000000000000000000000000000000000000000050040000000000000000000000000000000000000000000000000000000000005005000000000000000000000000000000000000000000000000000000000000500600000000000000000000000000000000000000000000000000000000000050070000000000000000000000000000000000000000000000000000000000005008000000000000000000000000000000000000000000000000000000000000500900000000000000000000000000000000000000000000000000000000000050800000000000000000000000000000000000000000000000000000000000005081000000000000000000000000000000000000000000000000000000000000508200000000000000000000000000000000000000000000000000000000000050830000000000000000000000000000000000000000000000000000000000005084000000000000000000000000000000000000000000000000000000000000508500000000000000000000000000000000000000000000000000000000000050860000000000000000000000000000000000000000000000000000000000005087000000000000000000000000000000000000000000000000000000000000508800000000000000000000000000000000000000000000000000000000000050890000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000510100000000000000000000000000000000000000000000000000000000000051020000000000000000000000000000000000000000000000000000000000005103000000000000000000000000000000000000000000000000000000000000510400000000000000000000000000000000000000000000000000000000000051050000000000000000000000000000000000000000000000000000000000005106000000000000000000000000000000000000000000000000000000000000510700000000000000000000000000000000000000000000000000000000000051080000000000000000000000000000000000000000000000000000000000005109000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060010000000000000000000000000000000000000000000000000000000000006002000000000000000000000000000000000000000000000000000000000000600300000000000000000000000000000000000000000000000000000000000060040000000000000000000000000000000000000000000000000000000000006005000000000000000000000000000000000000000000000000000000000000600600000000000000000000000000000000000000000000000000000000000060070000000000000000000000000000000000000000000000000000000000006008000000000000000000000000000000000000000000000000000000000000600900000000000000000000000000000000000000000000000000000000000060800000000000000000000000000000000000000000000000000000000000006081000000000000000000000000000000000000000000000000000000000000608200000000000000000000000000000000000000000000000000000000000060830000000000000000000000000000000000000000000000000000000000006084000000000000000000000000000000000000000000000000000000000000608500000000000000000000000000000000000000000000000000000000000060860000000000000000000000000000000000000000000000000000000000006087000000000000000000000000000000000000000000000000000000000000608800000000000000000000000000000000000000000000000000000000000060890000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000610100000000000000000000000000000000000000000000000000000000000061020000000000000000000000000000000000000000000000000000000000006103000000000000000000000000000000000000000000000000000000000000610400000000000000000000000000000000000000000000000000000000000061050000000000000000000000000000000000000000000000000000000000006106000000000000000000000000000000000000000000000000000000000000610700000000000000000000000000000000000000000000000000000000000061080000000000000000000000000000000000000000000000000000000000006109000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070010000000000000000000000000000000000000000000000000000000000007002000000000000000000000000000000000000000000000000000000000000700300000000000000000000000000000000000000000000000000000000000070040000000000000000000000000000000000000000000000000000000000007005000000000000000000000000000000000000000000000000000000000000700600000000000000000000000000000000000000000000000000000000000070070000000000000000000000000000000000000000000000000000000000007008000000000000000000000000000000000000000000000000000000000000700900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b6040516200140d3803806200140d83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191905050845160008190555084600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000d29291906200015f565b508260048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160068190555080600990805190602001906200013a92919062000210565b5083600890805190602001906200015392919062000210565b505050505050620002f3565b82805482825590600052602060002090600f01601090048101928215620001fd5791602002820160005b83821115620001cb57835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030262000189565b8015620001fb5782816101000a81549061ffff0219169055600201602081600101049283019260010302620001cb565b505b5090506200020c919062000297565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025357805160ff191683800117855562000284565b8280016001018555821562000284579182015b828111156200028357825182559160200191906001019062000266565b5b509050620002939190620002cb565b5090565b620002c891905b80821115620002c457600081816101000a81549061ffff0219169055506001016200029e565b5090565b90565b620002f091905b80821115620002ec576000816000905550600101620002d2565b5090565b90565b61110a80620003036000396000f3006060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100ca5780630e1c2d461461015857806318160ddd146101b2578063313ce567146101db57806370a082311461020a57806372c5cb631461029857806395d89b41146102c1578063a6fb475f1461034f578063c2bf17b0146103e7578063db0ec96814610495578063ea8b5ca31461050e578063f0141d841461053b575b34156100c557600080fd5b600080fd5b34156100d557600080fd5b6100dd610564565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561011d578082015181840152602081019050610102565b50505050905090810190601f16801561014a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61019860048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061060c565b604051808215151515815260200191505060405180910390f35b34156101bd57600080fd5b6101c5610799565b6040518082815260200191505060405180910390f35b34156101e657600080fd5b6101ee6107a2565b604051808260ff1660ff16815260200191505060405180910390f35b341561021557600080fd5b610241600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506107a7565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610284578082015181840152602081019050610269565b505050509050019250505060405180910390f35b34156102a357600080fd5b6102ab61086c565b6040518082815260200191505060405180910390f35b34156102cc57600080fd5b6102d4610876565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103145780820151818401526020810190506102f9565b50505050905090810190601f1680156103415780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561035a57600080fd5b6103e5600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061091e565b005b34156103f257600080fd5b61043260048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610c15565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156104a057600080fd5b61050c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610d89565b005b341561051957600080fd5b61052161102f565b604051808215151515815260200191505060405180910390f35b341561054657600080fd5b61054e61104c565b6040518082815260200191505060405180910390f35b61056c611057565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106025780601f106105d757610100808354040283529160200191610602565b820191906000526020600020905b8154815290600101906020018083116105e557829003601f168201915b5050505050905090565b6000806000806000806000806106248c8c8c8c610c15565b96509650965096508561ffff168502925083801561064157508234145b15610785576006543481151561065357fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561069b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f1935050505015156106fd57600080fd5b60076000815480929190600101919050555085600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff1602179055506001975061078a565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b6107af61106b565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561086057602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116108275790505b50505050509050919050565b6000600754905090565b61087e611057565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109145780601f106108e957610100808354040283529160200191610914565b820191906000526020600020905b8154815290600101906020018083116108f757829003601f168201915b5050505050905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561097c57600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905010156109cc57600080fd5b600090505b8151811015610ba157600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610a2b919061107f565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610a8f57fe5b9060200190602002015161ffff16815481101515610aa957fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610b3957fe5b9060200190602002015161ffff16815481101515610b5357fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060076000815480929190600101919050555080806001019150506109d1565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555050505050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610cc457600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff16600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050031015610d795760009050610d7e565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ddb57600080fd5b600090505b81518161ffff161015610fbc57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610e3e919061107f565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff16815181101515610ea657fe5b9060200190602002015161ffff16815481101515610ec057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff16815181101515610f5457fe5b9060200190602002015161ffff16815481101515610f6e57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610de0565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550505050565b60006004544211156110445760019050611049565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b8154818355818115116110b457600f016010900481600f016010900483600052602060002091820191016110b391906110b9565b5b505050565b6110db91905b808211156110d75760008160009055506001016110bf565b5090565b905600a165627a7a72305820edfba7b75aafb1845e5a8e62910bcf04a3dd20bd79e6e310ea3bb875fa4862af002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000002660000000000000000000000000000000000000000000000000000000000000012b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000105000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000001070000000000000000000000000000000000000000000000000000000000000108000000000000000000000000000000000000000000000000000000000000010900000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000000010030000000000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000000000000000000000000000100500000000000000000000000000000000000000000000000000000000000010060000000000000000000000000000000000000000000000000000000000001007000000000000000000000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000010090000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000108100000000000000000000000000000000000000000000000000000000000010820000000000000000000000000000000000000000000000000000000000001083000000000000000000000000000000000000000000000000000000000000108400000000000000000000000000000000000000000000000000000000000010850000000000000000000000000000000000000000000000000000000000001086000000000000000000000000000000000000000000000000000000000000108700000000000000000000000000000000000000000000000000000000000010880000000000000000000000000000000000000000000000000000000000001089000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000011010000000000000000000000000000000000000000000000000000000000001102000000000000000000000000000000000000000000000000000000000000110300000000000000000000000000000000000000000000000000000000000011040000000000000000000000000000000000000000000000000000000000001105000000000000000000000000000000000000000000000000000000000000110600000000000000000000000000000000000000000000000000000000000011070000000000000000000000000000000000000000000000000000000000001108000000000000000000000000000000000000000000000000000000000000110900000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000000000000000000000000000000000000000000200200000000000000000000000000000000000000000000000000000000000020030000000000000000000000000000000000000000000000000000000000002004000000000000000000000000000000000000000000000000000000000000200500000000000000000000000000000000000000000000000000000000000020060000000000000000000000000000000000000000000000000000000000002007000000000000000000000000000000000000000000000000000000000000200800000000000000000000000000000000000000000000000000000000000020090000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000208100000000000000000000000000000000000000000000000000000000000020820000000000000000000000000000000000000000000000000000000000002083000000000000000000000000000000000000000000000000000000000000208400000000000000000000000000000000000000000000000000000000000020850000000000000000000000000000000000000000000000000000000000002086000000000000000000000000000000000000000000000000000000000000208700000000000000000000000000000000000000000000000000000000000020880000000000000000000000000000000000000000000000000000000000002089000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021010000000000000000000000000000000000000000000000000000000000002102000000000000000000000000000000000000000000000000000000000000210300000000000000000000000000000000000000000000000000000000000021040000000000000000000000000000000000000000000000000000000000002105000000000000000000000000000000000000000000000000000000000000210600000000000000000000000000000000000000000000000000000000000021070000000000000000000000000000000000000000000000000000000000002108000000000000000000000000000000000000000000000000000000000000210900000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003001000000000000000000000000000000000000000000000000000000000000300200000000000000000000000000000000000000000000000000000000000030030000000000000000000000000000000000000000000000000000000000003004000000000000000000000000000000000000000000000000000000000000300500000000000000000000000000000000000000000000000000000000000030060000000000000000000000000000000000000000000000000000000000003007000000000000000000000000000000000000000000000000000000000000300800000000000000000000000000000000000000000000000000000000000030090000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000308100000000000000000000000000000000000000000000000000000000000030820000000000000000000000000000000000000000000000000000000000003083000000000000000000000000000000000000000000000000000000000000308400000000000000000000000000000000000000000000000000000000000030850000000000000000000000000000000000000000000000000000000000003086000000000000000000000000000000000000000000000000000000000000308700000000000000000000000000000000000000000000000000000000000030880000000000000000000000000000000000000000000000000000000000003089000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031010000000000000000000000000000000000000000000000000000000000003102000000000000000000000000000000000000000000000000000000000000310300000000000000000000000000000000000000000000000000000000000031040000000000000000000000000000000000000000000000000000000000003105000000000000000000000000000000000000000000000000000000000000310600000000000000000000000000000000000000000000000000000000000031070000000000000000000000000000000000000000000000000000000000003108000000000000000000000000000000000000000000000000000000000000310900000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004001000000000000000000000000000000000000000000000000000000000000400200000000000000000000000000000000000000000000000000000000000040030000000000000000000000000000000000000000000000000000000000004004000000000000000000000000000000000000000000000000000000000000400500000000000000000000000000000000000000000000000000000000000040060000000000000000000000000000000000000000000000000000000000004007000000000000000000000000000000000000000000000000000000000000400800000000000000000000000000000000000000000000000000000000000040090000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000408100000000000000000000000000000000000000000000000000000000000040820000000000000000000000000000000000000000000000000000000000004083000000000000000000000000000000000000000000000000000000000000408400000000000000000000000000000000000000000000000000000000000040850000000000000000000000000000000000000000000000000000000000004086000000000000000000000000000000000000000000000000000000000000408700000000000000000000000000000000000000000000000000000000000040880000000000000000000000000000000000000000000000000000000000004089000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004102000000000000000000000000000000000000000000000000000000000000410300000000000000000000000000000000000000000000000000000000000041040000000000000000000000000000000000000000000000000000000000004105000000000000000000000000000000000000000000000000000000000000410600000000000000000000000000000000000000000000000000000000000041070000000000000000000000000000000000000000000000000000000000004108000000000000000000000000000000000000000000000000000000000000410900000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005001000000000000000000000000000000000000000000000000000000000000500200000000000000000000000000000000000000000000000000000000000050030000000000000000000000000000000000000000000000000000000000005004000000000000000000000000000000000000000000000000000000000000500500000000000000000000000000000000000000000000000000000000000050060000000000000000000000000000000000000000000000000000000000005007000000000000000000000000000000000000000000000000000000000000500800000000000000000000000000000000000000000000000000000000000050090000000000000000000000000000000000000000000000000000000000005080000000000000000000000000000000000000000000000000000000000000508100000000000000000000000000000000000000000000000000000000000050820000000000000000000000000000000000000000000000000000000000005083000000000000000000000000000000000000000000000000000000000000508400000000000000000000000000000000000000000000000000000000000050850000000000000000000000000000000000000000000000000000000000005086000000000000000000000000000000000000000000000000000000000000508700000000000000000000000000000000000000000000000000000000000050880000000000000000000000000000000000000000000000000000000000005089000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000051010000000000000000000000000000000000000000000000000000000000005102000000000000000000000000000000000000000000000000000000000000510300000000000000000000000000000000000000000000000000000000000051040000000000000000000000000000000000000000000000000000000000005105000000000000000000000000000000000000000000000000000000000000510600000000000000000000000000000000000000000000000000000000000051070000000000000000000000000000000000000000000000000000000000005108000000000000000000000000000000000000000000000000000000000000510900000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006001000000000000000000000000000000000000000000000000000000000000600200000000000000000000000000000000000000000000000000000000000060030000000000000000000000000000000000000000000000000000000000006004000000000000000000000000000000000000000000000000000000000000600500000000000000000000000000000000000000000000000000000000000060060000000000000000000000000000000000000000000000000000000000006007000000000000000000000000000000000000000000000000000000000000600800000000000000000000000000000000000000000000000000000000000060090000000000000000000000000000000000000000000000000000000000006080000000000000000000000000000000000000000000000000000000000000608100000000000000000000000000000000000000000000000000000000000060820000000000000000000000000000000000000000000000000000000000006083000000000000000000000000000000000000000000000000000000000000608400000000000000000000000000000000000000000000000000000000000060850000000000000000000000000000000000000000000000000000000000006086000000000000000000000000000000000000000000000000000000000000608700000000000000000000000000000000000000000000000000000000000060880000000000000000000000000000000000000000000000000000000000006089000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061010000000000000000000000000000000000000000000000000000000000006102000000000000000000000000000000000000000000000000000000000000610300000000000000000000000000000000000000000000000000000000000061040000000000000000000000000000000000000000000000000000000000006105000000000000000000000000000000000000000000000000000000000000610600000000000000000000000000000000000000000000000000000000000061070000000000000000000000000000000000000000000000000000000000006108000000000000000000000000000000000000000000000000000000000000610900000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007001000000000000000000000000000000000000000000000000000000000000700200000000000000000000000000000000000000000000000000000000000070030000000000000000000000000000000000000000000000000000000000007004000000000000000000000000000000000000000000000000000000000000700500000000000000000000000000000000000000000000000000000000000070060000000000000000000000000000000000000000000000000000000000007007000000000000000000000000000000000000000000000000000000000000700800000000000000000000000000000000000000000000000000000000000070090000000000000000000000000000000000000000000000000000000000007080000000000000000000000000000000000000000000000000000000000000708100000000000000000000000000000000000000000000000000000000000070820000000000000000000000000000000000000000000000000000000000007083000000000000000000000000000000000000000000000000000000000000708400000000000000000000000000000000000000000000000000000000000070850000000000000000000000000000000000000000000000000000000000007086000000000000000000000000000000000000000000000000000000000000708700000000000000000000000000000000000000000000000000000000000070880000000000000000000000000000000000000000000000000000000000007089000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071010000000000000000000000000000000000000000000000000000000000007102000000000000000000000000000000000000000000000000000000000000710300000000000000000000000000000000000000000000000000000000000071040000000000000000000000000000000000000000000000000000000000007105000000000000000000000000000000000000000000000000000000000000710600000000000000000000000000000000000000000000000000000000000071070000000000000000000000000000000000000000000000000000000000007108000000000000000000000000000000000000000000000000000000000000710900000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000800200000000000000000000000000000000000000000000000000000000000080030000000000000000000000000000000000000000000000000000000000008004000000000000000000000000000000000000000000000000000000000000800500000000000000000000000000000000000000000000000000000000000080060000000000000000000000000000000000000000000000000000000000008007000000000000000000000000000000000000000000000000000000000000800800000000000000000000000000000000000000000000000000000000000080090000000000000000000000000000000000000000000000000000000000008080000000000000000000000000000000000000000000000000000000000000808100000000000000000000000000000000000000000000000000000000000080820000000000000000000000000000000000000000000000000000000000008083000000000000000000000000000000000000000000000000000000000000808400000000000000000000000000000000000000000000000000000000000080850000000000000000000000000000000000000000000000000000000000008086000000000000000000000000000000000000000000000000000000000000808700000000000000000000000000000000000000000000000000000000000080880000000000000000000000000000000000000000000000000000000000008089000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008102000000000000000000000000000000000000000000000000000000000000810300000000000000000000000000000000000000000000000000000000000081040000000000000000000000000000000000000000000000000000000000008105000000000000000000000000000000000000000000000000000000000000810600000000000000000000000000000000000000000000000000000000000081070000000000000000000000000000000000000000000000000000000000008108000000000000000000000000000000000000000000000000000000000000810900000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009001000000000000000000000000000000000000000000000000000000000000900200000000000000000000000000000000000000000000000000000000000090030000000000000000000000000000000000000000000000000000000000009004000000000000000000000000000000000000000000000000000000000000900500000000000000000000000000000000000000000000000000000000000090060000000000000000000000000000000000000000000000000000000000009007000000000000000000000000000000000000000000000000000000000000900800000000000000000000000000000000000000000000000000000000000090090000000000000000000000000000000000000000000000000000000000009080000000000000000000000000000000000000000000000000000000000000908100000000000000000000000000000000000000000000000000000000000090820000000000000000000000000000000000000000000000000000000000009083000000000000000000000000000000000000000000000000000000000000908400000000000000000000000000000000000000000000000000000000000090850000000000000000000000000000000000000000000000000000000000009086000000000000000000000000000000000000000000000000000000000000908700000000000000000000000000000000000000000000000000000000000090880000000000000000000000000000000000000000000000000000000000009089000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000091010000000000000000000000000000000000000000000000000000000000009102000000000000000000000000000000000000000000000000000000000000910300000000000000000000000000000000000000000000000000000000000091040000000000000000000000000000000000000000000000000000000000009105000000000000000000000000000000000000000000000000000000000000910600000000000000000000000000000000000000000000000000000000000091070000000000000000000000000000000000000000000000000000000000009108000000000000000000000000000000000000000000000000000000000000910900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001b7a38038062001b7a8339810160405280805182019190602001805182019190602001805190602001909190805182019190505083516000819055508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620001529291906200018f565b5080600990805190602001906200016b92919062000240565b5082600890805190602001906200018492919062000240565b505050505062000323565b82805482825590600052602060002090600f016010900481019282156200022d5791602002820160005b83821115620001fb57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001b9565b80156200022b5782816101000a81549061ffff0219169055600201602081600101049283019260010302620001fb565b505b5090506200023c9190620002c7565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200028357805160ff1916838001178555620002b4565b82800160010185558215620002b4579182015b82811115620002b357825182559160200191906001019062000296565b5b509050620002c39190620002fb565b5090565b620002f891905b80821115620002f457600081816101000a81549061ffff021916905550600101620002ce565b5090565b90565b6200032091905b808211156200031c57600081600090555060010162000302565b5090565b90565b61184780620003336000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063696ecc551461022a57806370a08231146102a857806372c5cb631461033657806395d89b411461035f578063a6fb475f146103ed578063bb6e7de914610485578063c2532c3d1461049a578063c9116b6914610539578063db0ec968146105a3578063ea8b5ca31461061c578063f0141d8414610649575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b6102a660048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610730565b005b34156102b357600080fd5b6102df600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a5d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610322578082015181840152602081019050610307565b505050509050019250505060405180910390f35b341561034157600080fd5b610349610b22565b6040518082815260200191505060405180910390f35b341561036a57600080fd5b610372610b2c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103b2578082015181840152602081019050610397565b50505050905090810190601f1680156103df5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103f857600080fd5b610483600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bd4565b005b341561049057600080fd5b610498610ec6565b005b34156104a557600080fd5b61053760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f5c565b005b341561054457600080fd5b61054c611133565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058f578082015181840152602081019050610574565b505050509050019250505060405180910390f35b34156105ae57600080fd5b61061a600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506111f6565b005b341561062757600080fd5b61062f61142d565b604051808215151515815260200191505060405180910390f35b341561065457600080fd5b61065c61144a565b6040518082815260200191505060405180910390f35b61067a611780565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b600080600080428911806107445750600089145b151561074f57600080fd5b61075a348a8a611455565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107da57600080fd5b5050602060405103519250600091505b8751821015610a1257878281518110151561080157fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561085f57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff1611151561089357600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108e49190611794565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561094757fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109d657fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506107ea565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a5257600080fd5b505050505050505050565b610a656117ce565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b1657602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610add5790505b50505050509050919050565b6000600754905090565b610b34611780565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bca5780601f10610b9f57610100808354040283529160200191610bca565b820191906000526020600020905b815481529060010190602001808311610bad57829003601f168201915b5050505050905090565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c3557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610ebe576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610ce457fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff16141580610d165750825b1515610d2157600080fd5b8382815181101515610d2f57fe5b9060200190602002015161ffff169050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d909190611794565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610df357fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e8257fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055508180600101925050610c8d565b505050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f5757600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f6d6000808a611455565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561100a57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561107157600080fd5b600090505b875181101561112957600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110d09190611794565b91600052602060002090601091828204019190066002028a848151811015156110f557fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff160217905550508080600101915050611076565b5050505050505050565b61113b6117ce565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156111ec57602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116111b35790505b5050505050905090565b600080600091505b8251821015611427576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110151561125557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161415151561128a57600080fd5b828281518110151561129857fe5b9060200190602002015161ffff169050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112f99190611794565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561135c57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113eb57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506111fe565b50505050565b60006003544211156114425760019050611447565b600090505b90565b60008060ff16905090565b600061145f6117e2565b60008060028551026054016040518059106114775750595b9080825280601f01601f1916602001820160405250925061149661071f565b9150600090505b60208110156114fe5780600802879060020a0260010283828151811015156114c157fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061149d565b600090505b60208110156115675780600802869060020a02600102836020830181518110151561152a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611503565b600090505b60148110156115eb5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115ae57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061156c565b600090505b8451811015611711576008858281518110151561160957fe5b9060200190602002015161ffff169060020a90047f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561165357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561169157fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116d457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506115f0565b826040518082805190602001908083835b6020831015156117475780518252602082019150602081019050602083039250611722565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117c957600f016010900481600f016010900483600052602060002091820191016117c891906117f6565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61181891905b808211156118145760008160009055506001016117fc565b5090565b905600a165627a7a7230582049fa84125e0a02ef1e55f288a7d02a3c951d7ad01e5191aaaaec5185e204c52c0029000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000870000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000000000000000000000000000000000104000000000000000000000000000000000000000000000000000000000000010500000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000107000000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001090000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000010020000000000000000000000000000000000000000000000000000000000001003000000000000000000000000000000000000000000000000000000000000100400000000000000000000000000000000000000000000000000000000000010050000000000000000000000000000000000000000000000000000000000001006000000000000000000000000000000000000000000000000000000000000100700000000000000000000000000000000000000000000000000000000000010080000000000000000000000000000000000000000000000000000000000001009000000000000000000000000000000000000000000000000000000000000000f486f6c69646179206f6e204d6172730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001ba938038062001ba98339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b508160099080519060200190620001999291906200026f565b508360089080519060200190620001b29291906200026f565b50505050505062000352565b82805482825590600052602060002090600f016010900481019282156200025c5791602002820160005b838211156200022a57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025a5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022a565b505b5090506200026b9190620002f6565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b257805160ff1916838001178555620002e3565b82800160010185558215620002e3579182015b82811115620002e2578251825591602001919060010190620002c5565b5b509050620002f291906200032a565b5090565b6200032791905b808211156200032357600081816101000a81549061ffff021916905550600101620002fd565b5090565b90565b6200034f91905b808211156200034b57600081600090555060010162000331565b5090565b90565b61184780620003626000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063696ecc551461022a57806370a08231146102a857806372c5cb631461033657806395d89b411461035f578063a6fb475f146103ed578063bb6e7de914610485578063c2532c3d1461049a578063c9116b6914610539578063db0ec968146105a3578063ea8b5ca31461061c578063f0141d8414610649575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b6102a660048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610730565b005b34156102b357600080fd5b6102df600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a5d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610322578082015181840152602081019050610307565b505050509050019250505060405180910390f35b341561034157600080fd5b610349610b22565b6040518082815260200191505060405180910390f35b341561036a57600080fd5b610372610b2c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103b2578082015181840152602081019050610397565b50505050905090810190601f1680156103df5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103f857600080fd5b610483600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bd4565b005b341561049057600080fd5b610498610ec6565b005b34156104a557600080fd5b61053760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f5c565b005b341561054457600080fd5b61054c611133565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058f578082015181840152602081019050610574565b505050509050019250505060405180910390f35b34156105ae57600080fd5b61061a600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506111f6565b005b341561062757600080fd5b61062f61142d565b604051808215151515815260200191505060405180910390f35b341561065457600080fd5b61065c61144a565b6040518082815260200191505060405180910390f35b61067a611780565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b600080600080428911806107445750600089145b151561074f57600080fd5b61075a348a8a611455565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107da57600080fd5b5050602060405103519250600091505b8751821015610a1257878281518110151561080157fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561085f57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff1611151561089357600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108e49190611794565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561094757fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109d657fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506107ea565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a5257600080fd5b505050505050505050565b610a656117ce565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b1657602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610add5790505b50505050509050919050565b6000600754905090565b610b34611780565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bca5780601f10610b9f57610100808354040283529160200191610bca565b820191906000526020600020905b815481529060010190602001808311610bad57829003601f168201915b5050505050905090565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c3557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610ebe576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610ce457fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff16141580610d165750825b1515610d2157600080fd5b8382815181101515610d2f57fe5b9060200190602002015161ffff169050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d909190611794565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610df357fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e8257fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055508180600101925050610c8d565b505050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f5757600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f6d6000808a611455565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561100a57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561107157600080fd5b600090505b875181101561112957600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110d09190611794565b91600052602060002090601091828204019190066002028a848151811015156110f557fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff160217905550508080600101915050611076565b5050505050505050565b61113b6117ce565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156111ec57602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116111b35790505b5050505050905090565b600080600091505b8251821015611427576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110151561125557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161415151561128a57600080fd5b828281518110151561129857fe5b9060200190602002015161ffff169050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112f99190611794565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561135c57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113eb57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506111fe565b50505050565b60006003544211156114425760019050611447565b600090505b90565b60008060ff16905090565b600061145f6117e2565b60008060028551026054016040518059106114775750595b9080825280601f01601f1916602001820160405250925061149661071f565b9150600090505b60208110156114fe5780600802879060020a0260010283828151811015156114c157fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061149d565b600090505b60208110156115675780600802869060020a02600102836020830181518110151561152a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611503565b600090505b60148110156115eb5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115ae57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061156c565b600090505b8451811015611711576008858281518110151561160957fe5b9060200190602002015161ffff169060020a90047f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561165357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561169157fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116d457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506115f0565b826040518082805190602001908083835b6020831015156117475780518252602082019150602081019050602083039250611722565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117c957600f016010900481600f016010900483600052602060002091820191016117c891906117f6565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61181891905b808211156118145760008160009055506001016117fc565b5090565b905600a165627a7a723058200792fad5c6263ca3e1d02094e7ae8f2684173dcd7d922a4217a7c654c8637dd5002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000015a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000000174170706c79696e6720666f72206d6f7274676167657332000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a7230582028821fcbcd9925cc4ac65c63aae47bd4e30af5cd3f4a37341253d92a6c665177002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000015900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000000174170706c79696e6720666f72206d6f7274676167657332000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a7230582028821fcbcd9925cc4ac65c63aae47bd4e30af5cd3f4a37341253d92a6c665177002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000015900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000000174170706c79696e6720666f72206d6f7274676167657332000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a7230582028821fcbcd9925cc4ac65c63aae47bd4e30af5cd3f4a37341253d92a6c665177002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000000174170706c79696e6720666f72206d6f7274676167657332000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c" - ,"0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c" - ,"0x" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a723058208a216750119a8c106cd7e3839e451f787900b989fd7fee9e3e5ce3f4086e2bc1002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000002640000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000002680000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000012c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000105000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000001070000000000000000000000000000000000000000000000000000000000000108000000000000000000000000000000000000000000000000000000000000010900000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000000010030000000000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000000000000000000000000000100500000000000000000000000000000000000000000000000000000000000010060000000000000000000000000000000000000000000000000000000000001007000000000000000000000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000010090000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000108100000000000000000000000000000000000000000000000000000000000010820000000000000000000000000000000000000000000000000000000000001083000000000000000000000000000000000000000000000000000000000000108400000000000000000000000000000000000000000000000000000000000010850000000000000000000000000000000000000000000000000000000000001086000000000000000000000000000000000000000000000000000000000000108700000000000000000000000000000000000000000000000000000000000010880000000000000000000000000000000000000000000000000000000000001089000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000011010000000000000000000000000000000000000000000000000000000000001102000000000000000000000000000000000000000000000000000000000000110300000000000000000000000000000000000000000000000000000000000011040000000000000000000000000000000000000000000000000000000000001105000000000000000000000000000000000000000000000000000000000000110600000000000000000000000000000000000000000000000000000000000011070000000000000000000000000000000000000000000000000000000000001108000000000000000000000000000000000000000000000000000000000000110900000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000000000000000000000000000000000000000000200200000000000000000000000000000000000000000000000000000000000020030000000000000000000000000000000000000000000000000000000000002004000000000000000000000000000000000000000000000000000000000000200500000000000000000000000000000000000000000000000000000000000020060000000000000000000000000000000000000000000000000000000000002007000000000000000000000000000000000000000000000000000000000000200800000000000000000000000000000000000000000000000000000000000020090000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000208100000000000000000000000000000000000000000000000000000000000020820000000000000000000000000000000000000000000000000000000000002083000000000000000000000000000000000000000000000000000000000000208400000000000000000000000000000000000000000000000000000000000020850000000000000000000000000000000000000000000000000000000000002086000000000000000000000000000000000000000000000000000000000000208700000000000000000000000000000000000000000000000000000000000020880000000000000000000000000000000000000000000000000000000000002089000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021010000000000000000000000000000000000000000000000000000000000002102000000000000000000000000000000000000000000000000000000000000210300000000000000000000000000000000000000000000000000000000000021040000000000000000000000000000000000000000000000000000000000002105000000000000000000000000000000000000000000000000000000000000210600000000000000000000000000000000000000000000000000000000000021070000000000000000000000000000000000000000000000000000000000002108000000000000000000000000000000000000000000000000000000000000210900000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003001000000000000000000000000000000000000000000000000000000000000300200000000000000000000000000000000000000000000000000000000000030030000000000000000000000000000000000000000000000000000000000003004000000000000000000000000000000000000000000000000000000000000300500000000000000000000000000000000000000000000000000000000000030060000000000000000000000000000000000000000000000000000000000003007000000000000000000000000000000000000000000000000000000000000300800000000000000000000000000000000000000000000000000000000000030090000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000308100000000000000000000000000000000000000000000000000000000000030820000000000000000000000000000000000000000000000000000000000003083000000000000000000000000000000000000000000000000000000000000308400000000000000000000000000000000000000000000000000000000000030850000000000000000000000000000000000000000000000000000000000003086000000000000000000000000000000000000000000000000000000000000308700000000000000000000000000000000000000000000000000000000000030880000000000000000000000000000000000000000000000000000000000003089000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031010000000000000000000000000000000000000000000000000000000000003102000000000000000000000000000000000000000000000000000000000000310300000000000000000000000000000000000000000000000000000000000031040000000000000000000000000000000000000000000000000000000000003105000000000000000000000000000000000000000000000000000000000000310600000000000000000000000000000000000000000000000000000000000031070000000000000000000000000000000000000000000000000000000000003108000000000000000000000000000000000000000000000000000000000000310900000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004001000000000000000000000000000000000000000000000000000000000000400200000000000000000000000000000000000000000000000000000000000040030000000000000000000000000000000000000000000000000000000000004004000000000000000000000000000000000000000000000000000000000000400500000000000000000000000000000000000000000000000000000000000040060000000000000000000000000000000000000000000000000000000000004007000000000000000000000000000000000000000000000000000000000000400800000000000000000000000000000000000000000000000000000000000040090000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000408100000000000000000000000000000000000000000000000000000000000040820000000000000000000000000000000000000000000000000000000000004083000000000000000000000000000000000000000000000000000000000000408400000000000000000000000000000000000000000000000000000000000040850000000000000000000000000000000000000000000000000000000000004086000000000000000000000000000000000000000000000000000000000000408700000000000000000000000000000000000000000000000000000000000040880000000000000000000000000000000000000000000000000000000000004089000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004102000000000000000000000000000000000000000000000000000000000000410300000000000000000000000000000000000000000000000000000000000041040000000000000000000000000000000000000000000000000000000000004105000000000000000000000000000000000000000000000000000000000000410600000000000000000000000000000000000000000000000000000000000041070000000000000000000000000000000000000000000000000000000000004108000000000000000000000000000000000000000000000000000000000000410900000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005001000000000000000000000000000000000000000000000000000000000000500200000000000000000000000000000000000000000000000000000000000050030000000000000000000000000000000000000000000000000000000000005004000000000000000000000000000000000000000000000000000000000000500500000000000000000000000000000000000000000000000000000000000050060000000000000000000000000000000000000000000000000000000000005007000000000000000000000000000000000000000000000000000000000000500800000000000000000000000000000000000000000000000000000000000050090000000000000000000000000000000000000000000000000000000000005080000000000000000000000000000000000000000000000000000000000000508100000000000000000000000000000000000000000000000000000000000050820000000000000000000000000000000000000000000000000000000000005083000000000000000000000000000000000000000000000000000000000000508400000000000000000000000000000000000000000000000000000000000050850000000000000000000000000000000000000000000000000000000000005086000000000000000000000000000000000000000000000000000000000000508700000000000000000000000000000000000000000000000000000000000050880000000000000000000000000000000000000000000000000000000000005089000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000051010000000000000000000000000000000000000000000000000000000000005102000000000000000000000000000000000000000000000000000000000000510300000000000000000000000000000000000000000000000000000000000051040000000000000000000000000000000000000000000000000000000000005105000000000000000000000000000000000000000000000000000000000000510600000000000000000000000000000000000000000000000000000000000051070000000000000000000000000000000000000000000000000000000000005108000000000000000000000000000000000000000000000000000000000000510900000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006001000000000000000000000000000000000000000000000000000000000000600200000000000000000000000000000000000000000000000000000000000060030000000000000000000000000000000000000000000000000000000000006004000000000000000000000000000000000000000000000000000000000000600500000000000000000000000000000000000000000000000000000000000060060000000000000000000000000000000000000000000000000000000000006007000000000000000000000000000000000000000000000000000000000000600800000000000000000000000000000000000000000000000000000000000060090000000000000000000000000000000000000000000000000000000000006080000000000000000000000000000000000000000000000000000000000000608100000000000000000000000000000000000000000000000000000000000060820000000000000000000000000000000000000000000000000000000000006083000000000000000000000000000000000000000000000000000000000000608400000000000000000000000000000000000000000000000000000000000060850000000000000000000000000000000000000000000000000000000000006086000000000000000000000000000000000000000000000000000000000000608700000000000000000000000000000000000000000000000000000000000060880000000000000000000000000000000000000000000000000000000000006089000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061010000000000000000000000000000000000000000000000000000000000006102000000000000000000000000000000000000000000000000000000000000610300000000000000000000000000000000000000000000000000000000000061040000000000000000000000000000000000000000000000000000000000006105000000000000000000000000000000000000000000000000000000000000610600000000000000000000000000000000000000000000000000000000000061070000000000000000000000000000000000000000000000000000000000006108000000000000000000000000000000000000000000000000000000000000610900000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007001000000000000000000000000000000000000000000000000000000000000700200000000000000000000000000000000000000000000000000000000000070030000000000000000000000000000000000000000000000000000000000007004000000000000000000000000000000000000000000000000000000000000700500000000000000000000000000000000000000000000000000000000000070060000000000000000000000000000000000000000000000000000000000007007000000000000000000000000000000000000000000000000000000000000700800000000000000000000000000000000000000000000000000000000000070090000000000000000000000000000000000000000000000000000000000007080000000000000000000000000000000000000000000000000000000000000708100000000000000000000000000000000000000000000000000000000000070820000000000000000000000000000000000000000000000000000000000007083000000000000000000000000000000000000000000000000000000000000708400000000000000000000000000000000000000000000000000000000000070850000000000000000000000000000000000000000000000000000000000007086000000000000000000000000000000000000000000000000000000000000708700000000000000000000000000000000000000000000000000000000000070880000000000000000000000000000000000000000000000000000000000007089000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071010000000000000000000000000000000000000000000000000000000000007102000000000000000000000000000000000000000000000000000000000000710300000000000000000000000000000000000000000000000000000000000071040000000000000000000000000000000000000000000000000000000000007105000000000000000000000000000000000000000000000000000000000000710600000000000000000000000000000000000000000000000000000000000071070000000000000000000000000000000000000000000000000000000000007108000000000000000000000000000000000000000000000000000000000000710900000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000800200000000000000000000000000000000000000000000000000000000000080030000000000000000000000000000000000000000000000000000000000008004000000000000000000000000000000000000000000000000000000000000800500000000000000000000000000000000000000000000000000000000000080060000000000000000000000000000000000000000000000000000000000008007000000000000000000000000000000000000000000000000000000000000800800000000000000000000000000000000000000000000000000000000000080090000000000000000000000000000000000000000000000000000000000008080000000000000000000000000000000000000000000000000000000000000808100000000000000000000000000000000000000000000000000000000000080820000000000000000000000000000000000000000000000000000000000008083000000000000000000000000000000000000000000000000000000000000808400000000000000000000000000000000000000000000000000000000000080850000000000000000000000000000000000000000000000000000000000008086000000000000000000000000000000000000000000000000000000000000808700000000000000000000000000000000000000000000000000000000000080880000000000000000000000000000000000000000000000000000000000008089000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008102000000000000000000000000000000000000000000000000000000000000810300000000000000000000000000000000000000000000000000000000000081040000000000000000000000000000000000000000000000000000000000008105000000000000000000000000000000000000000000000000000000000000810600000000000000000000000000000000000000000000000000000000000081070000000000000000000000000000000000000000000000000000000000008108000000000000000000000000000000000000000000000000000000000000810900000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009001000000000000000000000000000000000000000000000000000000000000900200000000000000000000000000000000000000000000000000000000000090030000000000000000000000000000000000000000000000000000000000009004000000000000000000000000000000000000000000000000000000000000900500000000000000000000000000000000000000000000000000000000000090060000000000000000000000000000000000000000000000000000000000009007000000000000000000000000000000000000000000000000000000000000900800000000000000000000000000000000000000000000000000000000000090090000000000000000000000000000000000000000000000000000000000009080000000000000000000000000000000000000000000000000000000000000908100000000000000000000000000000000000000000000000000000000000090820000000000000000000000000000000000000000000000000000000000009083000000000000000000000000000000000000000000000000000000000000908400000000000000000000000000000000000000000000000000000000000090850000000000000000000000000000000000000000000000000000000000009086000000000000000000000000000000000000000000000000000000000000908700000000000000000000000000000000000000000000000000000000000090880000000000000000000000000000000000000000000000000000000000009089000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000091010000000000000000000000000000000000000000000000000000000000009102000000000000000000000000000000000000000000000000000000000000910300000000000000000000000000000000000000000000000000000000000091040000000000000000000000000000000000000000000000000000000000009105000000000000000000000000000000000000000000000000000000000000910600000000000000000000000000000000000000000000000000000000000091070000000000000000000000000000000000000000000000000000000000009108000000000000000000000000000000000000000000000000000000000000910900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a723058208a216750119a8c106cd7e3839e451f787900b989fd7fee9e3e5ce3f4086e2bc1002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000002636000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000cad0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000093200000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001b7e38038062001b7e8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61181980620003656000396000f3006060604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100e0578063313ce5671461016e57806332a2c5d01461019d578063516741aa146101f25780635c6491e51461029157806363877ab81461032957806370a08231146103a257806372c5cb631461043057806395d89b4114610459578063bb6e7de9146104e7578063c9116b69146104fc578063ea8b5ca314610566578063f0141d8414610593578063f1aaf147146105bc575b34156100db57600080fd5b600080fd5b34156100eb57600080fd5b6100f361063a565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610133578082015181840152602081019050610118565b50505050905090810190601f1680156101605780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561017957600080fd5b6101816106e2565b604051808260ff1660ff16815260200191505060405180910390f35b34156101a857600080fd5b6101b06106e7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101fd57600080fd5b61028f60048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506106ef565b005b341561029c57600080fd5b610327600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506108c9565b005b341561033457600080fd5b6103a0600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bbd565b005b34156103ad57600080fd5b6103d9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e05565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561041c578082015181840152602081019050610401565b505050509050019250505060405180910390f35b341561043b57600080fd5b610443610ec8565b6040518082815260200191505060405180910390f35b341561046457600080fd5b61046c610ed2565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104ac578082015181840152602081019050610491565b50505050905090810190601f1680156104d95780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156104f257600080fd5b6104fa610f7a565b005b341561050757600080fd5b61050f611010565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610552578082015181840152602081019050610537565b505050509050019250505060405180910390f35b341561057157600080fd5b6105796110d1565b604051808215151515815260200191505060405180910390f35b341561059e57600080fd5b6105a66110ee565b6040518082815260200191505060405180910390f35b61063860048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506110f9565b005b610642611752565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106d85780601f106106ad576101008083540402835291602001916106d8565b820191906000526020600020905b8154815290600101906020018083116106bb57829003601f168201915b5050505050905090565b600081565b600030905090565b60008060006107006000808a611428565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561079d57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561080457600080fd5b600090505b87518110156108bf57600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108639190611766565b91600052602060002090601091828204019190066002028a8481518110151561088857fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff160217905550508080600101915050610809565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561092a57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bb5576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811015156109d957fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a095750825b1515610a1457600080fd5b8382815181101515610a2257fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610a829190611766565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610ae557fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610b7657fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610982565b505050505050565b600080600354421115610bcf57600080fd5b600091505b8251821015610dff576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c2b57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c5e57600080fd5b8282815181101515610c6c57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ccc9190611766565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d2f57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610dc057fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610bd4565b50505050565b610e0d6117a0565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ebc57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610e855790505b50505050509050919050565b6000600754905090565b610eda611752565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f705780601f10610f4557610100808354040283529160200191610f70565b820191906000526020600020905b815481529060010190602001808311610f5357829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561100b57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110186117a0565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156110c757602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110905790505b5050505050905090565b60006003544211156110e657600190506110eb565b600090505b90565b60008060ff16905090565b6000806000804289118061110d5750600089145b151561111857600080fd5b611123348a8a611428565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111a357600080fd5b5050602060405103519250600091505b87518210156113dd5787828151811015156111ca57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561122757fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561125957600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112aa9190611766565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561130d57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561139e57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111b3565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561141d57600080fd5b505050505050505050565b60006114326117b4565b600080600285510260540160405180591061144a5750595b9080825280601f01601f191660200182016040525092506114696106e7565b9150600090505b60208110156114d15780600802879060020a02600102838281518110151561149457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611470565b600090505b602081101561153a5780600802869060020a0260010283602083018151811015156114fd57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114d6565b600090505b60148110156115be5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561158157fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061153f565b600090505b84518110156116e357600885828151811015156115dc57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561162557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561166357fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116a657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506115c3565b826040518082805190602001908083835b60208310151561171957805182526020820191506020810190506020830392506116f4565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b81548183558181151161179b57600f016010900481600f0160109004836000526020600020918201910161179a91906117c8565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b6117ea91905b808211156117e65760008160009055506001016117ce565b5090565b905600a165627a7a72305820dd127bc67ffb3f56951a3ac13502a41674d74e88729115b207f44ce52b0a5978002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000002636000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000cad0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000093200000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" - ,"0x00" - ,"0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007" - ,"0xdb0ec968000000000000000000000000b05a1573146372165c65f3f8ac7340fee7fa88c40000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013" - ,"0x" - ,"0x00" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a" - ,"0xdb0ec968000000000000000000000000699657da752d806a5df9f8a12e25facd1b2215ca0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000017" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc46802090539840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000b" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000013" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc46802090539840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c" - ,"0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001be638038062001be683398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000f9929190620001ca565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550856006819055508260099080519060200190620001619291906200027b565b5087600890805190602001906200017a9291906200027b565b5084600a9080519060200190620001939291906200027b565b5083600b9080519060200190620001ac9291906200027b565b5081600c8190555080600d819055505050505050505050506200035e565b82805482825590600052602060002090600f01601090048101928215620002685791602002820160005b838211156200023657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001f4565b8015620002665782816101000a81549061ffff021916905560020160208160010104928301926001030262000236565b505b50905062000277919062000302565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002be57805160ff1916838001178555620002ef565b82800160010185558215620002ef579182015b82811115620002ee578251825591602001919060010190620002d1565b5b509050620002fe919062000336565b5090565b6200033391905b808211156200032f57600081816101000a81549061ffff02191690555060010162000309565b5090565b90565b6200035b91905b80821115620003575760008160009055506001016200033d565b5090565b90565b611878806200036e6000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd14610228578063313ce56714610251578063323046b1146102805780634bfbe5df1461030e57806370a082311461039c57806372c5cb631461042a57806395d89b4114610453578063a0d8848c146104e1578063a270a7371461050a578063a6fb475f14610598578063ba9a909014610630578063c2bf17b014610664578063db0ec96814610712578063e22bda351461078b578063ea8b5ca314610819578063f0141d8414610846575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086f565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610879565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610921565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610ad3565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b610264610adc565b604051808260ff1660ff16815260200191505060405180910390f35b341561028b57600080fd5b610293610ae1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102d35780820151818401526020810190506102b8565b50505050905090810190601f1680156103005780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561031957600080fd5b610321610b7f565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103a757600080fd5b6103d3600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c27565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104165780820151818401526020810190506103fb565b505050509050019250505060405180910390f35b341561043557600080fd5b61043d610cec565b6040518082815260200191505060405180910390f35b341561045e57600080fd5b610466610cf6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104a657808201518184015260208101905061048b565b50505050905090810190601f1680156104d35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156104ec57600080fd5b6104f4610d9e565b6040518082815260200191505060405180910390f35b341561051557600080fd5b61051d610da8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561055d578082015181840152602081019050610542565b50505050905090810190601f16801561058a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105a357600080fd5b61062e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610e46565b005b61064a600480803561ffff1690602001909190505061113d565b604051808215151515815260200191505060405180910390f35b341561066f57600080fd5b6106af60048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506112db565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b341561071d57600080fd5b610789600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061144f565b005b341561079657600080fd5b61079e6116f5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107de5780820151818401526020810190506107c3565b50505050905090810190601f16801561080b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561082457600080fd5b61082c61179d565b604051808215151515815260200191505060405180910390f35b341561085157600080fd5b6108596117ba565b6040518082815260200191505060405180910390f35b6000600d54905090565b6108816117c5565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109175780601f106108ec57610100808354040283529160200191610917565b820191906000526020600020905b8154815290600101906020018083116108fa57829003601f168201915b5050505050905090565b6000806000806000806000806109398c8c8c8c6112db565b9650965096509650600d54600360009054906101000a900461ffff16870161ffff16111561096657600080fd5b8561ffff168502925083801561097b57508234145b15610abf576006543481151561098d57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109d557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a3757600080fd5b60076000815480929190600101919050555085600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555060019750610ac4565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b775780601f10610b4c57610100808354040283529160200191610b77565b820191906000526020600020905b815481529060010190602001808311610b5a57829003601f168201915b505050505081565b610b876117c5565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c1d5780601f10610bf257610100808354040283529160200191610c1d565b820191906000526020600020905b815481529060010190602001808311610c0057829003601f168201915b5050505050905090565b610c2f6117d9565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610ca75790505b50505050509050919050565b6000600754905090565b610cfe6117c5565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d945780601f10610d6957610100808354040283529160200191610d94565b820191906000526020600020905b815481529060010190602001808311610d7757829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e3e5780601f10610e1357610100808354040283529160200191610e3e565b820191906000526020600020905b815481529060010190602001808311610e2157829003601f168201915b505050505081565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ea457600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ef457600080fd5b600090505b81518110156110c957600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610f5391906117ed565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610fb757fe5b9060200190602002015161ffff16815481101515610fd157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561106157fe5b9060200190602002015161ffff1681548110151561107b57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610ef9565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555050505050565b6000808261ffff16600c54023414158061116c5750600060018461ffff1681151561116457fe5b0661ffff1614155b1561117657600080fd5b600360009054906101000a900461ffff1690505b600360009054906101000a900461ffff16830161ffff168161ffff16101561123f57600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816111fd91906117ed565b916000526020600020906010918282040191900660020283909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061118a565b82600360008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f1935050505015156112d157600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561138a57600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff16600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003101561143f5760009050611444565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905010156114a157600080fd5b600090505b81518161ffff16101561168257600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161150491906117ed565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff1681518110151561156c57fe5b9060200190602002015161ffff1681548110151561158657fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561161a57fe5b9060200190602002015161ffff1681548110151561163457fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060076000815480929190600101919050555080806001019150506114a6565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550505050565b6116fd6117c5565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117935780601f1061176857610100808354040283529160200191611793565b820191906000526020600020905b81548152906001019060200180831161177657829003601f168201915b5050505050905090565b60006004544211156117b257600190506117b7565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b81548183558181151161182257600f016010900481600f016010900483600052602060002091820191016118219190611827565b5b505050565b61184991905b8082111561184557600081600090555060010161182d565b5090565b905600a165627a7a7230582071adaa5e8b36a626e0271897ab2325b900e8063173d8a32e790db3c2e6fdead3002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000011496e74656e7365204c61626f7572696e67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a33302f30322f3230313700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e506173697220526973205061726b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003494e4c0000000000000000000000000000000000000000000000000000000000" - ,"0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001be638038062001be683398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000f9929190620001ca565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550856006819055508260099080519060200190620001619291906200027b565b5087600890805190602001906200017a9291906200027b565b5084600a9080519060200190620001939291906200027b565b5083600b9080519060200190620001ac9291906200027b565b5081600c8190555080600d819055505050505050505050506200035e565b82805482825590600052602060002090600f01601090048101928215620002685791602002820160005b838211156200023657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001f4565b8015620002665782816101000a81549061ffff021916905560020160208160010104928301926001030262000236565b505b50905062000277919062000302565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002be57805160ff1916838001178555620002ef565b82800160010185558215620002ef579182015b82811115620002ee578251825591602001919060010190620002d1565b5b509050620002fe919062000336565b5090565b6200033391905b808211156200032f57600081816101000a81549061ffff02191690555060010162000309565b5090565b90565b6200035b91905b80821115620003575760008160009055506001016200033d565b5090565b90565b611878806200036e6000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd14610228578063313ce56714610251578063323046b1146102805780634bfbe5df1461030e57806370a082311461039c57806372c5cb631461042a57806395d89b4114610453578063a0d8848c146104e1578063a270a7371461050a578063a6fb475f14610598578063ba9a909014610630578063c2bf17b014610664578063db0ec96814610712578063e22bda351461078b578063ea8b5ca314610819578063f0141d8414610846575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086f565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610879565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610921565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610ad3565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b610264610adc565b604051808260ff1660ff16815260200191505060405180910390f35b341561028b57600080fd5b610293610ae1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102d35780820151818401526020810190506102b8565b50505050905090810190601f1680156103005780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561031957600080fd5b610321610b7f565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103a757600080fd5b6103d3600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c27565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104165780820151818401526020810190506103fb565b505050509050019250505060405180910390f35b341561043557600080fd5b61043d610cec565b6040518082815260200191505060405180910390f35b341561045e57600080fd5b610466610cf6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104a657808201518184015260208101905061048b565b50505050905090810190601f1680156104d35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156104ec57600080fd5b6104f4610d9e565b6040518082815260200191505060405180910390f35b341561051557600080fd5b61051d610da8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561055d578082015181840152602081019050610542565b50505050905090810190601f16801561058a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105a357600080fd5b61062e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610e46565b005b61064a600480803561ffff1690602001909190505061113d565b604051808215151515815260200191505060405180910390f35b341561066f57600080fd5b6106af60048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506112db565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b341561071d57600080fd5b610789600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061144f565b005b341561079657600080fd5b61079e6116f5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107de5780820151818401526020810190506107c3565b50505050905090810190601f16801561080b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561082457600080fd5b61082c61179d565b604051808215151515815260200191505060405180910390f35b341561085157600080fd5b6108596117ba565b6040518082815260200191505060405180910390f35b6000600d54905090565b6108816117c5565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109175780601f106108ec57610100808354040283529160200191610917565b820191906000526020600020905b8154815290600101906020018083116108fa57829003601f168201915b5050505050905090565b6000806000806000806000806109398c8c8c8c6112db565b9650965096509650600d54600360009054906101000a900461ffff16870161ffff16111561096657600080fd5b8561ffff168502925083801561097b57508234145b15610abf576006543481151561098d57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109d557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a3757600080fd5b60076000815480929190600101919050555085600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555060019750610ac4565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b775780601f10610b4c57610100808354040283529160200191610b77565b820191906000526020600020905b815481529060010190602001808311610b5a57829003601f168201915b505050505081565b610b876117c5565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c1d5780601f10610bf257610100808354040283529160200191610c1d565b820191906000526020600020905b815481529060010190602001808311610c0057829003601f168201915b5050505050905090565b610c2f6117d9565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610ca75790505b50505050509050919050565b6000600754905090565b610cfe6117c5565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d945780601f10610d6957610100808354040283529160200191610d94565b820191906000526020600020905b815481529060010190602001808311610d7757829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e3e5780601f10610e1357610100808354040283529160200191610e3e565b820191906000526020600020905b815481529060010190602001808311610e2157829003601f168201915b505050505081565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ea457600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ef457600080fd5b600090505b81518110156110c957600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610f5391906117ed565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610fb757fe5b9060200190602002015161ffff16815481101515610fd157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561106157fe5b9060200190602002015161ffff1681548110151561107b57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610ef9565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555050505050565b6000808261ffff16600c54023414158061116c5750600060018461ffff1681151561116457fe5b0661ffff1614155b1561117657600080fd5b600360009054906101000a900461ffff1690505b600360009054906101000a900461ffff16830161ffff168161ffff16101561123f57600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816111fd91906117ed565b916000526020600020906010918282040191900660020283909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061118a565b82600360008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f1935050505015156112d157600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561138a57600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff16600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003101561143f5760009050611444565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905010156114a157600080fd5b600090505b81518161ffff16101561168257600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161150491906117ed565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff1681518110151561156c57fe5b9060200190602002015161ffff1681548110151561158657fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561161a57fe5b9060200190602002015161ffff1681548110151561163457fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060076000815480929190600101919050555080806001019150506114a6565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550505050565b6116fd6117c5565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117935780601f1061176857610100808354040283529160200191611793565b820191906000526020600020905b81548152906001019060200180831161177657829003601f168201915b5050505050905090565b60006004544211156117b257600190506117b7565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b81548183558181151161182257600f016010900481600f016010900483600052602060002091820191016118219190611827565b5b505050565b61184991905b8082111561184557600081600090555060010161182d565b5090565b905600a165627a7a7230582071adaa5e8b36a626e0271897ab2325b900e8063173d8a32e790db3c2e6fdead3002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000011496e74656e7365204c61626f7572696e67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a33302f30322f3230313700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e506173697220526973205061726b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003494e4c0000000000000000000000000000000000000000000000000000000000" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000009" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000008" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" - ,"0x" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000014" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000015" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000016" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000019" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001a" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000018" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000009" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000009" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000017" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000b" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000010" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000004" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc46802090539840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000f" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e" - ,"0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc46802090539840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" - ,"0xba9a90900000000000000000000000000000000000000000000000000000000000000001" - ,"0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001b6c38038062001b6c83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000f9929190620001ca565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550856006819055508260099080519060200190620001619291906200027b565b5087600890805190602001906200017a9291906200027b565b5084600a9080519060200190620001939291906200027b565b5083600b9080519060200190620001ac9291906200027b565b5081600c8190555080600d819055505050505050505050506200035e565b82805482825590600052602060002090600f01601090048101928215620002685791602002820160005b838211156200023657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001f4565b8015620002665782816101000a81549061ffff021916905560020160208160010104928301926001030262000236565b505b50905062000277919062000302565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002be57805160ff1916838001178555620002ef565b82800160010185558215620002ef579182015b82811115620002ee578251825591602001919060010190620002d1565b5b509050620002fe919062000336565b5090565b6200033391905b808211156200032f57600081816101000a81549061ffff02191690555060010162000309565b5090565b90565b6200035b91905b80821115620003575760008160009055506001016200033d565b5090565b90565b6117fe806200036e6000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd14610228578063313ce56714610251578063323046b1146102805780634bfbe5df1461030e57806370a082311461039c57806372c5cb631461042a57806395d89b4114610453578063a0d8848c146104e1578063a270a7371461050a578063a6fb475f14610598578063ba9a909014610630578063c2bf17b014610664578063db0ec96814610712578063e22bda351461078b578063ea8b5ca314610819578063f0141d8414610846575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086f565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610879565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610921565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610ab7565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b610264610ac0565b604051808260ff1660ff16815260200191505060405180910390f35b341561028b57600080fd5b610293610ac5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102d35780820151818401526020810190506102b8565b50505050905090810190601f1680156103005780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561031957600080fd5b610321610b63565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103a757600080fd5b6103d3600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c0b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104165780820151818401526020810190506103fb565b505050509050019250505060405180910390f35b341561043557600080fd5b61043d610cd0565b6040518082815260200191505060405180910390f35b341561045e57600080fd5b610466610cda565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104a657808201518184015260208101905061048b565b50505050905090810190601f1680156104d35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156104ec57600080fd5b6104f4610d82565b6040518082815260200191505060405180910390f35b341561051557600080fd5b61051d610d8c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561055d578082015181840152602081019050610542565b50505050905090810190601f16801561058a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105a357600080fd5b61062e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610e2a565b005b61064a600480803561ffff16906020019091905050611101565b604051808215151515815260200191505060405180910390f35b341561066f57600080fd5b6106af60048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061129f565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b341561071d57600080fd5b610789600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050611401565b005b341561079657600080fd5b61079e61167b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107de5780820151818401526020810190506107c3565b50505050905090810190601f16801561080b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561082457600080fd5b61082c611723565b604051808215151515815260200191505060405180910390f35b341561085157600080fd5b610859611740565b6040518082815260200191505060405180910390f35b6000600d54905090565b61088161174b565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109175780601f106108ec57610100808354040283529160200191610917565b820191906000526020600020905b8154815290600101906020018083116108fa57829003601f168201915b5050505050905090565b6000806000806000806000806109398c8c8c8c61129f565b9650965096509650600d54600360009054906101000a900461ffff16870161ffff16111561096657600080fd5b8561ffff168502925083801561097b57508234145b15610aa3576006543481151561098d57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109d557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a3757600080fd5b6007600081548092919060010191905055508561ffff16600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019750610aa8565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b5b5780601f10610b3057610100808354040283529160200191610b5b565b820191906000526020600020905b815481529060010190602001808311610b3e57829003601f168201915b505050505081565b610b6b61174b565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c015780601f10610bd657610100808354040283529160200191610c01565b820191906000526020600020905b815481529060010190602001808311610be457829003601f168201915b5050505050905090565b610c1361175f565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610cc457602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610c8b5790505b50505050509050919050565b6000600754905090565b610ce261174b565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d785780601f10610d4d57610100808354040283529160200191610d78565b820191906000526020600020905b815481529060010190602001808311610d5b57829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e225780601f10610df757610100808354040283529160200191610e22565b820191906000526020600020905b815481529060010190602001808311610e0557829003601f168201915b505050505081565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610e8857600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ed857600080fd5b600090505b81518110156110ad57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610f379190611773565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610f9b57fe5b9060200190602002015161ffff16815481101515610fb557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561104557fe5b9060200190602002015161ffff1681548110151561105f57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610edd565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555050505050565b6000808261ffff16600c5402341415806111305750600060018461ffff1681151561112857fe5b0661ffff1614155b1561113a57600080fd5b600360009054906101000a900461ffff1690505b600360009054906101000a900461ffff16830161ffff168161ffff16101561120357600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816111c19190611773565b916000526020600020906010918282040191900660020283909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061114e565b82600360008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561129557600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561134e57600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490500310156113f157600090506113f6565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050101561145357600080fd5b600090505b815181101561162857600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816114b29190611773565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858581518110151561151657fe5b9060200190602002015161ffff1681548110151561153057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083838151811015156115c057fe5b9060200190602002015161ffff168154811015156115da57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050611458565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550505050565b61168361174b565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117195780601f106116ee57610100808354040283529160200191611719565b820191906000526020600020905b8154815290600101906020018083116116fc57829003601f168201915b5050505050905090565b6000600454421115611738576001905061173d565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b8154818355818115116117a857600f016010900481600f016010900483600052602060002091820191016117a791906117ad565b5b505050565b6117cf91905b808211156117cb5760008160009055506001016117b3565b5090565b905600a165627a7a723058206f42c96331c4810d2277882fd44b93547d9ef05d8fccc0216cc96a22b8c3f6e1002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000f47656f6361636865204d65657475700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a33302f30312f323031370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000134f6c64204368616e676920486f73706974616c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000347454f0000000000000000000000000000000000000000000000000000000000" - ,"0x60606040526000600355600060075534156200001a57600080fd5b604051620019483803806200194883398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000e0929190620001b1565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560068190555082600990805190602001906200014892919062000203565b5087600890805190602001906200016192919062000203565b5084600a90805190602001906200017a92919062000203565b5083600b90805190602001906200019392919062000203565b5081600c8190555080600d81905550505050505050505050620002b2565b828054828255906000526020600020908101928215620001f0579160200282015b82811115620001ef578251825591602001919060010190620001d2565b5b509050620001ff91906200028a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024657805160ff191683800117855562000277565b8280016001018555821562000277579182015b828111156200027657825182559160200191906001019062000259565b5b5090506200028691906200028a565b5090565b620002af91905b80821115620002ab57600081600090555060010162000291565b5090565b90565b61168680620002c26000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd146102285780632b4e4e9614610251578063313ce567146102ca578063323046b1146102f95780634bfbe5df1461038757806370a082311461041557806372c5cb63146104a357806395d89b41146104cc578063a0d8848c1461055a578063a270a73714610583578063b4dbf64214610611578063c2bf17b014610641578063e22bda35146106ef578063ea8b5ca31461077d578063f0141d84146107aa578063fe60ebdc146107d3575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086b565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610875565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061091d565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610aa5565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b6102c8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610aae565b005b34156102d557600080fd5b6102dd610cc8565b604051808260ff1660ff16815260200191505060405180910390f35b341561030457600080fd5b61030c610ccd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561034c578082015181840152602081019050610331565b50505050905090810190601f1680156103795780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561039257600080fd5b61039a610d6b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103da5780820151818401526020810190506103bf565b50505050905090810190601f1680156104075780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561042057600080fd5b61044c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e13565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561048f578082015181840152602081019050610474565b505050509050019250505060405180910390f35b34156104ae57600080fd5b6104b6610eb0565b6040518082815260200191505060405180910390f35b34156104d757600080fd5b6104df610eba565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561051f578082015181840152602081019050610504565b50505050905090810190601f16801561054c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561056557600080fd5b61056d610f62565b6040518082815260200191505060405180910390f35b341561058e57600080fd5b610596610f6c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156105d65780820151818401526020810190506105bb565b50505050905090810190601f1680156106035780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610627600480803590602001909190505061100a565b604051808215151515815260200191505060405180910390f35b341561064c57600080fd5b61068c60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050611138565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156106fa57600080fd5b61070261129a565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610742578082015181840152602081019050610727565b50505050905090810190601f16801561076f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561078857600080fd5b610790611342565b604051808215151515815260200191505060405180910390f35b34156107b557600080fd5b6107bd61135f565b6040518082815260200191505060405180910390f35b34156107de57600080fd5b610869600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061136a565b005b6000600d54905090565b61087d6115e1565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109135780601f106108e857610100808354040283529160200191610913565b820191906000526020600020905b8154815290600101906020018083116108f657829003601f168201915b5050505050905090565b6000806000806000806000806109358c8c8c8c611138565b9650965096509650600d546003548761ffff1601111561095457600080fd5b8561ffff168502925083801561096957508234145b15610a91576006543481151561097b57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109c357600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a2557600080fd5b6007600081548092919060010191905055508561ffff16600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019750610a96565b600080fd5b50505050505050949350505050565b60008054905090565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610b0057600080fd5b600090505b8151811015610c7557600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610b5f91906115f5565b91600052602060002090016000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610bb957fe5b90602001906020020151815481101515610bcf57fe5b906000526020600020900154909190915055506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610c3157fe5b90602001906020020151815481101515610c4757fe5b9060005260206000209001819055506007600081548092919060010191905055508080600101915050610b05565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550505050565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d635780601f10610d3857610100808354040283529160200191610d63565b820191906000526020600020905b815481529060010190602001808311610d4657829003601f168201915b505050505081565b610d736115e1565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e095780601f10610dde57610100808354040283529160200191610e09565b820191906000526020600020905b815481529060010190602001808311610dec57829003601f168201915b5050505050905090565b610e1b611621565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ea457602002820191906000526020600020905b815481526020019060010190808311610e90575b50505050509050919050565b6000600754905090565b610ec26115e1565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f585780601f10610f2d57610100808354040283529160200191610f58565b820191906000526020600020905b815481529060010190602001808311610f3b57829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156110025780601f10610fd757610100808354040283529160200191611002565b820191906000526020600020905b815481529060010190602001808311610fe557829003601f168201915b505050505081565b60008082600c54023414158061102d5750600060018481151561102957fe5b0614155b1561103757600080fd5b60035490505b60035483018110156110bc57600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161109a91906115f5565b916000526020600020900160008390919091505550808060010191505061103d565b82600360008282540192505081905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561112e57600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e757600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003101561128a576000905061128f565b600190505b945094509450949050565b6112a26115e1565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113385780601f1061130d57610100808354040283529160200191611338565b820191906000526020600020905b81548152906001019060200180831161131b57829003601f168201915b5050505050905090565b6000600454421115611357576001905061135c565b600090505b90565b60008060ff16905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113c857600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050101561141857600080fd5b600090505b815181101561158d57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161147791906115f5565b91600052602060002090016000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002085858151811015156114d157fe5b906020019060200201518154811015156114e757fe5b906000526020600020900154909190915055506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561154957fe5b9060200190602002015181548110151561155f57fe5b906000526020600020900181905550600760008154809291906001019190505550808060010191505061141d565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555050505050565b602060405190810160405280600081525090565b81548183558181151161161c5781836000526020600020918201910161161b9190611635565b5b505050565b602060405190810160405280600081525090565b61165791905b8082111561165357600081600090555060010161163b565b5090565b905600a165627a7a72305820e5a23be67453636fe4b69894d7f2a63e90e8f89b6c7f2a44cc0831e57b4c9a24002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000f47656f6361636865204d65657475700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a33302f30312f323031370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000134f6c64204368616e676920486f73706974616c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000347454f0000000000000000000000000000000000000000000000000000000000" - ,"0x23b872dd000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0xa9059cbb000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c0000000000000000000000000000000000000000000000000000000000000002" - ,"0x60606040526000600355600060075534156200001a57600080fd5b604051620019483803806200194883398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000e0929190620001b1565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560068190555082600990805190602001906200014892919062000203565b5087600890805190602001906200016192919062000203565b5084600a90805190602001906200017a92919062000203565b5083600b90805190602001906200019392919062000203565b5081600c8190555080600d81905550505050505050505050620002b2565b828054828255906000526020600020908101928215620001f0579160200282015b82811115620001ef578251825591602001919060010190620001d2565b5b509050620001ff91906200028a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024657805160ff191683800117855562000277565b8280016001018555821562000277579182015b828111156200027657825182559160200191906001019062000259565b5b5090506200028691906200028a565b5090565b620002af91905b80821115620002ab57600081600090555060010162000291565b5090565b90565b61168680620002c26000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd146102285780632b4e4e9614610251578063313ce567146102ca578063323046b1146102f95780634bfbe5df1461038757806370a082311461041557806372c5cb63146104a357806395d89b41146104cc578063a0d8848c1461055a578063a270a73714610583578063b4dbf64214610611578063c2bf17b014610641578063e22bda35146106ef578063ea8b5ca31461077d578063f0141d84146107aa578063fe60ebdc146107d3575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086b565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610875565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061091d565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610aa5565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b6102c8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610aae565b005b34156102d557600080fd5b6102dd610cc8565b604051808260ff1660ff16815260200191505060405180910390f35b341561030457600080fd5b61030c610ccd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561034c578082015181840152602081019050610331565b50505050905090810190601f1680156103795780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561039257600080fd5b61039a610d6b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103da5780820151818401526020810190506103bf565b50505050905090810190601f1680156104075780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561042057600080fd5b61044c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e13565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561048f578082015181840152602081019050610474565b505050509050019250505060405180910390f35b34156104ae57600080fd5b6104b6610eb0565b6040518082815260200191505060405180910390f35b34156104d757600080fd5b6104df610eba565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561051f578082015181840152602081019050610504565b50505050905090810190601f16801561054c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561056557600080fd5b61056d610f62565b6040518082815260200191505060405180910390f35b341561058e57600080fd5b610596610f6c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156105d65780820151818401526020810190506105bb565b50505050905090810190601f1680156106035780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610627600480803590602001909190505061100a565b604051808215151515815260200191505060405180910390f35b341561064c57600080fd5b61068c60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050611138565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156106fa57600080fd5b61070261129a565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610742578082015181840152602081019050610727565b50505050905090810190601f16801561076f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561078857600080fd5b610790611342565b604051808215151515815260200191505060405180910390f35b34156107b557600080fd5b6107bd61135f565b6040518082815260200191505060405180910390f35b34156107de57600080fd5b610869600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061136a565b005b6000600d54905090565b61087d6115e1565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109135780601f106108e857610100808354040283529160200191610913565b820191906000526020600020905b8154815290600101906020018083116108f657829003601f168201915b5050505050905090565b6000806000806000806000806109358c8c8c8c611138565b9650965096509650600d546003548761ffff1601111561095457600080fd5b8561ffff168502925083801561096957508234145b15610a91576006543481151561097b57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109c357600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a2557600080fd5b6007600081548092919060010191905055508561ffff16600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019750610a96565b600080fd5b50505050505050949350505050565b60008054905090565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610b0057600080fd5b600090505b8151811015610c7557600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610b5f91906115f5565b91600052602060002090016000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610bb957fe5b90602001906020020151815481101515610bcf57fe5b906000526020600020900154909190915055506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610c3157fe5b90602001906020020151815481101515610c4757fe5b9060005260206000209001819055506007600081548092919060010191905055508080600101915050610b05565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550505050565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d635780601f10610d3857610100808354040283529160200191610d63565b820191906000526020600020905b815481529060010190602001808311610d4657829003601f168201915b505050505081565b610d736115e1565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e095780601f10610dde57610100808354040283529160200191610e09565b820191906000526020600020905b815481529060010190602001808311610dec57829003601f168201915b5050505050905090565b610e1b611621565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ea457602002820191906000526020600020905b815481526020019060010190808311610e90575b50505050509050919050565b6000600754905090565b610ec26115e1565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f585780601f10610f2d57610100808354040283529160200191610f58565b820191906000526020600020905b815481529060010190602001808311610f3b57829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156110025780601f10610fd757610100808354040283529160200191611002565b820191906000526020600020905b815481529060010190602001808311610fe557829003601f168201915b505050505081565b60008082600c54023414158061102d5750600060018481151561102957fe5b0614155b1561103757600080fd5b60035490505b60035483018110156110bc57600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161109a91906115f5565b916000526020600020900160008390919091505550808060010191505061103d565b82600360008282540192505081905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561112e57600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e757600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003101561128a576000905061128f565b600190505b945094509450949050565b6112a26115e1565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113385780601f1061130d57610100808354040283529160200191611338565b820191906000526020600020905b81548152906001019060200180831161131b57829003601f168201915b5050505050905090565b6000600454421115611357576001905061135c565b600090505b90565b60008060ff16905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113c857600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050101561141857600080fd5b600090505b815181101561158d57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161147791906115f5565b91600052602060002090016000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002085858151811015156114d157fe5b906020019060200201518154811015156114e757fe5b906000526020600020900154909190915055506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561154957fe5b9060200190602002015181548110151561155f57fe5b906000526020600020900181905550600760008154809291906001019190505550808060010191505061141d565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555050505050565b602060405190810160405280600081525090565b81548183558181151161161c5781836000526020600020918201910161161b9190611635565b5b505050565b602060405190810160405280600081525090565b61165791905b8082111561165357600081600090555060010161163b565b5090565b905600a165627a7a72305820d2f7d7b61cacd1e9d44d53fbe9eb95c0ae51787109504667e8403fd3a4f310ef002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000b4d4a20636f6d656261636b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a32312f31302f323032300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094d474d206772616e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d4a430000000000000000000000000000000000000000000000000000000000" - ,"0x60606040526000600255600060065534156200001a57600080fd5b604051620016ea380380620016ea83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000e0929190620001b1565b508660038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560058190555082600890805190602001906200014892919062000203565b5087600790805190602001906200016192919062000203565b5084600990805190602001906200017a92919062000203565b5083600a90805190602001906200019392919062000203565b5081600b8190555080600c81905550505050505050505050620002b2565b828054828255906000526020600020908101928215620001f0579160200282015b82811115620001ef578251825591602001919060010190620001d2565b5b509050620001ff91906200028a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024657805160ff191683800117855562000277565b8280016001018555821562000277579182015b828111156200027657825182559160200191906001019062000259565b5b5090506200028691906200028a565b5090565b620002af91905b80821115620002ab57600081600090555060010162000291565b5090565b90565b61142880620002c26000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd1461022857806323b872dd146102515780632b4e4e96146102b2578063313ce5671461032b578063323046b11461035a5780634bfbe5df146103e857806370a082311461047657806372c5cb631461050457806395d89b411461052d578063a0d8848c146105bb578063a270a737146105e4578063b4dbf64214610672578063c2bf17b0146106a2578063e22bda3514610750578063ea8b5ca3146107de578063f0141d841461080b575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a610834565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b61015361083e565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506108e6565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610a1d565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b6102b0600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a26565b005b34156102bd57600080fd5b610329600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bc6565b005b341561033657600080fd5b61033e610d22565b604051808260ff1660ff16815260200191505060405180910390f35b341561036557600080fd5b61036d610d27565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103ad578082015181840152602081019050610392565b50505050905090810190601f1680156103da5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103f357600080fd5b6103fb610dc5565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043b578082015181840152602081019050610420565b50505050905090810190601f1680156104685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561048157600080fd5b6104ad600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e6d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104f05780820151818401526020810190506104d5565b505050509050019250505060405180910390f35b341561050f57600080fd5b610517610f0a565b6040518082815260200191505060405180910390f35b341561053857600080fd5b610540610f14565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610580578082015181840152602081019050610565565b50505050905090810190601f1680156105ad5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105c657600080fd5b6105ce610fbc565b6040518082815260200191505060405180910390f35b34156105ef57600080fd5b6105f7610fc6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561063757808201518184015260208101905061061c565b50505050905090810190601f1680156106645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6106886004808035906020019091905050611064565b604051808215151515815260200191505060405180910390f35b34156106ad57600080fd5b6106ed60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050611192565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b341561075b57600080fd5b6107636112b3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107a3578082015181840152602081019050610788565b50505050905090810190601f1680156107d05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156107e957600080fd5b6107f161135b565b604051808215151515815260200191505060405180910390f35b341561081657600080fd5b61081e611378565b6040518082815260200191505060405180910390f35b6000600c54905090565b610846611383565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108dc5780601f106108b1576101008083540402835291602001916108dc565b820191906000526020600020905b8154815290600101906020018083116108bf57829003601f168201915b5050505050905090565b6000806000806000806000806108fe8c8c8c8c611192565b9650965096509650600c546002548761ffff1601111561091d57600080fd5b8561ffff168502925083801561093257508234145b15610a09576005543481151561094457fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561098c57600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f1935050505015156109ee57600080fd5b60066000815480929190600101919050555060019750610a0e565b600080fd5b50505050505050949350505050565b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610a8457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ad357600080fd5b600090505b81811015610bc057600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610b319190611397565b916000526020600020900160008390919091505550600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081815481101515610b9257fe5b9060005260206000209001600090556006600081548092919060010191905055508080600101915050610ad8565b50505050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610c1857600080fd5b600090505b8151811015610d1d57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610c779190611397565b916000526020600020900160008484815181101515610c9257fe5b9060200190602002015190919091505550600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081815481101515610cef57fe5b9060005260206000209001600090556006600081548092919060010191905055508080600101915050610c1d565b505050565b600081565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610dbd5780601f10610d9257610100808354040283529160200191610dbd565b820191906000526020600020905b815481529060010190602001808311610da057829003601f168201915b505050505081565b610dcd611383565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e635780601f10610e3857610100808354040283529160200191610e63565b820191906000526020600020905b815481529060010190602001808311610e4657829003601f168201915b5050505050905090565b610e756113c3565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efe57602002820191906000526020600020905b815481526020019060010190808311610eea575b50505050509050919050565b6000600654905090565b610f1c611383565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb25780601f10610f8757610100808354040283529160200191610fb2565b820191906000526020600020905b815481529060010190602001808311610f9557829003601f168201915b5050505050905090565b6000600b54905090565b600a8054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561105c5780601f106110315761010080835404028352916020019161105c565b820191906000526020600020905b81548152906001019060200180831161103f57829003601f168201915b505050505081565b60008082600b5402341415806110875750600060018481151561108357fe5b0614155b1561109157600080fd5b60025490505b600254830181101561111657600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110f49190611397565b9160005260206000209001600083909190915055508080600101915050611097565b82600260008282540192505081905550600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561118857600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561124157600080fd5b50506020604051035193508261ffff16600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905010156112a357600090506112a8565b600190505b945094509450949050565b6112bb611383565b600a8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113515780601f1061132657610100808354040283529160200191611351565b820191906000526020600020905b81548152906001019060200180831161133457829003601f168201915b5050505050905090565b60006003544211156113705760019050611375565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b8154818355818115116113be578183600052602060002091820191016113bd91906113d7565b5b505050565b602060405190810160405280600081525090565b6113f991905b808211156113f55760008160009055506001016113dd565b5090565b905600a165627a7a7230582022cfd54936a82a7fa6bfc9a23f54bc20104eccb8ede93c36e4c2ab2cef5d17c5002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000b4d4a20636f6d656261636b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a32312f31302f323032300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094d474d206772616e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d4a430000000000000000000000000000000000000000000000000000000000" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x6060604052600060055534156200001557600080fd5b60405162001aee38038062001aee8339810160405280805190602001909190805182019190602001805190602001909190805190602001909190805182019190602001805182019190602001805182019190602001805190602001909190805190602001909190505088600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508660028190555033600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606486670de0b6b3a7640000028115156200012a57fe5b0460048190555082600790805190602001906200014992919062000234565b5087600690805190602001906200016292919062000234565b5084600890805190602001906200017b92919062000234565b5083600990805190602001906200019492919062000234565b5081600b8190555080600c81905550620001c1620001d06401000000000262001495176401000000009004565b505050505050505050620002e3565b6103e860016000727bee82bdd9e866b2bd114780a47f2261c684e373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200027757805160ff1916838001178555620002a8565b82800160010185558215620002a8579182015b82811115620002a75782518255916020019190600101906200028a565b5b509050620002b79190620002bb565b5090565b620002e091905b80821115620002dc576000816000905550600101620002c2565b5090565b90565b6117fb80620002f36000396000f300606060405260043610610128576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461013857806306fdde03146101615780630e1c2d46146101ef57806318160ddd1461029d57806323b872dd146102c6578063313ce5671461033f578063323046b11461036e578063454b6be1146103fc5780634bfbe5df146104bc57806370a082311461054a57806372c5cb63146105975780638043c9c0146105c057806395d89b411461064e578063a0d8848c146106dc578063a270a73714610705578063a9059cbb14610793578063aa6ca808146107ed578063b4dbf64214610802578063c2bf17b014610832578063e22bda35146108e0578063ea8b5ca31461096e578063f0141d841461099b575b341561013357600080fd5b600080fd5b341561014357600080fd5b61014b6109c4565b6040518082815260200191505060405180910390f35b341561016c57600080fd5b6101746109ce565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101b4578082015181840152602081019050610199565b50505050905090810190601f1680156101e15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156101fa57600080fd5b61023a60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610a6c565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156102a857600080fd5b6102b0610b7a565b6040518082815260200191505060405180910390f35b34156102d157600080fd5b610325600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b83565b604051808215151515815260200191505060405180910390f35b341561034a57600080fd5b610352610d4f565b604051808260ff1660ff16815260200191505060405180910390f35b341561037957600080fd5b610381610d54565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c15780820151818401526020810190506103a6565b50505050905090810190601f1680156103ee5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040757600080fd5b61044760048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610df2565b604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018661ffff1661ffff1681526020018581526020018415151515815260200183815260200182151515158152602001965050505050505060405180910390f35b34156104c757600080fd5b6104cf6110a8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561050f5780820151818401526020810190506104f4565b50505050905090810190601f16801561053c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561055557600080fd5b610581600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611150565b6040518082815260200191505060405180910390f35b34156105a257600080fd5b6105aa611199565b6040518082815260200191505060405180910390f35b34156105cb57600080fd5b6105d36111a3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106135780820151818401526020810190506105f8565b50505050905090810190601f1680156106405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561065957600080fd5b61066161124b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106a1578082015181840152602081019050610686565b50505050905090810190601f1680156106ce5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156106e757600080fd5b6106ef6112e9565b6040518082815260200191505060405180910390f35b341561071057600080fd5b6107186112f3565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561075857808201518184015260208101905061073d565b50505050905090810190601f1680156107855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561079e57600080fd5b6107d3600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050611391565b604051808215151515815260200191505060405180910390f35b34156107f857600080fd5b610800611495565b005b61081860048080359060200190919050506114f9565b604051808215151515815260200191505060405180910390f35b341561083d57600080fd5b61087d60048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506115dd565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156108eb57600080fd5b6108f36116eb565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610933578082015181840152602081019050610918565b50505050905090810190601f1680156109605780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561097957600080fd5b610981611793565b604051808215151515815260200191505060405180910390f35b34156109a657600080fd5b6109ae6117b0565b6040518082815260200191505060405180910390f35b6000600c54905090565b60068054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a645780601f10610a3957610100808354040283529160200191610a64565b820191906000526020600020905b815481529060010190602001808311610a4757829003601f168201915b505050505081565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610b1b57600080fd5b50506020604051035193508261ffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410159050945094509450949050565b60008054905090565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610be157600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515610d435781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360056000815480929190600101919050555060019050610d48565b600090505b9392505050565b600081565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610dea5780601f10610dbf57610100808354040283529160200191610dea565b820191906000526020600020905b815481529060010190602001808311610dcd57829003601f168201915b505050505081565b60008060008060008060008061ffff6001028c166001900496506010808d600019169060020a9004600019169060020a0260019004955060018c8c8c8c604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610ea757600080fd5b50506020604051035197508661ffff16600160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101594508661ffff16860293508334101515610f165760019250610f1b565b600092505b848015610f255750825b15611099578661ffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508661ffff16600160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600454606434811515610fdb57fe5b0402915081340390508773ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561102457600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050151561108657600080fd5b6005600081548092919060010191905055505b50509499939850945094509450565b6110b06117bb565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156111465780601f1061111b57610100808354040283529160200191611146565b820191906000526020600020905b81548152906001019060200180831161112957829003601f168201915b5050505050905090565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600554905090565b6111ab6117bb565b60068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112415780601f1061121657610100808354040283529160200191611241565b820191906000526020600020905b81548152906001019060200180831161122457829003601f168201915b5050505050905090565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112e15780601f106112b6576101008083540402835291602001916112e1565b820191906000526020600020905b8154815290600101906020018083116112c457829003601f168201915b505050505081565b6000600b54905090565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113895780601f1061135e57610100808354040283529160200191611389565b820191906000526020600020905b81548152906001019060200180831161136c57829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156113df57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506005600081548092919060010191905055506001905092915050565b6103e860016000727bee82bdd9e866b2bd114780a47f2261c684e373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550565b600081600b54023414158061151b5750600060018381151561151757fe5b0614155b1561152557600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561158757600080fd5b60018060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561168c57600080fd5b50506020604051035193508261ffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410159050945094509450949050565b6116f36117bb565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117895780601f1061175e57610100808354040283529160200191611789565b820191906000526020600020905b81548152906001019060200180831161176c57829003601f168201915b5050505050905090565b60006002544211156117a857600190506117ad565b600090505b90565b60008060ff16905090565b6020604051908101604052806000815250905600a165627a7a72305820aa4ec49a3d3c615a410bf3e2805df4b0443a492f214dd4d73874911ebbb25efe002900000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000145472616e73706172656e7420506172616469676d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a32332f30352f3230313800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f53696e6761706f726520466c796572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035450470000000000000000000000000000000000000000000000000000000000" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x6060604052600060055534156200001557600080fd5b604051620016ca380380620016ca8339810160405280805190602001909190805182019190602001805190602001909190805190602001909190805182019190602001805182019190602001805182019190602001805190602001909190805190602001909190505088600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508660028190555033600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606486670de0b6b3a7640000028115156200012a57fe5b04600481905550826007908051906020019062000149929190620001b2565b50876006908051906020019062000162929190620001b2565b5084600890805190602001906200017b929190620001b2565b50836009908051906020019062000194929190620001b2565b5081600b8190555080600c8190555050505050505050505062000261565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001f557805160ff191683800117855562000226565b8280016001018555821562000226579182015b828111156200022557825182559160200191906001019062000208565b5b50905062000235919062000239565b5090565b6200025e91905b808211156200025a57600081600090555060010162000240565b5090565b90565b61145980620002716000396000f300606060405260043610610112576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461012257806306fdde031461014b5780630e1c2d46146101d957806318160ddd1461023357806323b872dd1461025c578063313ce567146102d5578063323046b1146103045780634bfbe5df1461039257806370a082311461042057806372c5cb631461046d5780638043c9c01461049657806395d89b4114610524578063a0d8848c146105b2578063a270a737146105db578063a9059cbb14610669578063b4dbf642146106c3578063c2bf17b0146106f3578063e22bda35146107a1578063ea8b5ca31461082f578063f0141d841461085c575b341561011d57600080fd5b600080fd5b341561012d57600080fd5b610135610885565b6040518082815260200191505060405180910390f35b341561015657600080fd5b61015e61088f565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561019e578082015181840152602081019050610183565b50505050905090810190601f1680156101cb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61021960048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061092d565b604051808215151515815260200191505060405180910390f35b341561023e57600080fd5b610246610af2565b6040518082815260200191505060405180910390f35b341561026757600080fd5b6102bb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610afb565b604051808215151515815260200191505060405180910390f35b34156102e057600080fd5b6102e8610cc7565b604051808260ff1660ff16815260200191505060405180910390f35b341561030f57600080fd5b610317610ccc565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561035757808201518184015260208101905061033c565b50505050905090810190601f1680156103845780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561039d57600080fd5b6103a5610d6a565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103e55780820151818401526020810190506103ca565b50505050905090810190601f1680156104125780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561042b57600080fd5b610457600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e12565b6040518082815260200191505060405180910390f35b341561047857600080fd5b610480610e5b565b6040518082815260200191505060405180910390f35b34156104a157600080fd5b6104a9610e65565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e95780820151818401526020810190506104ce565b50505050905090810190601f1680156105165780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052f57600080fd5b610537610f0d565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561057757808201518184015260208101905061055c565b50505050905090810190601f1680156105a45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105bd57600080fd5b6105c5610fab565b6040518082815260200191505060405180910390f35b34156105e657600080fd5b6105ee610fb5565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561062e578082015181840152602081019050610613565b50505050905090810190601f16801561065b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561067457600080fd5b6106a9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050611053565b604051808215151515815260200191505060405180910390f35b6106d96004808035906020019091905050611157565b604051808215151515815260200191505060405180910390f35b34156106fe57600080fd5b61073e60048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061123b565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156107ac57600080fd5b6107b4611349565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107f45780820151818401526020810190506107d9565b50505050905090810190601f1680156108215780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561083a57600080fd5b6108426113f1565b604051808215151515815260200191505060405180910390f35b341561086757600080fd5b61086f61140e565b6040518082815260200191505060405180910390f35b6000600c54905090565b60068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109255780601f106108fa57610100808354040283529160200191610925565b820191906000526020600020905b81548152906001019060200180831161090857829003601f168201915b505050505081565b6000806000806000806000806109458c8c8c8c61123b565b96509650965096508561ffff168502925083801561096257508234145b15610ade578561ffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508561ffff16600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600454606434811515610a1857fe5b0402915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501515610a6157600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610ac357600080fd5b60056000815480929190600101919050555060019750610ae3565b600080fd5b50505050505050949350505050565b60008054905090565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610b5957600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515610cbb5781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360056000815480929190600101919050555060019050610cc0565b600090505b9392505050565b600081565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d625780601f10610d3757610100808354040283529160200191610d62565b820191906000526020600020905b815481529060010190602001808311610d4557829003601f168201915b505050505081565b610d72611419565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e085780601f10610ddd57610100808354040283529160200191610e08565b820191906000526020600020905b815481529060010190602001808311610deb57829003601f168201915b5050505050905090565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600554905090565b610e6d611419565b60068054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f035780601f10610ed857610100808354040283529160200191610f03565b820191906000526020600020905b815481529060010190602001808311610ee657829003601f168201915b5050505050905090565b60078054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fa35780601f10610f7857610100808354040283529160200191610fa3565b820191906000526020600020905b815481529060010190602001808311610f8657829003601f168201915b505050505081565b6000600b54905090565b60098054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561104b5780601f106110205761010080835404028352916020019161104b565b820191906000526020600020905b81548152906001019060200180831161102e57829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156110a157600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506005600081548092919060010191905055506001905092915050565b600081600b5402341415806111795750600060018381151561117557fe5b0614155b1561118357600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f1935050505015156111e557600080fd5b60018060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156112ea57600080fd5b50506020604051035193508261ffff16600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410159050945094509450949050565b611351611419565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113e75780601f106113bc576101008083540402835291602001916113e7565b820191906000526020600020905b8154815290600101906020018083116113ca57829003601f168201915b5050505050905090565b6000600254421115611406576001905061140b565b600090505b90565b60008060ff16905090565b6020604051908101604052806000815250905600a165627a7a72305820a031d8b8554004fd703791c0c564d2ec4cb2edcb93a3425b0b36d61fe6ede01f002900000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b4d4a20636f6d656261636b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a32312f31302f323032300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094d474d206772616e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d4a430000000000000000000000000000000000000000000000000000000000" - ,"0xf2fde38b0000000000000000000000000000000000000000000000000000000000000000" - ,"0xad8733ca000000000000000000000000352505482ceaf9d95f76da5d3f84e8d630b78c3b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000006000000000000000000000000dacc9c61754a0c4616fc5323dc946e89eb27230200000000000000000000000027af1b9c0490a8d656ffa32a7e56b85cdf211ea8000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000021acfd9f199fa91213a23193c9504f10cac2f06300000000000000000000000081b7e08f65bdf5648606c89998a9cc8164397647000000000000000000000000efde75ccae5c0f8fe856b22e2a175254e7f2b7330000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002710" - ,"0x" - ,"0xa9059cbb000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000008ac7230489e80000" - ,"0x" - ,"0x" - ,"0x299251cd00000000000000000000000074ab01a13bb912c73415d1e65a167108627f6ada00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032000000000000000000000000cca455208df89d37ddc1a82aec0fda159137517b0000000000000000000000002e863634ec7d9f2b5c841ea4e2e83d8e32846e8500000000000000000000000095c3d3d6b571549bb2cbf9d0587c3e979a62a1990000000000000000000000002be55849cc424dacb12bdfc199fdceeeab0ef705000000000000000000000000011e8238342f403eb24bb599b3a4f86a87de6282000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000016de4774f2542a1bc49b9cd0b8a80b769468ebd4000000000000000000000000a240b902887e16759d679aaa8292cb84c6f6c2c6000000000000000000000000dd50c2060939ac1f94e201278286b0a0d03037c80000000000000000000000008aa76da4127d74923d2cf0f9e97aa3afcb747d18000000000000000000000000085be78299d6271939e7b732e87643d7367f60a5000000000000000000000000465dc984a581e40d4f29f69e00afff07042b2c310000000000000000000000008f7f202a7ec7e24118e0c5426397fb3eb5a59a15000000000000000000000000288fff976c024d3115bcd05e5e7578a19f60b1130000000000000000000000008042ebcc8217bb4271bd32ec7408fb60a6a35e3400000000000000000000000024f3f53c77f82ed99f72b09be92f3a477d82b5b70000000000000000000000007c34db57c20eab8f1fca9b76b93d44f65338dae7000000000000000000000000305d44857dae0197551e7c3597c9a03c8bd43e830000000000000000000000006c5ed14e0ba5e8f98bfbe08d8d31741aa6ee3fdb00000000000000000000000055e2780588aa5000f464f700d2676fd0a22ee1600000000000000000000000000af34f7ed6e29f5f08a6538f6588e8fb3d03601500000000000000000000000084dd81652899327ecf0ced2ecc704f208059834100000000000000000000000044601662c4888248a523cb742610c0a5cabd2648000000000000000000000000d136e8878fbc8a1cae779760b4b70447b4a5ef5d000000000000000000000000af1e444ec82f3c4b0a9f3b6f1a41b0f42b78303e00000000000000000000000000503510c51624c67ae3aa37b47af2ca270b586a000000000000000000000000433b4cc2b6dd3e8953ba9ba9a0c169a45125596a000000000000000000000000fc15859aee77be7de9d6d45478b0265988e3c9370000000000000000000000000080da07a81ba604f040d6f3050f913e33a0f9ab000000000000000000000000cade8041a96a65bdd95d44df5ccdf67e82c6da5b000000000000000000000000f657830abdcef58aa3fc1b7594dc85fc8aa6a5c5000000000000000000000000004e5b2467a8f1861e920c384ceb03f771a35cb60000000000000000000000002e2ae2675b929f81326d5960b8d8063ed96418e00000000000000000000000008b93db60ab13819dcc0428cb5cbe5389e361f57300000000000000000000000059a15efa6b3326cfced0ffdb398a500478081302000000000000000000000000e441aba5aef9081d76c01b0767d0bfd934c04410000000000000000000000000e55f33961a656255d1870750a931c6af97e2e67b0000000000000000000000001534c5916595197c8dd270af3167b90a84a64ae2000000000000000000000000ce31dfe738fcb8272bb275ad6b199a2fbae71b9c0000000000000000000000007ee90046baff191a86a716de3a110faccc53a894000000000000000000000000edbc6ec9d2fb3f63a45502f66283bad1061150b8000000000000000000000000be969db1c039ce0203c9c4c27cf5c6e0d3c318be0000000000000000000000001278302a6d8c8cf0bf68409b1719208b2a18086a0000000000000000000000005ef9f1cf1acab0638a65bd969471a7a7754899950000000000000000000000009b86ce9d21c1394c2f9d9cf7f86415258ee4d6ae0000000000000000000000006594d8ab68a8192a82a4642436c24f76952fbaf30000000000000000000000005d1d6ff025e471e0a76058fde9ec01e979d749ac0000000000000000000000006d75461234a0898ce365c44b38f43cbc714d1431000000000000000000000000a160b0be09922d071bffaaa4be111ad93052b5e40000000000000000000000002601a089b9fc228c4a053ad1d96e52571824d468" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000027e4e09fe9743d6497b31504bfe2ad00d9567afd0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000092b6becccfb777223afd6d4f28461ad5469435be0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000ff7b12fff896f572e9e4dd31c3c2e8bcef8328980000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd00000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c830902000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c830902000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000079888add20834984e6b5a3d0676542c69c03b6740000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c8309020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c8309020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c8309020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000079888add20834984e6b5a3d0676542c69c03b6740000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c8309020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000001a68f5e645573c182a263a6d9391729789a7d1640000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000149512264d5077c092cc46472d6042e5006ae40b0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000001a68f5e645573c182a263a6d9391729789a7d1640000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000072d1ff0ecd51509f251d577891d686c7885aacff0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e9e6716d6458c334bb55cf70e19507df7bb816d90000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd0000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea7000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd0000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea7000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd0000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea7000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0xa9059cbb00000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a0200000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x60606040526000600655341561001457600080fd5b60405160808061069f8339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550809050505050506105a2806100fd6000396000f30060606040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007d57806323b872dd146100a657806370a082311461011f57806372c5cb631461016c578063a9059cbb14610195575b341561007857600080fd5b600080fd5b341561008857600080fd5b6100906101ef565b6040518082815260200191505060405180910390f35b34156100b157600080fd5b610105600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101f8565b604051808215151515815260200191505060405180910390f35b341561012a57600080fd5b610156600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506103ae565b6040518082815260200191505060405180910390f35b341561017757600080fd5b61017f6103f7565b6040518082815260200191505060405180910390f35b34156101a057600080fd5b6101d5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610401565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561025657600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103a65781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a3600190506103a7565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600654905090565b6000600554341080610451575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561045b57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360066000815480929190600101919050555060019050929150505600a165627a7a72305820723c6a75fca5e9610e120968d3f6d449318cef0110af304030cba3261381f4f10029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f706572610000000000000000000000000000000000000000000000000000000000000000000000005f751c000000000000000000000000000000000000000000000000000000000000000000" - ,"0x60606040526000600655341561001457600080fd5b60405160808061069f8339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550809050505050506105a2806100fd6000396000f30060606040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007d57806323b872dd146100a657806370a082311461011f57806372c5cb631461016c578063a9059cbb14610195575b341561007857600080fd5b600080fd5b341561008857600080fd5b6100906101ef565b6040518082815260200191505060405180910390f35b34156100b157600080fd5b610105600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101f8565b604051808215151515815260200191505060405180910390f35b341561012a57600080fd5b610156600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506103ae565b6040518082815260200191505060405180910390f35b341561017757600080fd5b61017f6103f7565b6040518082815260200191505060405180910390f35b34156101a057600080fd5b6101d5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610401565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561025657600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103a65781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a3600190506103a7565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600654905090565b6000600554341080610451575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561045b57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360066000815480929190600101919050555060019050929150505600a165627a7a72305820723c6a75fca5e9610e120968d3f6d449318cef0110af304030cba3261381f4f10029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f706572610000000000000000000000000000000000000000000000000000000000000000000000005f751c000000000000000000000000000000000000000000000000000000000000000000" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x6060604052341561000f57600080fd5b60405160808061064a8339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080905050505050610552806100f86000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007257806323b872dd1461009b57806370a0823114610114578063a9059cbb14610161575b341561006d57600080fd5b600080fd5b341561007d57600080fd5b6100856101bb565b6040518082815260200191505060405180910390f35b34156100a657600080fd5b6100fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c4565b604051808215151515815260200191505060405180910390f35b341561011f57600080fd5b61014b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061037a565b6040518082815260200191505060405180910390f35b341561016c57600080fd5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103c3565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022257600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103725781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360019050610373565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600554341080610413575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561041d57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050929150505600a165627a7a72305820fc6fe2b69ea1605361d5a2b9bd4cc8ef4e0426df34f8a1402caa8b2d90649b850029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f706572610000000000000000000000000000000000000000000000000000000000000000000000005f751c000000000000000000000000000000000000000000000000000000000000000000" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x6060604052341561000f57600080fd5b6040516080806106598339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080905050505050610561806100f86000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007257806323b872dd1461009b57806370a0823114610114578063a9059cbb14610161575b341561006d57600080fd5b600080fd5b341561007d57600080fd5b6100856101bb565b6040518082815260200191505060405180910390f35b34156100a657600080fd5b6100fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c4565b604051808215151515815260200191505060405180910390f35b341561011f57600080fd5b61014b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061037a565b6040518082815260200191505060405180910390f35b341561016c57600080fd5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103c3565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022257600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103725781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360019050610373565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006003544211156103d457600080fd5b600554341080610422575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561042c57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050929150505600a165627a7a72305820081acc60d332bcea2f22d1abd81dc46314c54c9c2d71482c0214b3aa2d112ee70029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f70657261000000000000000000000000000000000000000000000000000000000000000000000174e17560000000000000000000000000000000000000000000000000000000000000000000" - ,"0xa9059cbb000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f42956738a7c308193772298cd25dea5172b269c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd00000000000000000000000056c35ccfd4d5c7b4c900c77f886c0e65772eff67000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000056c35ccfd4d5c7b4c900c77f886c0e65772eff670000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000002" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x2e1b8e21000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004d2000000000000000000000000000000000000000000000000000000000000000b3132333431323334323334000000000000000000000000000000000000000000" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x3078000000000000000000000000007bee82bdefbfbdefbfbd66efbfbdefbfbd1147efbfbdefbfbd7f2261c684efbfbd000000000000000000000000efbfbd6d4befbfbdefbfbd2d0b0e6fefbfbd7f08efbfbdefbfbdefbfbd2fefbfbd052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x6060604052341561000f57600080fd5b6040516080806106598339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080905050505050610561806100f86000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007257806323b872dd1461009b57806370a0823114610114578063a9059cbb14610161575b341561006d57600080fd5b600080fd5b341561007d57600080fd5b6100856101bb565b6040518082815260200191505060405180910390f35b34156100a657600080fd5b6100fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c4565b604051808215151515815260200191505060405180910390f35b341561011f57600080fd5b61014b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061037a565b6040518082815260200191505060405180910390f35b341561016c57600080fd5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103c3565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022257600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103725781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360019050610373565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006003544211156103d457600080fd5b600554341080610422575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561042c57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050929150505600a165627a7a72305820081acc60d332bcea2f22d1abd81dc46314c54c9c2d71482c0214b3aa2d112ee70029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f706572610000000000000000000000000000000000000000000000000000000000000000000000005f751c000000000000000000000000000000000000000000000000000000000000000000" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe20000000000000000000000005bb8d47bb262aaeabef2207d1d4af3b13fb8d8e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe20000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd0000000000000000000000005bb8d47bb262aaeabef2207d1d4af3b13fb8d8e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000005bb8d47bb262aaeabef2207d1d4af3b13fb8d8e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000005bb8d47bb262aaeabef2207d1d4af3b13fb8d8e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe2000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe20000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe2000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe20000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fea78a32aaedb0908857ac74598c078f73adeee00000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000b1c36cac20c0127d9c24271d1d97ee45002056650000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000617ded54ec054f8be89147e9def2f68a24be101d0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000264a2629bc956327b37657b50306d83543a51c57000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000009d6268a6a7f62b73c3a55ccddde2f2796db497750000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000002f48d567cebe41df9f2e5093fb8962b5ae9517760000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000bece95c79dd839dacb162cc70fd408a5596cbf9e0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000264a2629bc956327b37657b50306d83543a51c570000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000edf94b3c304217f6e8b89cd8c6330ee027e12f360000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000455e83b7c3a2f264ba2fb0bc96b3cf315c8591f6000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000455e83b7c3a2f264ba2fb0bc96b3cf315c8591f6000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000455e83b7c3a2f264ba2fb0bc96b3cf315c8591f60000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007b91f7618a158137f23b09c4e2190cc27587c2570000000000000000000000000000000000000000000000000000000000000001" - ,"0x6060604052341561000f57600080fd5b6040516080806105438339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505050505061044b806100f86000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007057806323b872dd1461009957806370a0823114610112578063a9059cbb1461015f575b341561006b57600080fd5b600080fd5b341561007b57600080fd5b6100836101b9565b6040518082815260200191505060405180910390f35b34156100a457600080fd5b6100f8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c2565b604051808215151515815260200191505060405180910390f35b341561011d57600080fd5b610149600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102c5565b6040518082815260200191505060405180910390f35b341561016a57600080fd5b61019f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061030e565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022057600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190509392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600060035442111561031f57600080fd5b60055434108061037157506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561037b57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050929150505600a165627a7a72305820af0e8d60e0b80d2599f4b5d2996c65865e2fc9fb93028e319a6a8ff525058f6f002900000000000000000000000000000000000000000000000000000000000061a844616e6765726f757320776f6d616e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b9dddb80000000000000000000000000000000000000000000000000000000000000001" - ,"0x6060604052341561000f57600080fd5b6040516080806105438339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505050505061044b806100f86000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007057806323b872dd1461009957806370a0823114610112578063a9059cbb1461015f575b341561006b57600080fd5b600080fd5b341561007b57600080fd5b6100836101b9565b6040518082815260200191505060405180910390f35b34156100a457600080fd5b6100f8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c2565b604051808215151515815260200191505060405180910390f35b341561011d57600080fd5b610149600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102c5565b6040518082815260200191505060405180910390f35b341561016a57600080fd5b61019f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061030e565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022057600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190509392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600060035442111561031f57600080fd5b60055434108061037157506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561037b57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050929150505600a165627a7a72305820af0e8d60e0b80d2599f4b5d2996c65865e2fc9fb93028e319a6a8ff525058f6f00290000000000000000000000000000000000000000000000000000000000004e204d6973616476656e747572657320696e20616e20616d7374657264616d20636f000000000000000000000000000000000000000000000000000000005b9dddb80000000000000000000000000000000000000000000000000000000000000000" - ,"0x23b872dd000000000000000000000000dd35094c66be5822bdf2b4aae1491a5b7bfc6b76000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000dd35094c66be5822bdf2b4aae1491a5b7bfc6b760000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000005cb81c966f6a97bf6c9f868592d34f22868710080000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000278b94a77b870c3c4333119dc460caa9e69ddf830000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000041cd0acccc289eb713e0373962467e96b69967f7000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000041cd0acccc289eb713e0373962467e96b69967f70000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fb1b9b41040d16564a0101242c6ff78734e370a6000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fb1b9b41040d16564a0101242c6ff78734e370a60000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000087d0ec46e87b161411ab5b26df61846760049c370000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000535ef2a55cd79440b5b10f679404a5f2598538f80000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000076d45f3d3798808cf30461cf503ec0ba033861fb0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000030362ef7ed13d5f29ffd4931ad53c845fb4d11440000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000005657fd0af3a9efbc32cb070576f58f6c9d7d7cd0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000059691de7d4094bb2ffb71d500611180001b87b450000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000006580b7bde7205c45fcbace09eba71220a76f93850000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000056bd8aed482ec9ebce28f0616b4673a33b46f9840000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000004de70b13e2da1d393c35110a5c856a8af53127260000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000a8c19e4ba5ce3a1dabe72d2054d28f507b9005b80000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000006981ff3868fe463a827b858d3bf2dd985f6ef5600000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000b038c5e29400e184649cf176465d0c948ffa2ad7000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000b038c5e29400e184649cf176465d0c948ffa2ad70000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000b1741048d1e7d218ea49025530b68059b76396ec000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e2ffd2e1cffc7688315912856c255889371e76590000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000b1741048d1e7d218ea49025530b68059b76396ec0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd0000000000000000000000008119bde86bb60d17e307ef38a908e4ce06b34cfc000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000008119bde86bb60d17e307ef38a908e4ce06b34cfc0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd0000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd0000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd0000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd0000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd00000000000000000000000061b205f0d383f24b8fe675d54bdd00f0f7a1526b000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000d9126a6cd1afab5186bc72bfaaa7a5a58440861a0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" - ,"0x" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000064" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000015" - ,"0x18160ddd" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" - ,"0x6060604052341561000f57600080fd5b604051608080610551833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b610456806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600190505b5b5b929150505600a165627a7a723058205b86e848a779bf6ec997f3d2783ce089388f0791003bb8714419eb3898926f2d00290000000000000000000000000000000000000000000000000000000000001388706c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005b9dddb80000000000000000000000000000000000000000000000000000000000000000" - ,"0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000000000030694cff4ba44800247afc3a517c54d5ca0000000000000000000000000000000000000000000000000000000000000001" - ,"0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc00290000000000000000000000000000000000000000000000000000000000001388706c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005b9dddb80000000000000000000000000000000000000000000000000000000000000000" - ,"0x" - ,"0x23b872dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - ,"0x23b872dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - ,"0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" - ,"0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" - ,"0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" - ,"0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" - ,"0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" - ,"0x" - ,"0x6060604052341561000f57600080fd5b604051610dd1380380610dd18339810160405280805190602001909190805182019190602001805190602001909190805182019190505083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508360008190555082600390805190602001906100a79291906100e3565b5081600460006101000a81548160ff021916908360ff16021790555080600590805190602001906100d99291906100e3565b5050505050610188565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061012457805160ff1916838001178555610152565b82800160010185558215610152579182015b82811115610151578251825591602001919060010190610136565b5b50905061015f9190610163565b5090565b61018591905b80821115610181576000816000905550600101610169565b5090565b90565b610c3a806101976000396000f3006060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014257806318160ddd1461019c57806323b872dd146101c557806327e235e31461023e578063313ce5671461028b5780635c658165146102ba57806370a082311461032657806395d89b4114610373578063a9059cbb14610401578063dd62ed3e1461045b575b600080fd5b34156100bf57600080fd5b6100c76104c7565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101075780820151818401526020810190506100ec565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610182600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610565565b604051808215151515815260200191505060405180910390f35b34156101a757600080fd5b6101af610657565b6040518082815260200191505060405180910390f35b34156101d057600080fd5b610224600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061065d565b604051808215151515815260200191505060405180910390f35b341561024957600080fd5b610275600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506108f7565b6040518082815260200191505060405180910390f35b341561029657600080fd5b61029e61090f565b604051808260ff1660ff16815260200191505060405180910390f35b34156102c557600080fd5b610310600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610922565b6040518082815260200191505060405180910390f35b341561033157600080fd5b61035d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610947565b6040518082815260200191505060405180910390f35b341561037e57600080fd5b610386610990565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c65780820151818401526020810190506103ab565b50505050905090810190601f1680156103f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040c57600080fd5b610441600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a2e565b604051808215151515815260200191505060405180910390f35b341561046657600080fd5b6104b1600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b87565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561055d5780601f106105325761010080835404028352916020019161055d565b820191906000526020600020905b81548152906001019060200180831161054057829003601f168201915b505050505081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561072e5750828110155b151561073957600080fd5b82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156108865782600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b60016020528060005260406000206000915090505481565b600460009054906101000a900460ff1681565b6002602052816000526040600020602052806000526040600020600091509150505481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7e57600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a723058208867cc817b5728cc1c034e415ddc65b88add0ad41a9d9827b2ba80ba0ac9f1e6002900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000104f67757a68616e4c69666556616c75650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034f43470000000000000000000000000000000000000000000000000000000000" + , "0xdb0ec968000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b9" + , "0xa9059cbb000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000de0b6b3a7640000" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001c" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000e" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000093922cdabaa26d50e7c6cb19ee3bcd03462ed334000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" + , "0xa6fb475f000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0xdb0ec968000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000d2" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001bf9cadbff0499fbd2afb4c25289c8fc17518bd22060526b619d4645fcc4c94c5357dcccf6e3e9f20533b6343e7d0e88fa37e9e23790e0ecbc57b4b85a3b421d1f0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d" + , "0xa6fb475f000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e" + , "0xa6fb475f000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000d6" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000bf" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000bf" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xdb0ec968000000000000000000000000c9034ff4266b1690d2b579584e5c3259009ed13c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x" + , "0x" + , "0x" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060065534156200003357600080fd5b60405162001a3a38038062001a3a83398101604052808051820191906020018051820191906020018051906020019091908051820191905050835160008190555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000c9929190620001aa565b508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600890805190602001906200016b9291906200025b565b508260079080519060200190620001849291906200025b565b506001600960006101000a81548160ff021916908315150217905550505050506200033e565b82805482825590600052602060002090600f01601090048101928215620002485791602002820160005b838211156200021657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001d4565b8015620002465782816101000a81549061ffff021916905560020160208160010104928301926001030262000216565b505b509050620002579190620002e2565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200029e57805160ff1916838001178555620002cf565b82800160010185558215620002cf579182015b82811115620002ce578251825591602001919060010190620002b1565b5b509050620002de919062000316565b5090565b6200031391905b808211156200030f57600081816101000a81549061ffff021916905550600101620002e9565b5090565b90565b6200033b91905b80821115620003375760008160009055506001016200031d565b5090565b90565b6116ec806200034e6000396000f3006060604052600436106100e6576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100f657806318160ddd14610184578063313ce567146101ad57806332a2c5d0146101dc5780634f452b9a1461023157806358089fc61461025e578063696ecc551461028b57806370a082311461030957806372c5cb631461039757806395d89b41146103c0578063a6fb475f1461044e578063bb6e7de9146104e6578063c2532c3d146104fb578063db0ec9681461059a578063ea8b5ca314610613578063f0141d8414610640575b34156100f157600080fd5b600080fd5b341561010157600080fd5b610109610669565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014957808201518184015260208101905061012e565b50505050905090810190601f1680156101765780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018f57600080fd5b610197610711565b6040518082815260200191505060405180910390f35b34156101b857600080fd5b6101c061071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101e757600080fd5b6101ef61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023c57600080fd5b610244610727565b604051808215151515815260200191505060405180910390f35b341561026957600080fd5b61027161073e565b604051808215151515815260200191505060405180910390f35b61030760048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610751565b005b341561031457600080fd5b610340600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a7e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610383578082015181840152602081019050610368565b505050509050019250505060405180910390f35b34156103a257600080fd5b6103aa610b43565b6040518082815260200191505060405180910390f35b34156103cb57600080fd5b6103d3610b4d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104135780820151818401526020810190506103f8565b50505050905090810190601f1680156104405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561045957600080fd5b6104e4600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bf5565b005b34156104f157600080fd5b6104f9610e7e565b005b341561050657600080fd5b61059860048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f14565b005b34156105a557600080fd5b610611600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506110eb565b005b341561061e57600080fd5b6106266112d2565b604051808215151515815260200191505060405180910390f35b341561064b57600080fd5b6106536112ef565b6040518082815260200191505060405180910390f35b610671611625565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107075780601f106106dc57610100808354040283529160200191610707565b820191906000526020600020905b8154815290600101906020018083116106ea57829003601f168201915b5050505050905090565b60008054905090565b600081565b600030905090565b6000600960009054906101000a900460ff16905090565b600960009054906101000a900460ff1681565b600080600080428911806107655750600089145b151561077057600080fd5b61077b348a8a6112fa565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107fb57600080fd5b5050602060405103519250600091505b8751821015610a3357878281518110151561082257fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561088057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161115156108b457600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816109059190611639565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561096857fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109f757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff160217905550818060010192505061080b565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a7357600080fd5b505050505050505050565b610a86611673565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b3757602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610afe5790505b50505050509050919050565b6000600654905090565b610b55611625565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610beb5780601f10610bc057610100808354040283529160200191610beb565b820191906000526020600020905b815481529060010190602001808311610bce57829003601f168201915b5050505050905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c5357600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ca357600080fd5b600090505b8151811015610e7857600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d029190611639565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610d6657fe5b9060200190602002015161ffff16815481101515610d8057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610e1057fe5b9060200190602002015161ffff16815481101515610e2a57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506006600081548092919060010191905055508080600101915050610ca8565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f0f57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f256000808a6112fa565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610fc257600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561102957600080fd5b600090505b87518110156110e157600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110889190611639565b91600052602060002090601091828204019190066002028a848151811015156110ad57fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061102e565b5050505050505050565b60008090505b81518161ffff1610156112cd57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161114f9190611639565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff168151811015156111b757fe5b9060200190602002015161ffff168154811015156111d157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561126557fe5b9060200190602002015161ffff1681548110151561127f57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060066000815480929190600101919050555080806001019150506110f1565b505050565b60006003544211156112e757600190506112ec565b600090505b90565b60008060ff16905090565b6000611304611687565b600080600285510260540160405180591061131c5750595b9080825280601f01601f1916602001820160405250925061133b61071f565b9150600090505b60208110156113a35780600802879060020a02600102838281518110151561136657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611342565b600090505b602081101561140c5780600802869060020a0260010283602083018151811015156113cf57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506113a8565b600090505b60148110156114905780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561145357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611411565b600090505b84518110156115b657600885828151811015156114ae57fe5b9060200190602002015161ffff169060020a90047f01000000000000000000000000000000000000000000000000000000000000000283600283026054018151811015156114f857fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561153657fe5b906020019060200201517f010000000000000000000000000000000000000000000000000000000000000002836001600284026054010181518110151561157957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611495565b826040518082805190602001908083835b6020831015156115ec57805182526020820191506020810190506020830392506115c7565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b81548183558181151161166e57600f016010900481600f0160109004836000526020600020918201910161166d919061169b565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b6116bd91905b808211156116b95760008160009055506001016116a1565b5090565b905600a165627a7a723058201e8c8b879a2027fbce1df4eec16e8d9a2f206c5e7be2868a1878154ebf6e277a002900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000001c4000000000000000000000000000000000000000000000000000000000000000db0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000105000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000001070000000000000000000000000000000000000000000000000000000000000108000000000000000000000000000000000000000000000000000000000000010900000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000000010030000000000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000000000000000000000000000100500000000000000000000000000000000000000000000000000000000000010060000000000000000000000000000000000000000000000000000000000001007000000000000000000000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000010090000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000108100000000000000000000000000000000000000000000000000000000000010820000000000000000000000000000000000000000000000000000000000001083000000000000000000000000000000000000000000000000000000000000108400000000000000000000000000000000000000000000000000000000000010850000000000000000000000000000000000000000000000000000000000001086000000000000000000000000000000000000000000000000000000000000108700000000000000000000000000000000000000000000000000000000000010880000000000000000000000000000000000000000000000000000000000001089000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000011010000000000000000000000000000000000000000000000000000000000001102000000000000000000000000000000000000000000000000000000000000110300000000000000000000000000000000000000000000000000000000000011040000000000000000000000000000000000000000000000000000000000001105000000000000000000000000000000000000000000000000000000000000110600000000000000000000000000000000000000000000000000000000000011070000000000000000000000000000000000000000000000000000000000001108000000000000000000000000000000000000000000000000000000000000110900000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000000000000000000000000000000000000000000200200000000000000000000000000000000000000000000000000000000000020030000000000000000000000000000000000000000000000000000000000002004000000000000000000000000000000000000000000000000000000000000200500000000000000000000000000000000000000000000000000000000000020060000000000000000000000000000000000000000000000000000000000002007000000000000000000000000000000000000000000000000000000000000200800000000000000000000000000000000000000000000000000000000000020090000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000208100000000000000000000000000000000000000000000000000000000000020820000000000000000000000000000000000000000000000000000000000002083000000000000000000000000000000000000000000000000000000000000208400000000000000000000000000000000000000000000000000000000000020850000000000000000000000000000000000000000000000000000000000002086000000000000000000000000000000000000000000000000000000000000208700000000000000000000000000000000000000000000000000000000000020880000000000000000000000000000000000000000000000000000000000002089000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021010000000000000000000000000000000000000000000000000000000000002102000000000000000000000000000000000000000000000000000000000000210300000000000000000000000000000000000000000000000000000000000021040000000000000000000000000000000000000000000000000000000000002105000000000000000000000000000000000000000000000000000000000000210600000000000000000000000000000000000000000000000000000000000021070000000000000000000000000000000000000000000000000000000000002108000000000000000000000000000000000000000000000000000000000000210900000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003001000000000000000000000000000000000000000000000000000000000000300200000000000000000000000000000000000000000000000000000000000030030000000000000000000000000000000000000000000000000000000000003004000000000000000000000000000000000000000000000000000000000000300500000000000000000000000000000000000000000000000000000000000030060000000000000000000000000000000000000000000000000000000000003007000000000000000000000000000000000000000000000000000000000000300800000000000000000000000000000000000000000000000000000000000030090000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000308100000000000000000000000000000000000000000000000000000000000030820000000000000000000000000000000000000000000000000000000000003083000000000000000000000000000000000000000000000000000000000000308400000000000000000000000000000000000000000000000000000000000030850000000000000000000000000000000000000000000000000000000000003086000000000000000000000000000000000000000000000000000000000000308700000000000000000000000000000000000000000000000000000000000030880000000000000000000000000000000000000000000000000000000000003089000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031010000000000000000000000000000000000000000000000000000000000003102000000000000000000000000000000000000000000000000000000000000310300000000000000000000000000000000000000000000000000000000000031040000000000000000000000000000000000000000000000000000000000003105000000000000000000000000000000000000000000000000000000000000310600000000000000000000000000000000000000000000000000000000000031070000000000000000000000000000000000000000000000000000000000003108000000000000000000000000000000000000000000000000000000000000310900000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004001000000000000000000000000000000000000000000000000000000000000400200000000000000000000000000000000000000000000000000000000000040030000000000000000000000000000000000000000000000000000000000004004000000000000000000000000000000000000000000000000000000000000400500000000000000000000000000000000000000000000000000000000000040060000000000000000000000000000000000000000000000000000000000004007000000000000000000000000000000000000000000000000000000000000400800000000000000000000000000000000000000000000000000000000000040090000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000408100000000000000000000000000000000000000000000000000000000000040820000000000000000000000000000000000000000000000000000000000004083000000000000000000000000000000000000000000000000000000000000408400000000000000000000000000000000000000000000000000000000000040850000000000000000000000000000000000000000000000000000000000004086000000000000000000000000000000000000000000000000000000000000408700000000000000000000000000000000000000000000000000000000000040880000000000000000000000000000000000000000000000000000000000004089000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004102000000000000000000000000000000000000000000000000000000000000410300000000000000000000000000000000000000000000000000000000000041040000000000000000000000000000000000000000000000000000000000004105000000000000000000000000000000000000000000000000000000000000410600000000000000000000000000000000000000000000000000000000000041070000000000000000000000000000000000000000000000000000000000004108000000000000000000000000000000000000000000000000000000000000410900000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005001000000000000000000000000000000000000000000000000000000000000500200000000000000000000000000000000000000000000000000000000000050030000000000000000000000000000000000000000000000000000000000005004000000000000000000000000000000000000000000000000000000000000500500000000000000000000000000000000000000000000000000000000000050060000000000000000000000000000000000000000000000000000000000005007000000000000000000000000000000000000000000000000000000000000500800000000000000000000000000000000000000000000000000000000000050090000000000000000000000000000000000000000000000000000000000005080000000000000000000000000000000000000000000000000000000000000508100000000000000000000000000000000000000000000000000000000000050820000000000000000000000000000000000000000000000000000000000005083000000000000000000000000000000000000000000000000000000000000508400000000000000000000000000000000000000000000000000000000000050850000000000000000000000000000000000000000000000000000000000005086000000000000000000000000000000000000000000000000000000000000508700000000000000000000000000000000000000000000000000000000000050880000000000000000000000000000000000000000000000000000000000005089000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000051010000000000000000000000000000000000000000000000000000000000005102000000000000000000000000000000000000000000000000000000000000510300000000000000000000000000000000000000000000000000000000000051040000000000000000000000000000000000000000000000000000000000005105000000000000000000000000000000000000000000000000000000000000510600000000000000000000000000000000000000000000000000000000000051070000000000000000000000000000000000000000000000000000000000005108000000000000000000000000000000000000000000000000000000000000510900000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006001000000000000000000000000000000000000000000000000000000000000600200000000000000000000000000000000000000000000000000000000000060030000000000000000000000000000000000000000000000000000000000006004000000000000000000000000000000000000000000000000000000000000600500000000000000000000000000000000000000000000000000000000000060060000000000000000000000000000000000000000000000000000000000006007000000000000000000000000000000000000000000000000000000000000600800000000000000000000000000000000000000000000000000000000000060090000000000000000000000000000000000000000000000000000000000006080000000000000000000000000000000000000000000000000000000000000608100000000000000000000000000000000000000000000000000000000000060820000000000000000000000000000000000000000000000000000000000006083000000000000000000000000000000000000000000000000000000000000608400000000000000000000000000000000000000000000000000000000000060850000000000000000000000000000000000000000000000000000000000006086000000000000000000000000000000000000000000000000000000000000608700000000000000000000000000000000000000000000000000000000000060880000000000000000000000000000000000000000000000000000000000006089000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061010000000000000000000000000000000000000000000000000000000000006102000000000000000000000000000000000000000000000000000000000000610300000000000000000000000000000000000000000000000000000000000061040000000000000000000000000000000000000000000000000000000000006105000000000000000000000000000000000000000000000000000000000000610600000000000000000000000000000000000000000000000000000000000061070000000000000000000000000000000000000000000000000000000000006108000000000000000000000000000000000000000000000000000000000000610900000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007001000000000000000000000000000000000000000000000000000000000000700200000000000000000000000000000000000000000000000000000000000070030000000000000000000000000000000000000000000000000000000000007004000000000000000000000000000000000000000000000000000000000000700500000000000000000000000000000000000000000000000000000000000070060000000000000000000000000000000000000000000000000000000000007007000000000000000000000000000000000000000000000000000000000000700800000000000000000000000000000000000000000000000000000000000070090000000000000000000000000000000000000000000000000000000000000015576f726c6420536572696573204261736562616c6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000035753420000000000000000000000000000000000000000000000000000000000" + , "0x00" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000ec" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000be" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000be" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b7" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b7" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e7" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c7" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b6" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000009" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000008" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000008" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b5" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b4" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000b3" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" + , "0xdb0ec968000000000000000000000000cc5490a4b584ef7450492d45022ff017da5a35cc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000021" + , "0x00" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000bd" + , "0x" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001c15f77da29e4cfb5ff799df4e952958333647d0c33d815690a5f0982877e29d754e78ee4110d069f3218808affd075a5bb98a475bcfcbcf48e5f55e4d402a72bd000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000ae" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000ea" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e8" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a6" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000053" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000008f0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000a3" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0xdb0ec968000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004f" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001e3838038062001e388339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b508160099080519060200190620001999291906200026f565b508360089080519060200190620001b29291906200026f565b50505050505062000352565b82805482825590600052602060002090600f016010900481019282156200025c5791602002820160005b838211156200022a57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025a5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022a565b505b5090506200026b9190620002f6565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b257805160ff1916838001178555620002e3565b82800160010185558215620002e3579182015b82811115620002e2578251825591602001919060010190620002c5565b5b509050620002f291906200032a565b5090565b6200032791905b808211156200032357600081816101000a81549061ffff021916905550600101620002fd565b5090565b90565b6200034f91905b808211156200034b57600081600090555060010162000331565b5090565b90565b611ad680620003626000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063696ecc551461022a57806370a08231146102a857806372c5cb631461033657806395d89b411461035f578063a6fb475f146103ed578063bb6e7de914610485578063c2532c3d1461049a578063c9116b6914610539578063db0ec968146105a3578063ea8b5ca31461061c578063f0141d8414610649575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b6102a660048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610730565b005b34156102b357600080fd5b6102df600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b07565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610322578082015181840152602081019050610307565b505050509050019250505060405180910390f35b341561034157600080fd5b610349610bcc565b6040518082815260200191505060405180910390f35b341561036a57600080fd5b610372610bd6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103b2578082015181840152602081019050610397565b50505050905090810190601f1680156103df5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103f857600080fd5b610483600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610c7e565b005b341561049057600080fd5b61049861100d565b005b34156104a557600080fd5b61053760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506110a3565b005b341561054457600080fd5b61054c611324565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058f578082015181840152602081019050610574565b505050509050019250505060405180910390f35b34156105ae57600080fd5b61061a600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506113e7565b005b341561062757600080fd5b61062f6116bc565b604051808215151515815260200191505060405180910390f35b341561065457600080fd5b61065c6116d9565b6040518082815260200191505060405180910390f35b61067a611a0f565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b600080600080428911806107445750600089145b151561074f57600080fd5b61075a348a8a6116e4565b9350600184888888604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af115156107cd57600080fd5b5050602060405103519250600091505b8751821015610a055787828151811015156107f457fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561085257fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff1611151561088657600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108d79190611a23565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561093a57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109c957fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506107dd565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a4557600080fd5b8760405180828051906020019060200280838360005b83811015610a76578082015181840152602081019050610a5b565b5050505090500191505060405180910390208373ffffffffffffffffffffffffffffffffffffffff167fec67368df72865aef2c3748b4627cbcc0b539079709e3a6fbcaea909f4c68353898989604051808460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390a3505050505050505050565b610b0f611a5d565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610bc057602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610b875790505b50505050509050919050565b6000600754905090565b610bde611a0f565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c745780601f10610c4957610100808354040283529160200191610c74565b820191906000526020600020905b815481529060010190602001808311610c5757829003601f168201915b5050505050905090565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610cdf57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610f68576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610d8e57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff16141580610dc05750825b1515610dcb57600080fd5b8382815181101515610dd957fe5b9060200190602002015161ffff169050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610e3a9190611a23565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610e9d57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610f2c57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055508180600101925050610d37565b8360405180828051906020019060200280838360005b83811015610f99578082015181840152602081019050610f7e565b5050505090500191505060405180910390208573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f2dc84a69caf5a654b181a8d5cbc2194f4e4cab204443797dd13dff734279ee0660405160405180910390a4505050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561109e57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b60008060006110b46000808a6116e4565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1151561114457600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415156111ab57600080fd5b600090505b875181101561126357600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161120a9190611a23565b91600052602060002090601091828204019190066002028a8481518110151561122f57fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff1602179055505080806001019150506111b0565b8373ffffffffffffffffffffffffffffffffffffffff168860405180828051906020019060200280838360005b838110156112ab578082015181840152602081019050611290565b5050505090500191505060405180910390207f4490f02c64b562efdc9d14a196182a17381fdb62142db3a2117519102a151ea9898989604051808460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001935050505060405180910390a35050505050505050565b61132c611a5d565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156113dd57602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116113a45790505b5050505050905090565b6000806003544211156113f957600080fd5b600091505b8251821015611627576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110151561145557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161415151561148a57600080fd5b828281518110151561149857fe5b9060200190602002015161ffff169050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816114f99190611a23565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561155c57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156115eb57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506113fe565b8373ffffffffffffffffffffffffffffffffffffffff167f746c5afa194dd33ab23937c67f9e99800eb78b625176eb271c3dec182f57dbc1846040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156116a3578082015181840152602081019050611688565b505050509050019250505060405180910390a250505050565b60006003544211156116d157600190506116d6565b600090505b90565b60008060ff16905090565b60006116ee611a71565b60008060028551026054016040518059106117065750595b9080825280601f01601f1916602001820160405250925061172561071f565b9150600090505b602081101561178d5780600802879060020a02600102838281518110151561175057fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061172c565b600090505b60208110156117f65780600802869060020a0260010283602083018151811015156117b957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611792565b600090505b601481101561187a5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561183d57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506117fb565b600090505b84518110156119a0576008858281518110151561189857fe5b9060200190602002015161ffff169060020a90047f01000000000000000000000000000000000000000000000000000000000000000283600283026054018151811015156118e257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561192057fe5b906020019060200201517f010000000000000000000000000000000000000000000000000000000000000002836001600284026054010181518110151561196357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061187f565b826040518082805190602001908083835b6020831015156119d657805182526020820191506020810190506020830392506119b1565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b815481835581811511611a5857600f016010900481600f01601090048360005260206000209182019101611a579190611a85565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b611aa791905b80821115611aa3576000816000905550600101611a8b565b5090565b905600a165627a7a7230582014dd7212dadd7dc9b4e03b4efe24138115abc9c57e46d495b9379ae5a3d17fe3002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000b4d4a20636f6d656261636b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d4a430000000000000000000000000000000000000000000000000000000000" + , "0x696ecc55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae9823d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f0000000000000000000000004b0b2389900d2638b684f037d6ec8efa61cf3ec9000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000004a" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000ac" + , "0xdb0ec9680000000000000000000000004b0b2389900d2638b684f037d6ec8efa61cf3ec90000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000048" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000046" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000045" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000041" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e2" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000d5" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e6" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003e" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e5" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003a" + , "0x696ecc55000000000000000000000000000000000000000000000000000000005a9d16ba00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b607bc2ebbbc0ef7a3b1f520f5f5eea7a5a0dd3959e7013588020d2732d0cfc5647990dae807d0d1509186a0e4f4773d7569d906abe97829a3925350e62f6f116000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012" + , "0xdb0ec96800000000000000000000000021acfd9f199fa91213a23193c9504f10cac2f0630000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000036" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001f" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003d" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000034" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000e4" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000030" + , "0xdb0ec96800000000000000000000000021acfd9f199fa91213a23193c9504f10cac2f06300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002d" + , "0xdb0ec968000000000000000000000000f8523f7cae2254d27efb50be22c118b31b79056200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a" + , "0xdb0ec968000000000000000000000000f8523f7cae2254d27efb50be22c118b31b79056200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c" + , "0xa6fb475f000000000000000000000000c830f48cf39419f0d01a125396ebf8dc6b61b65f000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001e" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001d" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000024" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000025" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000018" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a" + , "0xdb0ec968000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000032" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001c" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001b" + , "0x696ecc55000000000000000000000000000000000000000000000000000000005a9a00e200000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001bc59d6718734043600a49ec2419e566fa03676058e88326ff1161c579c6b8e79951d22461ab6f27bedd72d6b56c1fecf9f4cbb79a7728c510022617a9e42782ea000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012" + , "0x696ecc55000000000000000000000000000000000000000000000000000000005a9a001f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001c8ee5c1b644deba36a536a9ba32ca200af2914e212d725b6c2b4837bc9fdcb81f1658bfa9f6e7a8ea82a14efaa84bb1cf079b5ca5595f2dcd6a2adb5b89012c78000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000007a" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000019" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000017" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000014" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001a" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000020" + , "0xdb0ec96800000000000000000000000021acfd9f199fa91213a23193c9504f10cac2f063000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000096" + , "0xdb0ec968000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000095" + , "0xdb0ec968000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000df" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000019" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c6" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000018" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000017" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000db" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000e1" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000de" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007" + , "0x63877ab800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" + , "0xa6fb475f00000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c2" + , "0xdb0ec96800000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000089" + , "0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0x5c6491e500000000000000000000000099f05a668119d8938d79f85add73c9ab8ff719b1000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x696ecc55000000000000000000000000000000000000000000000000000000005a916f4300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b16e9d2a4a45ec33193fc04d3ffc4786b5d636f7b63127a81c4b9ae87109abc02798aeb53b47c30ab8ac1eb6231fc2990a2f2bc21dfecc698e5cdb6de1bd0ff060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e" + , "0x696ecc55000000000000000000000000000000000000000000000000000000005a9002c000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b7e92d67d8443d0cf548be4ab6c29ae910b7996b248d876687d79bd5df9786cbd34797d008f639ce56189ad26555ee18ab16bf23b9a0cb9e3a0d60bbb4556770d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001" + , "0x696ecc55000000000000000000000000000000000000000000000000000000005a8ff7b300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b929cbfe005791c7fba07d03b27f5b7ecf712ab0744cda025d2782590b78770d406e828ae6f3217ea3a0c9cd4a77a443cb3de037aa5ba7dd205b56a04aa341bbd000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x696ecc55000000000000000000000000000000000000000000000000000000005a8ff7b300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b929cbfe005791c7fba07d03b27f5b7ecf712ab0744cda025d2782590b78770d406e828ae6f3217ea3a0c9cd4a77a443cb3de037aa5ba7dd205b56a04aa341bbd000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x" + , "0xdb0ec9680000000000000000000000009b9d498ce067f4dc2a971f2abd533182c309bf71000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xa9059cbb000000000000000000000000e56c880c8e0f8869f7fcb2f7f774d923578f9f5d0000000000000000000000000000000000000000000000000000000000000064" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060065534156200003357600080fd5b60405162001a3a38038062001a3a83398101604052808051820191906020018051820191906020018051906020019091908051820191905050835160008190555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000c9929190620001aa565b508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600890805190602001906200016b9291906200025b565b508260079080519060200190620001849291906200025b565b506001600960006101000a81548160ff021916908315150217905550505050506200033e565b82805482825590600052602060002090600f01601090048101928215620002485791602002820160005b838211156200021657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001d4565b8015620002465782816101000a81549061ffff021916905560020160208160010104928301926001030262000216565b505b509050620002579190620002e2565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200029e57805160ff1916838001178555620002cf565b82800160010185558215620002cf579182015b82811115620002ce578251825591602001919060010190620002b1565b5b509050620002de919062000316565b5090565b6200031391905b808211156200030f57600081816101000a81549061ffff021916905550600101620002e9565b5090565b90565b6200033b91905b80821115620003375760008160009055506001016200031d565b5090565b90565b6116ec806200034e6000396000f3006060604052600436106100e6576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100f657806318160ddd14610184578063313ce567146101ad57806332a2c5d0146101dc5780634f452b9a1461023157806358089fc61461025e578063696ecc551461028b57806370a082311461030957806372c5cb631461039757806395d89b41146103c0578063a6fb475f1461044e578063bb6e7de9146104e6578063c2532c3d146104fb578063db0ec9681461059a578063ea8b5ca314610613578063f0141d8414610640575b34156100f157600080fd5b600080fd5b341561010157600080fd5b610109610669565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014957808201518184015260208101905061012e565b50505050905090810190601f1680156101765780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018f57600080fd5b610197610711565b6040518082815260200191505060405180910390f35b34156101b857600080fd5b6101c061071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101e757600080fd5b6101ef61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023c57600080fd5b610244610727565b604051808215151515815260200191505060405180910390f35b341561026957600080fd5b61027161073e565b604051808215151515815260200191505060405180910390f35b61030760048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610751565b005b341561031457600080fd5b610340600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a7e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610383578082015181840152602081019050610368565b505050509050019250505060405180910390f35b34156103a257600080fd5b6103aa610b43565b6040518082815260200191505060405180910390f35b34156103cb57600080fd5b6103d3610b4d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104135780820151818401526020810190506103f8565b50505050905090810190601f1680156104405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561045957600080fd5b6104e4600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bf5565b005b34156104f157600080fd5b6104f9610e7e565b005b341561050657600080fd5b61059860048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f14565b005b34156105a557600080fd5b610611600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506110eb565b005b341561061e57600080fd5b6106266112d2565b604051808215151515815260200191505060405180910390f35b341561064b57600080fd5b6106536112ef565b6040518082815260200191505060405180910390f35b610671611625565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107075780601f106106dc57610100808354040283529160200191610707565b820191906000526020600020905b8154815290600101906020018083116106ea57829003601f168201915b5050505050905090565b60008054905090565b600081565b600030905090565b6000600960009054906101000a900460ff16905090565b600960009054906101000a900460ff1681565b600080600080428911806107655750600089145b151561077057600080fd5b61077b348a8a6112fa565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107fb57600080fd5b5050602060405103519250600091505b8751821015610a3357878281518110151561082257fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561088057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161115156108b457600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816109059190611639565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561096857fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109f757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff160217905550818060010192505061080b565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a7357600080fd5b505050505050505050565b610a86611673565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b3757602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610afe5790505b50505050509050919050565b6000600654905090565b610b55611625565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610beb5780601f10610bc057610100808354040283529160200191610beb565b820191906000526020600020905b815481529060010190602001808311610bce57829003601f168201915b5050505050905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c5357600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ca357600080fd5b600090505b8151811015610e7857600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d029190611639565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610d6657fe5b9060200190602002015161ffff16815481101515610d8057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610e1057fe5b9060200190602002015161ffff16815481101515610e2a57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506006600081548092919060010191905055508080600101915050610ca8565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f0f57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f256000808a6112fa565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610fc257600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561102957600080fd5b600090505b87518110156110e157600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110889190611639565b91600052602060002090601091828204019190066002028a848151811015156110ad57fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061102e565b5050505050505050565b60008090505b81518161ffff1610156112cd57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161114f9190611639565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff168151811015156111b757fe5b9060200190602002015161ffff168154811015156111d157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561126557fe5b9060200190602002015161ffff1681548110151561127f57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060066000815480929190600101919050555080806001019150506110f1565b505050565b60006003544211156112e757600190506112ec565b600090505b90565b60008060ff16905090565b6000611304611687565b600080600285510260540160405180591061131c5750595b9080825280601f01601f1916602001820160405250925061133b61071f565b9150600090505b60208110156113a35780600802879060020a02600102838281518110151561136657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611342565b600090505b602081101561140c5780600802869060020a0260010283602083018151811015156113cf57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506113a8565b600090505b60148110156114905780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561145357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611411565b600090505b84518110156115b657600885828151811015156114ae57fe5b9060200190602002015161ffff169060020a90047f01000000000000000000000000000000000000000000000000000000000000000283600283026054018151811015156114f857fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561153657fe5b906020019060200201517f010000000000000000000000000000000000000000000000000000000000000002836001600284026054010181518110151561157957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611495565b826040518082805190602001908083835b6020831015156115ec57805182526020820191506020810190506020830392506115c7565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b81548183558181151161166e57600f016010900481600f0160109004836000526020600020918201910161166d919061169b565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b6116bd91905b808211156116b95760008160009055506001016116a1565b5090565b905600a165627a7a72305820ebc7638bd4c8a42df0b8c70cc5a2d8005a57765ef68320b29e3793dcb9ba3d0800290000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , "0xdb0ec968000000000000000000000000a2845ed453b15beb7aaf3f01adabf69e79270838000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016" + , "0xdb0ec9680000000000000000000000009f75b16cfb79f0bc11dacf149e342637864d89c80000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000d4" + , "0xdb0ec9680000000000000000000000009f75b16cfb79f0bc11dacf149e342637864d89c800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000d2" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004b" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000004c" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000028" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003f" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060065534156200003357600080fd5b60405162001a3a38038062001a3a83398101604052808051820191906020018051820191906020018051906020019091908051820191905050835160008190555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000c9929190620001aa565b508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600890805190602001906200016b9291906200025b565b508260079080519060200190620001849291906200025b565b506001600960006101000a81548160ff021916908315150217905550505050506200033e565b82805482825590600052602060002090600f01601090048101928215620002485791602002820160005b838211156200021657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001d4565b8015620002465782816101000a81549061ffff021916905560020160208160010104928301926001030262000216565b505b509050620002579190620002e2565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200029e57805160ff1916838001178555620002cf565b82800160010185558215620002cf579182015b82811115620002ce578251825591602001919060010190620002b1565b5b509050620002de919062000316565b5090565b6200031391905b808211156200030f57600081816101000a81549061ffff021916905550600101620002e9565b5090565b90565b6200033b91905b80821115620003375760008160009055506001016200031d565b5090565b90565b6116ec806200034e6000396000f3006060604052600436106100e6576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100f657806318160ddd14610184578063313ce567146101ad57806332a2c5d0146101dc5780634f452b9a1461023157806358089fc61461025e578063696ecc551461028b57806370a082311461030957806372c5cb631461039757806395d89b41146103c0578063a6fb475f1461044e578063bb6e7de9146104e6578063c2532c3d146104fb578063db0ec9681461059a578063ea8b5ca314610613578063f0141d8414610640575b34156100f157600080fd5b600080fd5b341561010157600080fd5b610109610669565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561014957808201518184015260208101905061012e565b50505050905090810190601f1680156101765780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018f57600080fd5b610197610711565b6040518082815260200191505060405180910390f35b34156101b857600080fd5b6101c061071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101e757600080fd5b6101ef61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561023c57600080fd5b610244610727565b604051808215151515815260200191505060405180910390f35b341561026957600080fd5b61027161073e565b604051808215151515815260200191505060405180910390f35b61030760048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610751565b005b341561031457600080fd5b610340600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a7e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610383578082015181840152602081019050610368565b505050509050019250505060405180910390f35b34156103a257600080fd5b6103aa610b43565b6040518082815260200191505060405180910390f35b34156103cb57600080fd5b6103d3610b4d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104135780820151818401526020810190506103f8565b50505050905090810190601f1680156104405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561045957600080fd5b6104e4600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bf5565b005b34156104f157600080fd5b6104f9610e7e565b005b341561050657600080fd5b61059860048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f14565b005b34156105a557600080fd5b610611600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506110eb565b005b341561061e57600080fd5b6106266112d2565b604051808215151515815260200191505060405180910390f35b341561064b57600080fd5b6106536112ef565b6040518082815260200191505060405180910390f35b610671611625565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107075780601f106106dc57610100808354040283529160200191610707565b820191906000526020600020905b8154815290600101906020018083116106ea57829003601f168201915b5050505050905090565b60008054905090565b600081565b600030905090565b6000600960009054906101000a900460ff16905090565b600960009054906101000a900460ff1681565b600080600080428911806107655750600089145b151561077057600080fd5b61077b348a8a6112fa565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107fb57600080fd5b5050602060405103519250600091505b8751821015610a3357878281518110151561082257fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561088057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161115156108b457600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816109059190611639565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561096857fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109f757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff160217905550818060010192505061080b565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a7357600080fd5b505050505050505050565b610a86611673565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b3757602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610afe5790505b50505050509050919050565b6000600654905090565b610b55611625565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610beb5780601f10610bc057610100808354040283529160200191610beb565b820191906000526020600020905b815481529060010190602001808311610bce57829003601f168201915b5050505050905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c5357600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ca357600080fd5b600090505b8151811015610e7857600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d029190611639565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610d6657fe5b9060200190602002015161ffff16815481101515610d8057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610e1057fe5b9060200190602002015161ffff16815481101515610e2a57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506006600081548092919060010191905055508080600101915050610ca8565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f0f57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f256000808a6112fa565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610fc257600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561102957600080fd5b600090505b87518110156110e157600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110889190611639565b91600052602060002090601091828204019190066002028a848151811015156110ad57fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061102e565b5050505050505050565b60008090505b81518161ffff1610156112cd57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161114f9190611639565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff168151811015156111b757fe5b9060200190602002015161ffff168154811015156111d157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561126557fe5b9060200190602002015161ffff1681548110151561127f57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060066000815480929190600101919050555080806001019150506110f1565b505050565b60006003544211156112e757600190506112ec565b600090505b90565b60008060ff16905090565b6000611304611687565b600080600285510260540160405180591061131c5750595b9080825280601f01601f1916602001820160405250925061133b61071f565b9150600090505b60208110156113a35780600802879060020a02600102838281518110151561136657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611342565b600090505b602081101561140c5780600802869060020a0260010283602083018151811015156113cf57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506113a8565b600090505b60148110156114905780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561145357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611411565b600090505b84518110156115b657600885828151811015156114ae57fe5b9060200190602002015161ffff169060020a90047f01000000000000000000000000000000000000000000000000000000000000000283600283026054018151811015156114f857fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561153657fe5b906020019060200201517f010000000000000000000000000000000000000000000000000000000000000002836001600284026054010181518110151561157957fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611495565b826040518082805190602001908083835b6020831015156115ec57805182526020820191506020810190506020830392506115c7565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b81548183558181151161166e57600f016010900481600f0160109004836000526020600020918201910161166d919061169b565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b6116bd91905b808211156116b95760008160009055506001016116a1565b5090565b905600a165627a7a723058207037e0229a2aef420f84573dc598a79fea426da8415b9fb6124bfbce4c0ac507002900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000001c4000000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001081000000000000000000000000000000000000000000000000000000000000108200000000000000000000000000000000000000000000000000000000000010830000000000000000000000000000000000000000000000000000000000001084000000000000000000000000000000000000000000000000000000000000108500000000000000000000000000000000000000000000000000000000000010860000000000000000000000000000000000000000000000000000000000001087000000000000000000000000000000000000000000000000000000000000108800000000000000000000000000000000000000000000000000000000000010890000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110100000000000000000000000000000000000000000000000000000000000011020000000000000000000000000000000000000000000000000000000000001103000000000000000000000000000000000000000000000000000000000000110400000000000000000000000000000000000000000000000000000000000011050000000000000000000000000000000000000000000000000000000000001106000000000000000000000000000000000000000000000000000000000000110700000000000000000000000000000000000000000000000000000000000011080000000000000000000000000000000000000000000000000000000000001109000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020010000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000200300000000000000000000000000000000000000000000000000000000000020040000000000000000000000000000000000000000000000000000000000002005000000000000000000000000000000000000000000000000000000000000200600000000000000000000000000000000000000000000000000000000000020070000000000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000200900000000000000000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000002081000000000000000000000000000000000000000000000000000000000000208200000000000000000000000000000000000000000000000000000000000020830000000000000000000000000000000000000000000000000000000000002084000000000000000000000000000000000000000000000000000000000000208500000000000000000000000000000000000000000000000000000000000020860000000000000000000000000000000000000000000000000000000000002087000000000000000000000000000000000000000000000000000000000000208800000000000000000000000000000000000000000000000000000000000020890000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000210100000000000000000000000000000000000000000000000000000000000021020000000000000000000000000000000000000000000000000000000000002103000000000000000000000000000000000000000000000000000000000000210400000000000000000000000000000000000000000000000000000000000021050000000000000000000000000000000000000000000000000000000000002106000000000000000000000000000000000000000000000000000000000000210700000000000000000000000000000000000000000000000000000000000021080000000000000000000000000000000000000000000000000000000000002109000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030010000000000000000000000000000000000000000000000000000000000003002000000000000000000000000000000000000000000000000000000000000300300000000000000000000000000000000000000000000000000000000000030040000000000000000000000000000000000000000000000000000000000003005000000000000000000000000000000000000000000000000000000000000300600000000000000000000000000000000000000000000000000000000000030070000000000000000000000000000000000000000000000000000000000003008000000000000000000000000000000000000000000000000000000000000300900000000000000000000000000000000000000000000000000000000000030800000000000000000000000000000000000000000000000000000000000003081000000000000000000000000000000000000000000000000000000000000308200000000000000000000000000000000000000000000000000000000000030830000000000000000000000000000000000000000000000000000000000003084000000000000000000000000000000000000000000000000000000000000308500000000000000000000000000000000000000000000000000000000000030860000000000000000000000000000000000000000000000000000000000003087000000000000000000000000000000000000000000000000000000000000308800000000000000000000000000000000000000000000000000000000000030890000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000310100000000000000000000000000000000000000000000000000000000000031020000000000000000000000000000000000000000000000000000000000003103000000000000000000000000000000000000000000000000000000000000310400000000000000000000000000000000000000000000000000000000000031050000000000000000000000000000000000000000000000000000000000003106000000000000000000000000000000000000000000000000000000000000310700000000000000000000000000000000000000000000000000000000000031080000000000000000000000000000000000000000000000000000000000003109000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040010000000000000000000000000000000000000000000000000000000000004002000000000000000000000000000000000000000000000000000000000000400300000000000000000000000000000000000000000000000000000000000040040000000000000000000000000000000000000000000000000000000000004005000000000000000000000000000000000000000000000000000000000000400600000000000000000000000000000000000000000000000000000000000040070000000000000000000000000000000000000000000000000000000000004008000000000000000000000000000000000000000000000000000000000000400900000000000000000000000000000000000000000000000000000000000040800000000000000000000000000000000000000000000000000000000000004081000000000000000000000000000000000000000000000000000000000000408200000000000000000000000000000000000000000000000000000000000040830000000000000000000000000000000000000000000000000000000000004084000000000000000000000000000000000000000000000000000000000000408500000000000000000000000000000000000000000000000000000000000040860000000000000000000000000000000000000000000000000000000000004087000000000000000000000000000000000000000000000000000000000000408800000000000000000000000000000000000000000000000000000000000040890000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000410100000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004103000000000000000000000000000000000000000000000000000000000000410400000000000000000000000000000000000000000000000000000000000041050000000000000000000000000000000000000000000000000000000000004106000000000000000000000000000000000000000000000000000000000000410700000000000000000000000000000000000000000000000000000000000041080000000000000000000000000000000000000000000000000000000000004109000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050010000000000000000000000000000000000000000000000000000000000005002000000000000000000000000000000000000000000000000000000000000500300000000000000000000000000000000000000000000000000000000000050040000000000000000000000000000000000000000000000000000000000005005000000000000000000000000000000000000000000000000000000000000500600000000000000000000000000000000000000000000000000000000000050070000000000000000000000000000000000000000000000000000000000005008000000000000000000000000000000000000000000000000000000000000500900000000000000000000000000000000000000000000000000000000000050800000000000000000000000000000000000000000000000000000000000005081000000000000000000000000000000000000000000000000000000000000508200000000000000000000000000000000000000000000000000000000000050830000000000000000000000000000000000000000000000000000000000005084000000000000000000000000000000000000000000000000000000000000508500000000000000000000000000000000000000000000000000000000000050860000000000000000000000000000000000000000000000000000000000005087000000000000000000000000000000000000000000000000000000000000508800000000000000000000000000000000000000000000000000000000000050890000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000510100000000000000000000000000000000000000000000000000000000000051020000000000000000000000000000000000000000000000000000000000005103000000000000000000000000000000000000000000000000000000000000510400000000000000000000000000000000000000000000000000000000000051050000000000000000000000000000000000000000000000000000000000005106000000000000000000000000000000000000000000000000000000000000510700000000000000000000000000000000000000000000000000000000000051080000000000000000000000000000000000000000000000000000000000005109000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060010000000000000000000000000000000000000000000000000000000000006002000000000000000000000000000000000000000000000000000000000000600300000000000000000000000000000000000000000000000000000000000060040000000000000000000000000000000000000000000000000000000000006005000000000000000000000000000000000000000000000000000000000000600600000000000000000000000000000000000000000000000000000000000060070000000000000000000000000000000000000000000000000000000000006008000000000000000000000000000000000000000000000000000000000000600900000000000000000000000000000000000000000000000000000000000060800000000000000000000000000000000000000000000000000000000000006081000000000000000000000000000000000000000000000000000000000000608200000000000000000000000000000000000000000000000000000000000060830000000000000000000000000000000000000000000000000000000000006084000000000000000000000000000000000000000000000000000000000000608500000000000000000000000000000000000000000000000000000000000060860000000000000000000000000000000000000000000000000000000000006087000000000000000000000000000000000000000000000000000000000000608800000000000000000000000000000000000000000000000000000000000060890000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000610100000000000000000000000000000000000000000000000000000000000061020000000000000000000000000000000000000000000000000000000000006103000000000000000000000000000000000000000000000000000000000000610400000000000000000000000000000000000000000000000000000000000061050000000000000000000000000000000000000000000000000000000000006106000000000000000000000000000000000000000000000000000000000000610700000000000000000000000000000000000000000000000000000000000061080000000000000000000000000000000000000000000000000000000000006109000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070010000000000000000000000000000000000000000000000000000000000007002000000000000000000000000000000000000000000000000000000000000700300000000000000000000000000000000000000000000000000000000000070040000000000000000000000000000000000000000000000000000000000007005000000000000000000000000000000000000000000000000000000000000700600000000000000000000000000000000000000000000000000000000000070070000000000000000000000000000000000000000000000000000000000007008000000000000000000000000000000000000000000000000000000000000700900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0xbb6e7de9" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060055534156200003357600080fd5b60405162000fd038038062000fd083398101604052808051820191906020018051820191906020018051906020019091908051820191905050835160008190555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000c992919062000169565b508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600790805190602001906200012a9291906200021a565b508260069080519060200190620001439291906200021a565b506001600860006101000a81548160ff02191690831515021790555050505050620002fd565b82805482825590600052602060002090600f01601090048101928215620002075791602002820160005b83821115620001d557835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030262000193565b8015620002055782816101000a81549061ffff0219169055600201602081600101049283019260010302620001d5565b505b509050620002169190620002a1565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025d57805160ff19168380011785556200028e565b828001600101855582156200028e579182015b828111156200028d57825182559160200191906001019062000270565b5b5090506200029d9190620002d5565b5090565b620002d291905b80821115620002ce57600081816101000a81549061ffff021916905550600101620002a8565b5090565b90565b620002fa91905b80821115620002f6576000816000905550600101620002dc565b5090565b90565b610cc3806200030d6000396000f3006060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100ca57806318160ddd14610158578063313ce567146101815780634f452b9a146101b057806370a08231146101dd57806372c5cb631461026b57806395d89b4114610294578063a6fb475f14610322578063bb6e7de9146103ba578063db0ec968146103cf578063ea8b5ca314610448578063f0141d8414610475575b34156100c557600080fd5b600080fd5b34156100d557600080fd5b6100dd61049e565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561011d578082015181840152602081019050610102565b50505050905090810190601f16801561014a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561016357600080fd5b61016b610546565b6040518082815260200191505060405180910390f35b341561018c57600080fd5b61019461054f565b604051808260ff1660ff16815260200191505060405180910390f35b34156101bb57600080fd5b6101c3610554565b604051808215151515815260200191505060405180910390f35b34156101e857600080fd5b610214600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061056b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561025757808201518184015260208101905061023c565b505050509050019250505060405180910390f35b341561027657600080fd5b61027e610630565b6040518082815260200191505060405180910390f35b341561029f57600080fd5b6102a761063a565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102e75780820151818401526020810190506102cc565b50505050905090810190601f1680156103145780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561032d57600080fd5b6103b8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506106e2565b005b34156103c557600080fd5b6103cd61096b565b005b34156103da57600080fd5b610446600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610a01565b005b341561045357600080fd5b61045b610be8565b604051808215151515815260200191505060405180910390f35b341561048057600080fd5b610488610c05565b6040518082815260200191505060405180910390f35b6104a6610c10565b60068054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561053c5780601f106105115761010080835404028352916020019161053c565b820191906000526020600020905b81548152906001019060200180831161051f57829003601f168201915b5050505050905090565b60008054905090565b600081565b6000600860009054906101000a900460ff16905090565b610573610c24565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561062457602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116105eb5790505b50505050509050919050565b6000600554905090565b610642610c10565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106d85780601f106106ad576101008083540402835291602001916106d8565b820191906000526020600020905b8154815290600101906020018083116106bb57829003601f168201915b5050505050905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561074057600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050101561079057600080fd5b600090505b815181101561096557600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816107ef9190610c38565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858581518110151561085357fe5b9060200190602002015161ffff1681548110151561086d57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083838151811015156108fd57fe5b9060200190602002015161ffff1681548110151561091757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506005600081548092919060010191905055508080600101915050610795565b50505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156109fc57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b60008090505b81518161ffff161015610be357600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610a659190610c38565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff16815181101515610acd57fe5b9060200190602002015161ffff16815481101515610ae757fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff16815181101515610b7b57fe5b9060200190602002015161ffff16815481101515610b9557fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506005600081548092919060010191905055508080600101915050610a07565b505050565b6000600354421115610bfd5760019050610c02565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b815481835581811511610c6d57600f016010900481600f01601090048360005260206000209182019101610c6c9190610c72565b5b505050565b610c9491905b80821115610c90576000816000905550600101610c78565b5090565b905600a165627a7a72305820212b7b59296e18695c347b474d7d655c250fd94e27f00f051ef88cb281d6632a002900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000001c4000000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001081000000000000000000000000000000000000000000000000000000000000108200000000000000000000000000000000000000000000000000000000000010830000000000000000000000000000000000000000000000000000000000001084000000000000000000000000000000000000000000000000000000000000108500000000000000000000000000000000000000000000000000000000000010860000000000000000000000000000000000000000000000000000000000001087000000000000000000000000000000000000000000000000000000000000108800000000000000000000000000000000000000000000000000000000000010890000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110100000000000000000000000000000000000000000000000000000000000011020000000000000000000000000000000000000000000000000000000000001103000000000000000000000000000000000000000000000000000000000000110400000000000000000000000000000000000000000000000000000000000011050000000000000000000000000000000000000000000000000000000000001106000000000000000000000000000000000000000000000000000000000000110700000000000000000000000000000000000000000000000000000000000011080000000000000000000000000000000000000000000000000000000000001109000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020010000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000200300000000000000000000000000000000000000000000000000000000000020040000000000000000000000000000000000000000000000000000000000002005000000000000000000000000000000000000000000000000000000000000200600000000000000000000000000000000000000000000000000000000000020070000000000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000200900000000000000000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000002081000000000000000000000000000000000000000000000000000000000000208200000000000000000000000000000000000000000000000000000000000020830000000000000000000000000000000000000000000000000000000000002084000000000000000000000000000000000000000000000000000000000000208500000000000000000000000000000000000000000000000000000000000020860000000000000000000000000000000000000000000000000000000000002087000000000000000000000000000000000000000000000000000000000000208800000000000000000000000000000000000000000000000000000000000020890000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000210100000000000000000000000000000000000000000000000000000000000021020000000000000000000000000000000000000000000000000000000000002103000000000000000000000000000000000000000000000000000000000000210400000000000000000000000000000000000000000000000000000000000021050000000000000000000000000000000000000000000000000000000000002106000000000000000000000000000000000000000000000000000000000000210700000000000000000000000000000000000000000000000000000000000021080000000000000000000000000000000000000000000000000000000000002109000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030010000000000000000000000000000000000000000000000000000000000003002000000000000000000000000000000000000000000000000000000000000300300000000000000000000000000000000000000000000000000000000000030040000000000000000000000000000000000000000000000000000000000003005000000000000000000000000000000000000000000000000000000000000300600000000000000000000000000000000000000000000000000000000000030070000000000000000000000000000000000000000000000000000000000003008000000000000000000000000000000000000000000000000000000000000300900000000000000000000000000000000000000000000000000000000000030800000000000000000000000000000000000000000000000000000000000003081000000000000000000000000000000000000000000000000000000000000308200000000000000000000000000000000000000000000000000000000000030830000000000000000000000000000000000000000000000000000000000003084000000000000000000000000000000000000000000000000000000000000308500000000000000000000000000000000000000000000000000000000000030860000000000000000000000000000000000000000000000000000000000003087000000000000000000000000000000000000000000000000000000000000308800000000000000000000000000000000000000000000000000000000000030890000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000310100000000000000000000000000000000000000000000000000000000000031020000000000000000000000000000000000000000000000000000000000003103000000000000000000000000000000000000000000000000000000000000310400000000000000000000000000000000000000000000000000000000000031050000000000000000000000000000000000000000000000000000000000003106000000000000000000000000000000000000000000000000000000000000310700000000000000000000000000000000000000000000000000000000000031080000000000000000000000000000000000000000000000000000000000003109000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040010000000000000000000000000000000000000000000000000000000000004002000000000000000000000000000000000000000000000000000000000000400300000000000000000000000000000000000000000000000000000000000040040000000000000000000000000000000000000000000000000000000000004005000000000000000000000000000000000000000000000000000000000000400600000000000000000000000000000000000000000000000000000000000040070000000000000000000000000000000000000000000000000000000000004008000000000000000000000000000000000000000000000000000000000000400900000000000000000000000000000000000000000000000000000000000040800000000000000000000000000000000000000000000000000000000000004081000000000000000000000000000000000000000000000000000000000000408200000000000000000000000000000000000000000000000000000000000040830000000000000000000000000000000000000000000000000000000000004084000000000000000000000000000000000000000000000000000000000000408500000000000000000000000000000000000000000000000000000000000040860000000000000000000000000000000000000000000000000000000000004087000000000000000000000000000000000000000000000000000000000000408800000000000000000000000000000000000000000000000000000000000040890000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000410100000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004103000000000000000000000000000000000000000000000000000000000000410400000000000000000000000000000000000000000000000000000000000041050000000000000000000000000000000000000000000000000000000000004106000000000000000000000000000000000000000000000000000000000000410700000000000000000000000000000000000000000000000000000000000041080000000000000000000000000000000000000000000000000000000000004109000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050010000000000000000000000000000000000000000000000000000000000005002000000000000000000000000000000000000000000000000000000000000500300000000000000000000000000000000000000000000000000000000000050040000000000000000000000000000000000000000000000000000000000005005000000000000000000000000000000000000000000000000000000000000500600000000000000000000000000000000000000000000000000000000000050070000000000000000000000000000000000000000000000000000000000005008000000000000000000000000000000000000000000000000000000000000500900000000000000000000000000000000000000000000000000000000000050800000000000000000000000000000000000000000000000000000000000005081000000000000000000000000000000000000000000000000000000000000508200000000000000000000000000000000000000000000000000000000000050830000000000000000000000000000000000000000000000000000000000005084000000000000000000000000000000000000000000000000000000000000508500000000000000000000000000000000000000000000000000000000000050860000000000000000000000000000000000000000000000000000000000005087000000000000000000000000000000000000000000000000000000000000508800000000000000000000000000000000000000000000000000000000000050890000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000510100000000000000000000000000000000000000000000000000000000000051020000000000000000000000000000000000000000000000000000000000005103000000000000000000000000000000000000000000000000000000000000510400000000000000000000000000000000000000000000000000000000000051050000000000000000000000000000000000000000000000000000000000005106000000000000000000000000000000000000000000000000000000000000510700000000000000000000000000000000000000000000000000000000000051080000000000000000000000000000000000000000000000000000000000005109000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060010000000000000000000000000000000000000000000000000000000000006002000000000000000000000000000000000000000000000000000000000000600300000000000000000000000000000000000000000000000000000000000060040000000000000000000000000000000000000000000000000000000000006005000000000000000000000000000000000000000000000000000000000000600600000000000000000000000000000000000000000000000000000000000060070000000000000000000000000000000000000000000000000000000000006008000000000000000000000000000000000000000000000000000000000000600900000000000000000000000000000000000000000000000000000000000060800000000000000000000000000000000000000000000000000000000000006081000000000000000000000000000000000000000000000000000000000000608200000000000000000000000000000000000000000000000000000000000060830000000000000000000000000000000000000000000000000000000000006084000000000000000000000000000000000000000000000000000000000000608500000000000000000000000000000000000000000000000000000000000060860000000000000000000000000000000000000000000000000000000000006087000000000000000000000000000000000000000000000000000000000000608800000000000000000000000000000000000000000000000000000000000060890000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000610100000000000000000000000000000000000000000000000000000000000061020000000000000000000000000000000000000000000000000000000000006103000000000000000000000000000000000000000000000000000000000000610400000000000000000000000000000000000000000000000000000000000061050000000000000000000000000000000000000000000000000000000000006106000000000000000000000000000000000000000000000000000000000000610700000000000000000000000000000000000000000000000000000000000061080000000000000000000000000000000000000000000000000000000000006109000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070010000000000000000000000000000000000000000000000000000000000007002000000000000000000000000000000000000000000000000000000000000700300000000000000000000000000000000000000000000000000000000000070040000000000000000000000000000000000000000000000000000000000007005000000000000000000000000000000000000000000000000000000000000700600000000000000000000000000000000000000000000000000000000000070070000000000000000000000000000000000000000000000000000000000007008000000000000000000000000000000000000000000000000000000000000700900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0x4f452b9a" + , "0xbb6e7de9" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b" + , "0x4f452b9a" + , "0x4f452b9a" + , "0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b604051620015043803806200150483398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191905050845160008190555084600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000d29291906200015f565b508260048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160068190555080600990805190602001906200013a92919062000210565b5083600890805190602001906200015392919062000210565b505050505050620002f3565b82805482825590600052602060002090600f01601090048101928215620001fd5791602002820160005b83821115620001cb57835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030262000189565b8015620001fb5782816101000a81549061ffff0219169055600201602081600101049283019260010302620001cb565b505b5090506200020c919062000297565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025357805160ff191683800117855562000284565b8280016001018555821562000284579182015b828111156200028357825182559160200191906001019062000266565b5b509050620002939190620002cb565b5090565b620002c891905b80821115620002c457600081816101000a81549061ffff0219169055506001016200029e565b5090565b90565b620002f091905b80821115620002ec576000816000905550600101620002d2565b5090565b90565b61120180620003036000396000f3006060604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100e05780630e1c2d461461016e57806318160ddd146101c8578063313ce567146101f15780634f452b9a1461022057806370a082311461024d57806372c5cb63146102db57806395d89b4114610304578063a6fb475f14610392578063bb6e7de91461042a578063c2bf17b01461043f578063db0ec968146104ed578063ea8b5ca314610566578063f0141d8414610593575b34156100db57600080fd5b600080fd5b34156100eb57600080fd5b6100f36105bc565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610133578082015181840152602081019050610118565b50505050905090810190601f1680156101605780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101ae60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610664565b604051808215151515815260200191505060405180910390f35b34156101d357600080fd5b6101db6107f1565b6040518082815260200191505060405180910390f35b34156101fc57600080fd5b6102046107fa565b604051808260ff1660ff16815260200191505060405180910390f35b341561022b57600080fd5b6102336107ff565b604051808215151515815260200191505060405180910390f35b341561025857600080fd5b610284600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610808565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102c75780820151818401526020810190506102ac565b505050509050019250505060405180910390f35b34156102e657600080fd5b6102ee6108cd565b6040518082815260200191505060405180910390f35b341561030f57600080fd5b6103176108d7565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561035757808201518184015260208101905061033c565b50505050905090810190601f1680156103845780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561039d57600080fd5b610428600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061097f565b005b341561043557600080fd5b61043d610c76565b005b341561044a57600080fd5b61048a60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610d0c565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156104f857600080fd5b610564600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610e80565b005b341561057157600080fd5b610579611126565b604051808215151515815260200191505060405180910390f35b341561059e57600080fd5b6105a6611143565b6040518082815260200191505060405180910390f35b6105c461114e565b60088054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561065a5780601f1061062f5761010080835404028352916020019161065a565b820191906000526020600020905b81548152906001019060200180831161063d57829003601f168201915b5050505050905090565b60008060008060008060008061067c8c8c8c8c610d0c565b96509650965096508561ffff168502925083801561069957508234145b156107dd57600654348115156106ab57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156106f357600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050151561075557600080fd5b60076000815480929190600101919050555085600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550600197506107e2565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b60006001905090565b610810611162565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156108c157602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116108885790505b50505050509050919050565b6000600754905090565b6108df61114e565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109755780601f1061094a57610100808354040283529160200191610975565b820191906000526020600020905b81548152906001019060200180831161095857829003601f168201915b5050505050905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156109dd57600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610a2d57600080fd5b600090505b8151811015610c0257600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610a8c9190611176565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610af057fe5b9060200190602002015161ffff16815481101515610b0a57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610b9a57fe5b9060200190602002015161ffff16815481101515610bb457fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610a32565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555050505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610d0757600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610dbb57600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff16600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050031015610e705760009050610e75565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ed257600080fd5b600090505b81518161ffff1610156110b357600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610f359190611176565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff16815181101515610f9d57fe5b9060200190602002015161ffff16815481101515610fb757fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561104b57fe5b9060200190602002015161ffff1681548110151561106557fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610ed7565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550505050565b600060045442111561113b5760019050611140565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b8154818355818115116111ab57600f016010900481600f016010900483600052602060002091820191016111aa91906111b0565b5b505050565b6111d291905b808211156111ce5760008160009055506001016111b6565b5090565b905600a165627a7a72305820da22677d7b59f2e0bfb17b922124b5c626653f72e3fbf15e60ff47e0065dbcee002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000001c20000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000001c6000000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001081000000000000000000000000000000000000000000000000000000000000108200000000000000000000000000000000000000000000000000000000000010830000000000000000000000000000000000000000000000000000000000001084000000000000000000000000000000000000000000000000000000000000108500000000000000000000000000000000000000000000000000000000000010860000000000000000000000000000000000000000000000000000000000001087000000000000000000000000000000000000000000000000000000000000108800000000000000000000000000000000000000000000000000000000000010890000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110100000000000000000000000000000000000000000000000000000000000011020000000000000000000000000000000000000000000000000000000000001103000000000000000000000000000000000000000000000000000000000000110400000000000000000000000000000000000000000000000000000000000011050000000000000000000000000000000000000000000000000000000000001106000000000000000000000000000000000000000000000000000000000000110700000000000000000000000000000000000000000000000000000000000011080000000000000000000000000000000000000000000000000000000000001109000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020010000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000200300000000000000000000000000000000000000000000000000000000000020040000000000000000000000000000000000000000000000000000000000002005000000000000000000000000000000000000000000000000000000000000200600000000000000000000000000000000000000000000000000000000000020070000000000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000200900000000000000000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000002081000000000000000000000000000000000000000000000000000000000000208200000000000000000000000000000000000000000000000000000000000020830000000000000000000000000000000000000000000000000000000000002084000000000000000000000000000000000000000000000000000000000000208500000000000000000000000000000000000000000000000000000000000020860000000000000000000000000000000000000000000000000000000000002087000000000000000000000000000000000000000000000000000000000000208800000000000000000000000000000000000000000000000000000000000020890000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000210100000000000000000000000000000000000000000000000000000000000021020000000000000000000000000000000000000000000000000000000000002103000000000000000000000000000000000000000000000000000000000000210400000000000000000000000000000000000000000000000000000000000021050000000000000000000000000000000000000000000000000000000000002106000000000000000000000000000000000000000000000000000000000000210700000000000000000000000000000000000000000000000000000000000021080000000000000000000000000000000000000000000000000000000000002109000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030010000000000000000000000000000000000000000000000000000000000003002000000000000000000000000000000000000000000000000000000000000300300000000000000000000000000000000000000000000000000000000000030040000000000000000000000000000000000000000000000000000000000003005000000000000000000000000000000000000000000000000000000000000300600000000000000000000000000000000000000000000000000000000000030070000000000000000000000000000000000000000000000000000000000003008000000000000000000000000000000000000000000000000000000000000300900000000000000000000000000000000000000000000000000000000000030800000000000000000000000000000000000000000000000000000000000003081000000000000000000000000000000000000000000000000000000000000308200000000000000000000000000000000000000000000000000000000000030830000000000000000000000000000000000000000000000000000000000003084000000000000000000000000000000000000000000000000000000000000308500000000000000000000000000000000000000000000000000000000000030860000000000000000000000000000000000000000000000000000000000003087000000000000000000000000000000000000000000000000000000000000308800000000000000000000000000000000000000000000000000000000000030890000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000310100000000000000000000000000000000000000000000000000000000000031020000000000000000000000000000000000000000000000000000000000003103000000000000000000000000000000000000000000000000000000000000310400000000000000000000000000000000000000000000000000000000000031050000000000000000000000000000000000000000000000000000000000003106000000000000000000000000000000000000000000000000000000000000310700000000000000000000000000000000000000000000000000000000000031080000000000000000000000000000000000000000000000000000000000003109000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040010000000000000000000000000000000000000000000000000000000000004002000000000000000000000000000000000000000000000000000000000000400300000000000000000000000000000000000000000000000000000000000040040000000000000000000000000000000000000000000000000000000000004005000000000000000000000000000000000000000000000000000000000000400600000000000000000000000000000000000000000000000000000000000040070000000000000000000000000000000000000000000000000000000000004008000000000000000000000000000000000000000000000000000000000000400900000000000000000000000000000000000000000000000000000000000040800000000000000000000000000000000000000000000000000000000000004081000000000000000000000000000000000000000000000000000000000000408200000000000000000000000000000000000000000000000000000000000040830000000000000000000000000000000000000000000000000000000000004084000000000000000000000000000000000000000000000000000000000000408500000000000000000000000000000000000000000000000000000000000040860000000000000000000000000000000000000000000000000000000000004087000000000000000000000000000000000000000000000000000000000000408800000000000000000000000000000000000000000000000000000000000040890000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000410100000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004103000000000000000000000000000000000000000000000000000000000000410400000000000000000000000000000000000000000000000000000000000041050000000000000000000000000000000000000000000000000000000000004106000000000000000000000000000000000000000000000000000000000000410700000000000000000000000000000000000000000000000000000000000041080000000000000000000000000000000000000000000000000000000000004109000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050010000000000000000000000000000000000000000000000000000000000005002000000000000000000000000000000000000000000000000000000000000500300000000000000000000000000000000000000000000000000000000000050040000000000000000000000000000000000000000000000000000000000005005000000000000000000000000000000000000000000000000000000000000500600000000000000000000000000000000000000000000000000000000000050070000000000000000000000000000000000000000000000000000000000005008000000000000000000000000000000000000000000000000000000000000500900000000000000000000000000000000000000000000000000000000000050800000000000000000000000000000000000000000000000000000000000005081000000000000000000000000000000000000000000000000000000000000508200000000000000000000000000000000000000000000000000000000000050830000000000000000000000000000000000000000000000000000000000005084000000000000000000000000000000000000000000000000000000000000508500000000000000000000000000000000000000000000000000000000000050860000000000000000000000000000000000000000000000000000000000005087000000000000000000000000000000000000000000000000000000000000508800000000000000000000000000000000000000000000000000000000000050890000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000510100000000000000000000000000000000000000000000000000000000000051020000000000000000000000000000000000000000000000000000000000005103000000000000000000000000000000000000000000000000000000000000510400000000000000000000000000000000000000000000000000000000000051050000000000000000000000000000000000000000000000000000000000005106000000000000000000000000000000000000000000000000000000000000510700000000000000000000000000000000000000000000000000000000000051080000000000000000000000000000000000000000000000000000000000005109000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060010000000000000000000000000000000000000000000000000000000000006002000000000000000000000000000000000000000000000000000000000000600300000000000000000000000000000000000000000000000000000000000060040000000000000000000000000000000000000000000000000000000000006005000000000000000000000000000000000000000000000000000000000000600600000000000000000000000000000000000000000000000000000000000060070000000000000000000000000000000000000000000000000000000000006008000000000000000000000000000000000000000000000000000000000000600900000000000000000000000000000000000000000000000000000000000060800000000000000000000000000000000000000000000000000000000000006081000000000000000000000000000000000000000000000000000000000000608200000000000000000000000000000000000000000000000000000000000060830000000000000000000000000000000000000000000000000000000000006084000000000000000000000000000000000000000000000000000000000000608500000000000000000000000000000000000000000000000000000000000060860000000000000000000000000000000000000000000000000000000000006087000000000000000000000000000000000000000000000000000000000000608800000000000000000000000000000000000000000000000000000000000060890000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000610100000000000000000000000000000000000000000000000000000000000061020000000000000000000000000000000000000000000000000000000000006103000000000000000000000000000000000000000000000000000000000000610400000000000000000000000000000000000000000000000000000000000061050000000000000000000000000000000000000000000000000000000000006106000000000000000000000000000000000000000000000000000000000000610700000000000000000000000000000000000000000000000000000000000061080000000000000000000000000000000000000000000000000000000000006109000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070010000000000000000000000000000000000000000000000000000000000007002000000000000000000000000000000000000000000000000000000000000700300000000000000000000000000000000000000000000000000000000000070040000000000000000000000000000000000000000000000000000000000007005000000000000000000000000000000000000000000000000000000000000700600000000000000000000000000000000000000000000000000000000000070070000000000000000000000000000000000000000000000000000000000007008000000000000000000000000000000000000000000000000000000000000700900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b6040516200140d3803806200140d83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191905050845160008190555084600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000d29291906200015f565b508260048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160068190555080600990805190602001906200013a92919062000210565b5083600890805190602001906200015392919062000210565b505050505050620002f3565b82805482825590600052602060002090600f01601090048101928215620001fd5791602002820160005b83821115620001cb57835183826101000a81548161ffff021916908361ffff160217905550926020019260020160208160010104928301926001030262000189565b8015620001fb5782816101000a81549061ffff0219169055600201602081600101049283019260010302620001cb565b505b5090506200020c919062000297565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025357805160ff191683800117855562000284565b8280016001018555821562000284579182015b828111156200028357825182559160200191906001019062000266565b5b509050620002939190620002cb565b5090565b620002c891905b80821115620002c457600081816101000a81549061ffff0219169055506001016200029e565b5090565b90565b620002f091905b80821115620002ec576000816000905550600101620002d2565b5090565b90565b61110a80620003036000396000f3006060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100ca5780630e1c2d461461015857806318160ddd146101b2578063313ce567146101db57806370a082311461020a57806372c5cb631461029857806395d89b41146102c1578063a6fb475f1461034f578063c2bf17b0146103e7578063db0ec96814610495578063ea8b5ca31461050e578063f0141d841461053b575b34156100c557600080fd5b600080fd5b34156100d557600080fd5b6100dd610564565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561011d578082015181840152602081019050610102565b50505050905090810190601f16801561014a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61019860048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061060c565b604051808215151515815260200191505060405180910390f35b34156101bd57600080fd5b6101c5610799565b6040518082815260200191505060405180910390f35b34156101e657600080fd5b6101ee6107a2565b604051808260ff1660ff16815260200191505060405180910390f35b341561021557600080fd5b610241600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506107a7565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610284578082015181840152602081019050610269565b505050509050019250505060405180910390f35b34156102a357600080fd5b6102ab61086c565b6040518082815260200191505060405180910390f35b34156102cc57600080fd5b6102d4610876565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103145780820151818401526020810190506102f9565b50505050905090810190601f1680156103415780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561035a57600080fd5b6103e5600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061091e565b005b34156103f257600080fd5b61043260048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610c15565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156104a057600080fd5b61050c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610d89565b005b341561051957600080fd5b61052161102f565b604051808215151515815260200191505060405180910390f35b341561054657600080fd5b61054e61104c565b6040518082815260200191505060405180910390f35b61056c611057565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106025780601f106105d757610100808354040283529160200191610602565b820191906000526020600020905b8154815290600101906020018083116105e557829003601f168201915b5050505050905090565b6000806000806000806000806106248c8c8c8c610c15565b96509650965096508561ffff168502925083801561064157508234145b15610785576006543481151561065357fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561069b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f1935050505015156106fd57600080fd5b60076000815480929190600101919050555085600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff1602179055506001975061078a565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b6107af61106b565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561086057602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116108275790505b50505050509050919050565b6000600754905090565b61087e611057565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109145780601f106108e957610100808354040283529160200191610914565b820191906000526020600020905b8154815290600101906020018083116108f757829003601f168201915b5050505050905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561097c57600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905010156109cc57600080fd5b600090505b8151811015610ba157600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610a2b919061107f565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610a8f57fe5b9060200190602002015161ffff16815481101515610aa957fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610b3957fe5b9060200190602002015161ffff16815481101515610b5357fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060076000815480929190600101919050555080806001019150506109d1565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555050505050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610cc457600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff16600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050031015610d795760009050610d7e565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ddb57600080fd5b600090505b81518161ffff161015610fbc57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610e3e919061107f565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff16815181101515610ea657fe5b9060200190602002015161ffff16815481101515610ec057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff16815181101515610f5457fe5b9060200190602002015161ffff16815481101515610f6e57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610de0565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550505050565b60006004544211156110445760019050611049565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b8154818355818115116110b457600f016010900481600f016010900483600052602060002091820191016110b391906110b9565b5b505050565b6110db91905b808211156110d75760008160009055506001016110bf565b5090565b905600a165627a7a72305820edfba7b75aafb1845e5a8e62910bcf04a3dd20bd79e6e310ea3bb875fa4862af002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000002660000000000000000000000000000000000000000000000000000000000000012b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000105000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000001070000000000000000000000000000000000000000000000000000000000000108000000000000000000000000000000000000000000000000000000000000010900000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000000010030000000000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000000000000000000000000000100500000000000000000000000000000000000000000000000000000000000010060000000000000000000000000000000000000000000000000000000000001007000000000000000000000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000010090000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000108100000000000000000000000000000000000000000000000000000000000010820000000000000000000000000000000000000000000000000000000000001083000000000000000000000000000000000000000000000000000000000000108400000000000000000000000000000000000000000000000000000000000010850000000000000000000000000000000000000000000000000000000000001086000000000000000000000000000000000000000000000000000000000000108700000000000000000000000000000000000000000000000000000000000010880000000000000000000000000000000000000000000000000000000000001089000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000011010000000000000000000000000000000000000000000000000000000000001102000000000000000000000000000000000000000000000000000000000000110300000000000000000000000000000000000000000000000000000000000011040000000000000000000000000000000000000000000000000000000000001105000000000000000000000000000000000000000000000000000000000000110600000000000000000000000000000000000000000000000000000000000011070000000000000000000000000000000000000000000000000000000000001108000000000000000000000000000000000000000000000000000000000000110900000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000000000000000000000000000000000000000000200200000000000000000000000000000000000000000000000000000000000020030000000000000000000000000000000000000000000000000000000000002004000000000000000000000000000000000000000000000000000000000000200500000000000000000000000000000000000000000000000000000000000020060000000000000000000000000000000000000000000000000000000000002007000000000000000000000000000000000000000000000000000000000000200800000000000000000000000000000000000000000000000000000000000020090000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000208100000000000000000000000000000000000000000000000000000000000020820000000000000000000000000000000000000000000000000000000000002083000000000000000000000000000000000000000000000000000000000000208400000000000000000000000000000000000000000000000000000000000020850000000000000000000000000000000000000000000000000000000000002086000000000000000000000000000000000000000000000000000000000000208700000000000000000000000000000000000000000000000000000000000020880000000000000000000000000000000000000000000000000000000000002089000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021010000000000000000000000000000000000000000000000000000000000002102000000000000000000000000000000000000000000000000000000000000210300000000000000000000000000000000000000000000000000000000000021040000000000000000000000000000000000000000000000000000000000002105000000000000000000000000000000000000000000000000000000000000210600000000000000000000000000000000000000000000000000000000000021070000000000000000000000000000000000000000000000000000000000002108000000000000000000000000000000000000000000000000000000000000210900000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003001000000000000000000000000000000000000000000000000000000000000300200000000000000000000000000000000000000000000000000000000000030030000000000000000000000000000000000000000000000000000000000003004000000000000000000000000000000000000000000000000000000000000300500000000000000000000000000000000000000000000000000000000000030060000000000000000000000000000000000000000000000000000000000003007000000000000000000000000000000000000000000000000000000000000300800000000000000000000000000000000000000000000000000000000000030090000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000308100000000000000000000000000000000000000000000000000000000000030820000000000000000000000000000000000000000000000000000000000003083000000000000000000000000000000000000000000000000000000000000308400000000000000000000000000000000000000000000000000000000000030850000000000000000000000000000000000000000000000000000000000003086000000000000000000000000000000000000000000000000000000000000308700000000000000000000000000000000000000000000000000000000000030880000000000000000000000000000000000000000000000000000000000003089000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031010000000000000000000000000000000000000000000000000000000000003102000000000000000000000000000000000000000000000000000000000000310300000000000000000000000000000000000000000000000000000000000031040000000000000000000000000000000000000000000000000000000000003105000000000000000000000000000000000000000000000000000000000000310600000000000000000000000000000000000000000000000000000000000031070000000000000000000000000000000000000000000000000000000000003108000000000000000000000000000000000000000000000000000000000000310900000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004001000000000000000000000000000000000000000000000000000000000000400200000000000000000000000000000000000000000000000000000000000040030000000000000000000000000000000000000000000000000000000000004004000000000000000000000000000000000000000000000000000000000000400500000000000000000000000000000000000000000000000000000000000040060000000000000000000000000000000000000000000000000000000000004007000000000000000000000000000000000000000000000000000000000000400800000000000000000000000000000000000000000000000000000000000040090000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000408100000000000000000000000000000000000000000000000000000000000040820000000000000000000000000000000000000000000000000000000000004083000000000000000000000000000000000000000000000000000000000000408400000000000000000000000000000000000000000000000000000000000040850000000000000000000000000000000000000000000000000000000000004086000000000000000000000000000000000000000000000000000000000000408700000000000000000000000000000000000000000000000000000000000040880000000000000000000000000000000000000000000000000000000000004089000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004102000000000000000000000000000000000000000000000000000000000000410300000000000000000000000000000000000000000000000000000000000041040000000000000000000000000000000000000000000000000000000000004105000000000000000000000000000000000000000000000000000000000000410600000000000000000000000000000000000000000000000000000000000041070000000000000000000000000000000000000000000000000000000000004108000000000000000000000000000000000000000000000000000000000000410900000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005001000000000000000000000000000000000000000000000000000000000000500200000000000000000000000000000000000000000000000000000000000050030000000000000000000000000000000000000000000000000000000000005004000000000000000000000000000000000000000000000000000000000000500500000000000000000000000000000000000000000000000000000000000050060000000000000000000000000000000000000000000000000000000000005007000000000000000000000000000000000000000000000000000000000000500800000000000000000000000000000000000000000000000000000000000050090000000000000000000000000000000000000000000000000000000000005080000000000000000000000000000000000000000000000000000000000000508100000000000000000000000000000000000000000000000000000000000050820000000000000000000000000000000000000000000000000000000000005083000000000000000000000000000000000000000000000000000000000000508400000000000000000000000000000000000000000000000000000000000050850000000000000000000000000000000000000000000000000000000000005086000000000000000000000000000000000000000000000000000000000000508700000000000000000000000000000000000000000000000000000000000050880000000000000000000000000000000000000000000000000000000000005089000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000051010000000000000000000000000000000000000000000000000000000000005102000000000000000000000000000000000000000000000000000000000000510300000000000000000000000000000000000000000000000000000000000051040000000000000000000000000000000000000000000000000000000000005105000000000000000000000000000000000000000000000000000000000000510600000000000000000000000000000000000000000000000000000000000051070000000000000000000000000000000000000000000000000000000000005108000000000000000000000000000000000000000000000000000000000000510900000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006001000000000000000000000000000000000000000000000000000000000000600200000000000000000000000000000000000000000000000000000000000060030000000000000000000000000000000000000000000000000000000000006004000000000000000000000000000000000000000000000000000000000000600500000000000000000000000000000000000000000000000000000000000060060000000000000000000000000000000000000000000000000000000000006007000000000000000000000000000000000000000000000000000000000000600800000000000000000000000000000000000000000000000000000000000060090000000000000000000000000000000000000000000000000000000000006080000000000000000000000000000000000000000000000000000000000000608100000000000000000000000000000000000000000000000000000000000060820000000000000000000000000000000000000000000000000000000000006083000000000000000000000000000000000000000000000000000000000000608400000000000000000000000000000000000000000000000000000000000060850000000000000000000000000000000000000000000000000000000000006086000000000000000000000000000000000000000000000000000000000000608700000000000000000000000000000000000000000000000000000000000060880000000000000000000000000000000000000000000000000000000000006089000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061010000000000000000000000000000000000000000000000000000000000006102000000000000000000000000000000000000000000000000000000000000610300000000000000000000000000000000000000000000000000000000000061040000000000000000000000000000000000000000000000000000000000006105000000000000000000000000000000000000000000000000000000000000610600000000000000000000000000000000000000000000000000000000000061070000000000000000000000000000000000000000000000000000000000006108000000000000000000000000000000000000000000000000000000000000610900000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007001000000000000000000000000000000000000000000000000000000000000700200000000000000000000000000000000000000000000000000000000000070030000000000000000000000000000000000000000000000000000000000007004000000000000000000000000000000000000000000000000000000000000700500000000000000000000000000000000000000000000000000000000000070060000000000000000000000000000000000000000000000000000000000007007000000000000000000000000000000000000000000000000000000000000700800000000000000000000000000000000000000000000000000000000000070090000000000000000000000000000000000000000000000000000000000007080000000000000000000000000000000000000000000000000000000000000708100000000000000000000000000000000000000000000000000000000000070820000000000000000000000000000000000000000000000000000000000007083000000000000000000000000000000000000000000000000000000000000708400000000000000000000000000000000000000000000000000000000000070850000000000000000000000000000000000000000000000000000000000007086000000000000000000000000000000000000000000000000000000000000708700000000000000000000000000000000000000000000000000000000000070880000000000000000000000000000000000000000000000000000000000007089000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071010000000000000000000000000000000000000000000000000000000000007102000000000000000000000000000000000000000000000000000000000000710300000000000000000000000000000000000000000000000000000000000071040000000000000000000000000000000000000000000000000000000000007105000000000000000000000000000000000000000000000000000000000000710600000000000000000000000000000000000000000000000000000000000071070000000000000000000000000000000000000000000000000000000000007108000000000000000000000000000000000000000000000000000000000000710900000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000800200000000000000000000000000000000000000000000000000000000000080030000000000000000000000000000000000000000000000000000000000008004000000000000000000000000000000000000000000000000000000000000800500000000000000000000000000000000000000000000000000000000000080060000000000000000000000000000000000000000000000000000000000008007000000000000000000000000000000000000000000000000000000000000800800000000000000000000000000000000000000000000000000000000000080090000000000000000000000000000000000000000000000000000000000008080000000000000000000000000000000000000000000000000000000000000808100000000000000000000000000000000000000000000000000000000000080820000000000000000000000000000000000000000000000000000000000008083000000000000000000000000000000000000000000000000000000000000808400000000000000000000000000000000000000000000000000000000000080850000000000000000000000000000000000000000000000000000000000008086000000000000000000000000000000000000000000000000000000000000808700000000000000000000000000000000000000000000000000000000000080880000000000000000000000000000000000000000000000000000000000008089000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008102000000000000000000000000000000000000000000000000000000000000810300000000000000000000000000000000000000000000000000000000000081040000000000000000000000000000000000000000000000000000000000008105000000000000000000000000000000000000000000000000000000000000810600000000000000000000000000000000000000000000000000000000000081070000000000000000000000000000000000000000000000000000000000008108000000000000000000000000000000000000000000000000000000000000810900000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009001000000000000000000000000000000000000000000000000000000000000900200000000000000000000000000000000000000000000000000000000000090030000000000000000000000000000000000000000000000000000000000009004000000000000000000000000000000000000000000000000000000000000900500000000000000000000000000000000000000000000000000000000000090060000000000000000000000000000000000000000000000000000000000009007000000000000000000000000000000000000000000000000000000000000900800000000000000000000000000000000000000000000000000000000000090090000000000000000000000000000000000000000000000000000000000009080000000000000000000000000000000000000000000000000000000000000908100000000000000000000000000000000000000000000000000000000000090820000000000000000000000000000000000000000000000000000000000009083000000000000000000000000000000000000000000000000000000000000908400000000000000000000000000000000000000000000000000000000000090850000000000000000000000000000000000000000000000000000000000009086000000000000000000000000000000000000000000000000000000000000908700000000000000000000000000000000000000000000000000000000000090880000000000000000000000000000000000000000000000000000000000009089000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000091010000000000000000000000000000000000000000000000000000000000009102000000000000000000000000000000000000000000000000000000000000910300000000000000000000000000000000000000000000000000000000000091040000000000000000000000000000000000000000000000000000000000009105000000000000000000000000000000000000000000000000000000000000910600000000000000000000000000000000000000000000000000000000000091070000000000000000000000000000000000000000000000000000000000009108000000000000000000000000000000000000000000000000000000000000910900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001b7a38038062001b7a8339810160405280805182019190602001805182019190602001805190602001909190805182019190505083516000819055508160038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620001529291906200018f565b5080600990805190602001906200016b92919062000240565b5082600890805190602001906200018492919062000240565b505050505062000323565b82805482825590600052602060002090600f016010900481019282156200022d5791602002820160005b83821115620001fb57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001b9565b80156200022b5782816101000a81549061ffff0219169055600201602081600101049283019260010302620001fb565b505b5090506200023c9190620002c7565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200028357805160ff1916838001178555620002b4565b82800160010185558215620002b4579182015b82811115620002b357825182559160200191906001019062000296565b5b509050620002c39190620002fb565b5090565b620002f891905b80821115620002f457600081816101000a81549061ffff021916905550600101620002ce565b5090565b90565b6200032091905b808211156200031c57600081600090555060010162000302565b5090565b90565b61184780620003336000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063696ecc551461022a57806370a08231146102a857806372c5cb631461033657806395d89b411461035f578063a6fb475f146103ed578063bb6e7de914610485578063c2532c3d1461049a578063c9116b6914610539578063db0ec968146105a3578063ea8b5ca31461061c578063f0141d8414610649575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b6102a660048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610730565b005b34156102b357600080fd5b6102df600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a5d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610322578082015181840152602081019050610307565b505050509050019250505060405180910390f35b341561034157600080fd5b610349610b22565b6040518082815260200191505060405180910390f35b341561036a57600080fd5b610372610b2c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103b2578082015181840152602081019050610397565b50505050905090810190601f1680156103df5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103f857600080fd5b610483600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bd4565b005b341561049057600080fd5b610498610ec6565b005b34156104a557600080fd5b61053760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f5c565b005b341561054457600080fd5b61054c611133565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058f578082015181840152602081019050610574565b505050509050019250505060405180910390f35b34156105ae57600080fd5b61061a600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506111f6565b005b341561062757600080fd5b61062f61142d565b604051808215151515815260200191505060405180910390f35b341561065457600080fd5b61065c61144a565b6040518082815260200191505060405180910390f35b61067a611780565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b600080600080428911806107445750600089145b151561074f57600080fd5b61075a348a8a611455565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107da57600080fd5b5050602060405103519250600091505b8751821015610a1257878281518110151561080157fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561085f57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff1611151561089357600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108e49190611794565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561094757fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109d657fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506107ea565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a5257600080fd5b505050505050505050565b610a656117ce565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b1657602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610add5790505b50505050509050919050565b6000600754905090565b610b34611780565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bca5780601f10610b9f57610100808354040283529160200191610bca565b820191906000526020600020905b815481529060010190602001808311610bad57829003601f168201915b5050505050905090565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c3557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610ebe576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610ce457fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff16141580610d165750825b1515610d2157600080fd5b8382815181101515610d2f57fe5b9060200190602002015161ffff169050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d909190611794565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610df357fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e8257fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055508180600101925050610c8d565b505050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f5757600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f6d6000808a611455565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561100a57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561107157600080fd5b600090505b875181101561112957600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110d09190611794565b91600052602060002090601091828204019190066002028a848151811015156110f557fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff160217905550508080600101915050611076565b5050505050505050565b61113b6117ce565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156111ec57602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116111b35790505b5050505050905090565b600080600091505b8251821015611427576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110151561125557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161415151561128a57600080fd5b828281518110151561129857fe5b9060200190602002015161ffff169050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112f99190611794565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561135c57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113eb57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506111fe565b50505050565b60006003544211156114425760019050611447565b600090505b90565b60008060ff16905090565b600061145f6117e2565b60008060028551026054016040518059106114775750595b9080825280601f01601f1916602001820160405250925061149661071f565b9150600090505b60208110156114fe5780600802879060020a0260010283828151811015156114c157fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061149d565b600090505b60208110156115675780600802869060020a02600102836020830181518110151561152a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611503565b600090505b60148110156115eb5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115ae57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061156c565b600090505b8451811015611711576008858281518110151561160957fe5b9060200190602002015161ffff169060020a90047f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561165357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561169157fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116d457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506115f0565b826040518082805190602001908083835b6020831015156117475780518252602082019150602081019050602083039250611722565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117c957600f016010900481600f016010900483600052602060002091820191016117c891906117f6565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61181891905b808211156118145760008160009055506001016117fc565b5090565b905600a165627a7a7230582049fa84125e0a02ef1e55f288a7d02a3c951d7ad01e5191aaaaec5185e204c52c0029000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000870000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000000000000000000000000000000000104000000000000000000000000000000000000000000000000000000000000010500000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000107000000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001090000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000010020000000000000000000000000000000000000000000000000000000000001003000000000000000000000000000000000000000000000000000000000000100400000000000000000000000000000000000000000000000000000000000010050000000000000000000000000000000000000000000000000000000000001006000000000000000000000000000000000000000000000000000000000000100700000000000000000000000000000000000000000000000000000000000010080000000000000000000000000000000000000000000000000000000000001009000000000000000000000000000000000000000000000000000000000000000f486f6c69646179206f6e204d6172730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001ba938038062001ba98339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b508160099080519060200190620001999291906200026f565b508360089080519060200190620001b29291906200026f565b50505050505062000352565b82805482825590600052602060002090600f016010900481019282156200025c5791602002820160005b838211156200022a57835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025a5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022a565b505b5090506200026b9190620002f6565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b257805160ff1916838001178555620002e3565b82800160010185558215620002e3579182015b82811115620002e2578251825591602001919060010190620002c5565b5b509050620002f291906200032a565b5090565b6200032791905b808211156200032357600081816101000a81549061ffff021916905550600101620002fd565b5090565b90565b6200034f91905b808211156200034b57600081600090555060010162000331565b5090565b90565b61184780620003626000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063696ecc551461022a57806370a08231146102a857806372c5cb631461033657806395d89b411461035f578063a6fb475f146103ed578063bb6e7de914610485578063c2532c3d1461049a578063c9116b6914610539578063db0ec968146105a3578063ea8b5ca31461061c578063f0141d8414610649575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b6102a660048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610730565b005b34156102b357600080fd5b6102df600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a5d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610322578082015181840152602081019050610307565b505050509050019250505060405180910390f35b341561034157600080fd5b610349610b22565b6040518082815260200191505060405180910390f35b341561036a57600080fd5b610372610b2c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103b2578082015181840152602081019050610397565b50505050905090810190601f1680156103df5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103f857600080fd5b610483600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bd4565b005b341561049057600080fd5b610498610ec6565b005b34156104a557600080fd5b61053760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610f5c565b005b341561054457600080fd5b61054c611133565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058f578082015181840152602081019050610574565b505050509050019250505060405180910390f35b34156105ae57600080fd5b61061a600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506111f6565b005b341561062757600080fd5b61062f61142d565b604051808215151515815260200191505060405180910390f35b341561065457600080fd5b61065c61144a565b6040518082815260200191505060405180910390f35b61067a611780565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b600080600080428911806107445750600089145b151561074f57600080fd5b61075a348a8a611455565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107da57600080fd5b5050602060405103519250600091505b8751821015610a1257878281518110151561080157fe5b9060200190602002015161ffff1690506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561085f57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff1611151561089357600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108e49190611794565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561094757fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156109d657fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506107ea565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501515610a5257600080fd5b505050505050505050565b610a656117ce565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610b1657602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610add5790505b50505050509050919050565b6000600754905090565b610b34611780565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bca5780601f10610b9f57610100808354040283529160200191610bca565b820191906000526020600020905b815481529060010190602001808311610bad57829003601f168201915b5050505050905090565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c3557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610ebe576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610ce457fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff16141580610d165750825b1515610d2157600080fd5b8382815181101515610d2f57fe5b9060200190602002015161ffff169050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d909190611794565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610df357fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e8257fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055508180600101925050610c8d565b505050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610f5757600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6000806000610f6d6000808a611455565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561100a57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561107157600080fd5b600090505b875181101561112957600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110d09190611794565b91600052602060002090601091828204019190066002028a848151811015156110f557fe5b90602001906020020151909190916101000a81548161ffff021916908361ffff160217905550508080600101915050611076565b5050505050505050565b61113b6117ce565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156111ec57602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff16815260200190600201906020826001010492830192600103820291508084116111b35790505b5050505050905090565b600080600091505b8251821015611427576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110151561125557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1661ffff161415151561128a57600080fd5b828281518110151561129857fe5b9060200190602002015161ffff169050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112f99190611794565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561135c57fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113eb57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555081806001019250506111fe565b50505050565b60006003544211156114425760019050611447565b600090505b90565b60008060ff16905090565b600061145f6117e2565b60008060028551026054016040518059106114775750595b9080825280601f01601f1916602001820160405250925061149661071f565b9150600090505b60208110156114fe5780600802879060020a0260010283828151811015156114c157fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061149d565b600090505b60208110156115675780600802869060020a02600102836020830181518110151561152a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611503565b600090505b60148110156115eb5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115ae57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061156c565b600090505b8451811015611711576008858281518110151561160957fe5b9060200190602002015161ffff169060020a90047f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561165357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561169157fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116d457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506115f0565b826040518082805190602001908083835b6020831015156117475780518252602082019150602081019050602083039250611722565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117c957600f016010900481600f016010900483600052602060002091820191016117c891906117f6565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61181891905b808211156118145760008160009055506001016117fc565b5090565b905600a165627a7a723058200792fad5c6263ca3e1d02094e7ae8f2684173dcd7d922a4217a7c654c8637dd5002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000015a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000000174170706c79696e6720666f72206d6f7274676167657332000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a7230582028821fcbcd9925cc4ac65c63aae47bd4e30af5cd3f4a37341253d92a6c665177002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000015900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000000174170706c79696e6720666f72206d6f7274676167657332000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a7230582028821fcbcd9925cc4ac65c63aae47bd4e30af5cd3f4a37341253d92a6c665177002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000015900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000000174170706c79696e6720666f72206d6f7274676167657332000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a7230582028821fcbcd9925cc4ac65c63aae47bd4e30af5cd3f4a37341253d92a6c665177002900000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000000000000000000000000000000000000010040000000000000000000000000000000000000000000000000000000000001005000000000000000000000000000000000000000000000000000000000000100600000000000000000000000000000000000000000000000000000000000010070000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100900000000000000000000000000000000000000000000000000000000000000174170706c79696e6720666f72206d6f7274676167657332000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c" + , "0x63877ab8000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c" + , "0x" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a723058208a216750119a8c106cd7e3839e451f787900b989fd7fee9e3e5ce3f4086e2bc1002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000002640000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000002680000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000012c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000105000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000001070000000000000000000000000000000000000000000000000000000000000108000000000000000000000000000000000000000000000000000000000000010900000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000000010030000000000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000000000000000000000000000100500000000000000000000000000000000000000000000000000000000000010060000000000000000000000000000000000000000000000000000000000001007000000000000000000000000000000000000000000000000000000000000100800000000000000000000000000000000000000000000000000000000000010090000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000108100000000000000000000000000000000000000000000000000000000000010820000000000000000000000000000000000000000000000000000000000001083000000000000000000000000000000000000000000000000000000000000108400000000000000000000000000000000000000000000000000000000000010850000000000000000000000000000000000000000000000000000000000001086000000000000000000000000000000000000000000000000000000000000108700000000000000000000000000000000000000000000000000000000000010880000000000000000000000000000000000000000000000000000000000001089000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000011010000000000000000000000000000000000000000000000000000000000001102000000000000000000000000000000000000000000000000000000000000110300000000000000000000000000000000000000000000000000000000000011040000000000000000000000000000000000000000000000000000000000001105000000000000000000000000000000000000000000000000000000000000110600000000000000000000000000000000000000000000000000000000000011070000000000000000000000000000000000000000000000000000000000001108000000000000000000000000000000000000000000000000000000000000110900000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002001000000000000000000000000000000000000000000000000000000000000200200000000000000000000000000000000000000000000000000000000000020030000000000000000000000000000000000000000000000000000000000002004000000000000000000000000000000000000000000000000000000000000200500000000000000000000000000000000000000000000000000000000000020060000000000000000000000000000000000000000000000000000000000002007000000000000000000000000000000000000000000000000000000000000200800000000000000000000000000000000000000000000000000000000000020090000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000208100000000000000000000000000000000000000000000000000000000000020820000000000000000000000000000000000000000000000000000000000002083000000000000000000000000000000000000000000000000000000000000208400000000000000000000000000000000000000000000000000000000000020850000000000000000000000000000000000000000000000000000000000002086000000000000000000000000000000000000000000000000000000000000208700000000000000000000000000000000000000000000000000000000000020880000000000000000000000000000000000000000000000000000000000002089000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021010000000000000000000000000000000000000000000000000000000000002102000000000000000000000000000000000000000000000000000000000000210300000000000000000000000000000000000000000000000000000000000021040000000000000000000000000000000000000000000000000000000000002105000000000000000000000000000000000000000000000000000000000000210600000000000000000000000000000000000000000000000000000000000021070000000000000000000000000000000000000000000000000000000000002108000000000000000000000000000000000000000000000000000000000000210900000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003001000000000000000000000000000000000000000000000000000000000000300200000000000000000000000000000000000000000000000000000000000030030000000000000000000000000000000000000000000000000000000000003004000000000000000000000000000000000000000000000000000000000000300500000000000000000000000000000000000000000000000000000000000030060000000000000000000000000000000000000000000000000000000000003007000000000000000000000000000000000000000000000000000000000000300800000000000000000000000000000000000000000000000000000000000030090000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000308100000000000000000000000000000000000000000000000000000000000030820000000000000000000000000000000000000000000000000000000000003083000000000000000000000000000000000000000000000000000000000000308400000000000000000000000000000000000000000000000000000000000030850000000000000000000000000000000000000000000000000000000000003086000000000000000000000000000000000000000000000000000000000000308700000000000000000000000000000000000000000000000000000000000030880000000000000000000000000000000000000000000000000000000000003089000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031010000000000000000000000000000000000000000000000000000000000003102000000000000000000000000000000000000000000000000000000000000310300000000000000000000000000000000000000000000000000000000000031040000000000000000000000000000000000000000000000000000000000003105000000000000000000000000000000000000000000000000000000000000310600000000000000000000000000000000000000000000000000000000000031070000000000000000000000000000000000000000000000000000000000003108000000000000000000000000000000000000000000000000000000000000310900000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004001000000000000000000000000000000000000000000000000000000000000400200000000000000000000000000000000000000000000000000000000000040030000000000000000000000000000000000000000000000000000000000004004000000000000000000000000000000000000000000000000000000000000400500000000000000000000000000000000000000000000000000000000000040060000000000000000000000000000000000000000000000000000000000004007000000000000000000000000000000000000000000000000000000000000400800000000000000000000000000000000000000000000000000000000000040090000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000408100000000000000000000000000000000000000000000000000000000000040820000000000000000000000000000000000000000000000000000000000004083000000000000000000000000000000000000000000000000000000000000408400000000000000000000000000000000000000000000000000000000000040850000000000000000000000000000000000000000000000000000000000004086000000000000000000000000000000000000000000000000000000000000408700000000000000000000000000000000000000000000000000000000000040880000000000000000000000000000000000000000000000000000000000004089000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004102000000000000000000000000000000000000000000000000000000000000410300000000000000000000000000000000000000000000000000000000000041040000000000000000000000000000000000000000000000000000000000004105000000000000000000000000000000000000000000000000000000000000410600000000000000000000000000000000000000000000000000000000000041070000000000000000000000000000000000000000000000000000000000004108000000000000000000000000000000000000000000000000000000000000410900000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005001000000000000000000000000000000000000000000000000000000000000500200000000000000000000000000000000000000000000000000000000000050030000000000000000000000000000000000000000000000000000000000005004000000000000000000000000000000000000000000000000000000000000500500000000000000000000000000000000000000000000000000000000000050060000000000000000000000000000000000000000000000000000000000005007000000000000000000000000000000000000000000000000000000000000500800000000000000000000000000000000000000000000000000000000000050090000000000000000000000000000000000000000000000000000000000005080000000000000000000000000000000000000000000000000000000000000508100000000000000000000000000000000000000000000000000000000000050820000000000000000000000000000000000000000000000000000000000005083000000000000000000000000000000000000000000000000000000000000508400000000000000000000000000000000000000000000000000000000000050850000000000000000000000000000000000000000000000000000000000005086000000000000000000000000000000000000000000000000000000000000508700000000000000000000000000000000000000000000000000000000000050880000000000000000000000000000000000000000000000000000000000005089000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000051010000000000000000000000000000000000000000000000000000000000005102000000000000000000000000000000000000000000000000000000000000510300000000000000000000000000000000000000000000000000000000000051040000000000000000000000000000000000000000000000000000000000005105000000000000000000000000000000000000000000000000000000000000510600000000000000000000000000000000000000000000000000000000000051070000000000000000000000000000000000000000000000000000000000005108000000000000000000000000000000000000000000000000000000000000510900000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006001000000000000000000000000000000000000000000000000000000000000600200000000000000000000000000000000000000000000000000000000000060030000000000000000000000000000000000000000000000000000000000006004000000000000000000000000000000000000000000000000000000000000600500000000000000000000000000000000000000000000000000000000000060060000000000000000000000000000000000000000000000000000000000006007000000000000000000000000000000000000000000000000000000000000600800000000000000000000000000000000000000000000000000000000000060090000000000000000000000000000000000000000000000000000000000006080000000000000000000000000000000000000000000000000000000000000608100000000000000000000000000000000000000000000000000000000000060820000000000000000000000000000000000000000000000000000000000006083000000000000000000000000000000000000000000000000000000000000608400000000000000000000000000000000000000000000000000000000000060850000000000000000000000000000000000000000000000000000000000006086000000000000000000000000000000000000000000000000000000000000608700000000000000000000000000000000000000000000000000000000000060880000000000000000000000000000000000000000000000000000000000006089000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061010000000000000000000000000000000000000000000000000000000000006102000000000000000000000000000000000000000000000000000000000000610300000000000000000000000000000000000000000000000000000000000061040000000000000000000000000000000000000000000000000000000000006105000000000000000000000000000000000000000000000000000000000000610600000000000000000000000000000000000000000000000000000000000061070000000000000000000000000000000000000000000000000000000000006108000000000000000000000000000000000000000000000000000000000000610900000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007001000000000000000000000000000000000000000000000000000000000000700200000000000000000000000000000000000000000000000000000000000070030000000000000000000000000000000000000000000000000000000000007004000000000000000000000000000000000000000000000000000000000000700500000000000000000000000000000000000000000000000000000000000070060000000000000000000000000000000000000000000000000000000000007007000000000000000000000000000000000000000000000000000000000000700800000000000000000000000000000000000000000000000000000000000070090000000000000000000000000000000000000000000000000000000000007080000000000000000000000000000000000000000000000000000000000000708100000000000000000000000000000000000000000000000000000000000070820000000000000000000000000000000000000000000000000000000000007083000000000000000000000000000000000000000000000000000000000000708400000000000000000000000000000000000000000000000000000000000070850000000000000000000000000000000000000000000000000000000000007086000000000000000000000000000000000000000000000000000000000000708700000000000000000000000000000000000000000000000000000000000070880000000000000000000000000000000000000000000000000000000000007089000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071010000000000000000000000000000000000000000000000000000000000007102000000000000000000000000000000000000000000000000000000000000710300000000000000000000000000000000000000000000000000000000000071040000000000000000000000000000000000000000000000000000000000007105000000000000000000000000000000000000000000000000000000000000710600000000000000000000000000000000000000000000000000000000000071070000000000000000000000000000000000000000000000000000000000007108000000000000000000000000000000000000000000000000000000000000710900000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000000000000000000000000000000000800200000000000000000000000000000000000000000000000000000000000080030000000000000000000000000000000000000000000000000000000000008004000000000000000000000000000000000000000000000000000000000000800500000000000000000000000000000000000000000000000000000000000080060000000000000000000000000000000000000000000000000000000000008007000000000000000000000000000000000000000000000000000000000000800800000000000000000000000000000000000000000000000000000000000080090000000000000000000000000000000000000000000000000000000000008080000000000000000000000000000000000000000000000000000000000000808100000000000000000000000000000000000000000000000000000000000080820000000000000000000000000000000000000000000000000000000000008083000000000000000000000000000000000000000000000000000000000000808400000000000000000000000000000000000000000000000000000000000080850000000000000000000000000000000000000000000000000000000000008086000000000000000000000000000000000000000000000000000000000000808700000000000000000000000000000000000000000000000000000000000080880000000000000000000000000000000000000000000000000000000000008089000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008102000000000000000000000000000000000000000000000000000000000000810300000000000000000000000000000000000000000000000000000000000081040000000000000000000000000000000000000000000000000000000000008105000000000000000000000000000000000000000000000000000000000000810600000000000000000000000000000000000000000000000000000000000081070000000000000000000000000000000000000000000000000000000000008108000000000000000000000000000000000000000000000000000000000000810900000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009001000000000000000000000000000000000000000000000000000000000000900200000000000000000000000000000000000000000000000000000000000090030000000000000000000000000000000000000000000000000000000000009004000000000000000000000000000000000000000000000000000000000000900500000000000000000000000000000000000000000000000000000000000090060000000000000000000000000000000000000000000000000000000000009007000000000000000000000000000000000000000000000000000000000000900800000000000000000000000000000000000000000000000000000000000090090000000000000000000000000000000000000000000000000000000000009080000000000000000000000000000000000000000000000000000000000000908100000000000000000000000000000000000000000000000000000000000090820000000000000000000000000000000000000000000000000000000000009083000000000000000000000000000000000000000000000000000000000000908400000000000000000000000000000000000000000000000000000000000090850000000000000000000000000000000000000000000000000000000000009086000000000000000000000000000000000000000000000000000000000000908700000000000000000000000000000000000000000000000000000000000090880000000000000000000000000000000000000000000000000000000000009089000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000091010000000000000000000000000000000000000000000000000000000000009102000000000000000000000000000000000000000000000000000000000000910300000000000000000000000000000000000000000000000000000000000091040000000000000000000000000000000000000000000000000000000000009105000000000000000000000000000000000000000000000000000000000000910600000000000000000000000000000000000000000000000000000000000091070000000000000000000000000000000000000000000000000000000000009108000000000000000000000000000000000000000000000000000000000000910900000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001bbf38038062001bbf8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61185a80620003656000396000f3006060604052600436106100db576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100eb578063313ce5671461017957806332a2c5d0146101a85780634f452b9a146101fd578063516741aa1461022a5780635c6491e5146102c957806363877ab81461036157806370a08231146103da57806372c5cb631461046857806395d89b4114610491578063bb6e7de91461051f578063c9116b6914610534578063ea8b5ca31461059e578063f0141d84146105cb578063f1aaf147146105f4575b34156100e657600080fd5b600080fd5b34156100f657600080fd5b6100fe610672565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018457600080fd5b61018c61071a565b604051808260ff1660ff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb61071f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561020857600080fd5b610210610727565b604051808215151515815260200191505060405180910390f35b341561023557600080fd5b6102c760048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610730565b005b34156102d457600080fd5b61035f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061090a565b005b341561036c57600080fd5b6103d8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bfe565b005b34156103e557600080fd5b610411600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e46565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610454578082015181840152602081019050610439565b505050509050019250505060405180910390f35b341561047357600080fd5b61047b610f09565b6040518082815260200191505060405180910390f35b341561049c57600080fd5b6104a4610f13565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e45780820151818401526020810190506104c9565b50505050905090810190601f1680156105115780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052a57600080fd5b610532610fbb565b005b341561053f57600080fd5b610547611051565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561058a57808201518184015260208101905061056f565b505050509050019250505060405180910390f35b34156105a957600080fd5b6105b1611112565b604051808215151515815260200191505060405180910390f35b34156105d657600080fd5b6105de61112f565b6040518082815260200191505060405180910390f35b61067060048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061113a565b005b61067a611793565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107105780601f106106e557610100808354040283529160200191610710565b820191906000526020600020905b8154815290600101906020018083116106f357829003601f168201915b5050505050905090565b600081565b600030905090565b60006001905090565b60008060006107416000808a611469565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156107de57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561084557600080fd5b600090505b875181101561090057600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108a491906117a7565b91600052602060002090601091828204019190066002028a848151811015156108c957fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff16021790555050808060010191505061084a565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561096b57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bf6576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610a1a57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a4a5750825b1515610a5557600080fd5b8382815181101515610a6357fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ac391906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610b2657fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610bb757fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506109c3565b505050505050565b600080600354421115610c1057600080fd5b600091505b8251821015610e40576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c6c57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c9f57600080fd5b8282815181101515610cad57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610d0d91906117a7565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d7057fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610e0157fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610c15565b50505050565b610e4e6117e1565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efd57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610ec65790505b50505050509050919050565b6000600754905090565b610f1b611793565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb15780601f10610f8657610100808354040283529160200191610fb1565b820191906000526020600020905b815481529060010190602001808311610f9457829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561104c57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110596117e1565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561110857602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110d15790505b5050505050905090565b6000600354421115611127576001905061112c565b600090505b90565b60008060ff16905090565b6000806000804289118061114e5750600089145b151561115957600080fd5b611164348a8a611469565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e457600080fd5b5050602060405103519250600091505b875182101561141e57878281518110151561120b57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561126857fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561129a57600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112eb91906117a7565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561134e57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811015156113df57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111f4565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561145e57600080fd5b505050505050505050565b60006114736117f5565b600080600285510260540160405180591061148b5750595b9080825280601f01601f191660200182016040525092506114aa61071f565b9150600090505b60208110156115125780600802879060020a0260010283828151811015156114d557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114b1565b600090505b602081101561157b5780600802869060020a02600102836020830181518110151561153e57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611517565b600090505b60148110156115ff5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a0283826040018151811015156115c257fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611580565b600090505b8451811015611724576008858281518110151561161d57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561166657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084818151811015156116a457fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116e757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611604565b826040518082805190602001908083835b60208310151561175a5780518252602082019150602081019050602083039250611735565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b8154818355818115116117dc57600f016010900481600f016010900483600052602060002091820191016117db9190611809565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b61182b91905b8082111561182757600081600090555060010161180f565b5090565b905600a165627a7a723058208a216750119a8c106cd7e3839e451f787900b989fd7fee9e3e5ce3f4086e2bc1002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000002636000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000cad0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000093200000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0x60606040526000600260006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001b7e38038062001b7e8339810160405280805182019190602001805182019190602001805190602001909190805182019190602001805190602001909190505084516000819055508260038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508460016000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020908051906020019062000180929190620001be565b5081600990805190602001906200019992919062000272565b508360089080519060200190620001b292919062000272565b50505050505062000355565b82805482825590600052602060002090600f016010900481019282156200025f5791602002820160005b838211156200022d57835183826101000a81548161ffff021916908360010b61ffff1602179055509260200192600201602081600101049283019260010302620001e8565b80156200025d5782816101000a81549061ffff02191690556002016020816001010492830192600103026200022d565b505b5090506200026e9190620002f9565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002b557805160ff1916838001178555620002e6565b82800160010185558215620002e6579182015b82811115620002e5578251825591602001919060010190620002c8565b5b509050620002f591906200032d565b5090565b6200032a91905b808211156200032657600081816101000a81549061ffff02191690555060010162000300565b5090565b90565b6200035291905b808211156200034e57600081600090555060010162000334565b5090565b90565b61181980620003656000396000f3006060604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100e0578063313ce5671461016e57806332a2c5d01461019d578063516741aa146101f25780635c6491e51461029157806363877ab81461032957806370a08231146103a257806372c5cb631461043057806395d89b4114610459578063bb6e7de9146104e7578063c9116b69146104fc578063ea8b5ca314610566578063f0141d8414610593578063f1aaf147146105bc575b34156100db57600080fd5b600080fd5b34156100eb57600080fd5b6100f361063a565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610133578082015181840152602081019050610118565b50505050905090810190601f1680156101605780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561017957600080fd5b6101816106e2565b604051808260ff1660ff16815260200191505060405180910390f35b34156101a857600080fd5b6101b06106e7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101fd57600080fd5b61028f60048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff16906020019091908035600019169060200190919080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506106ef565b005b341561029c57600080fd5b610327600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506108c9565b005b341561033457600080fd5b6103a0600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bbd565b005b34156103ad57600080fd5b6103d9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e05565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561041c578082015181840152602081019050610401565b505050509050019250505060405180910390f35b341561043b57600080fd5b610443610ec8565b6040518082815260200191505060405180910390f35b341561046457600080fd5b61046c610ed2565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104ac578082015181840152602081019050610491565b50505050905090810190601f1680156104d95780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156104f257600080fd5b6104fa610f7a565b005b341561050757600080fd5b61050f611010565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610552578082015181840152602081019050610537565b505050509050019250505060405180910390f35b341561057157600080fd5b6105796110d1565b604051808215151515815260200191505060405180910390f35b341561059e57600080fd5b6105a66110ee565b6040518082815260200191505060405180910390f35b61063860048080359060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506110f9565b005b610642611752565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106d85780601f106106ad576101008083540402835291602001916106d8565b820191906000526020600020905b8154815290600101906020018083116106bb57829003601f168201915b5050505050905090565b600081565b600030905090565b60008060006107006000808a611428565b92506001836040518082600019166000191681526020019150506040518091039020888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561079d57600080fd5b5050602060405103519150600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151561080457600080fd5b600090505b87518110156108bf57600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816108639190611766565b91600052602060002090601091828204019190066002028a8481518110151561088857fe5b90602001906020020151909190916101000a81548161ffff021916908360010b61ffff160217905550508080600101915050610809565b5050505050505050565b6000806000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561092a57600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16149250600091505b8351821015610bb5576000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811015156109d957fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b141580610a095750825b1515610a1457600080fd5b8382815181101515610a2257fe5b9060200190602002015160010b9050600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610a829190611766565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610ae557fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610b7657fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610982565b505050505050565b600080600354421115610bcf57600080fd5b600091505b8251821015610dff576000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481101515610c2b57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b14151515610c5e57600080fd5b8282815181101515610c6c57fe5b9060200190602002015160010b9050600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610ccc9190611766565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481101515610d2f57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002082815481101515610dc057fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff1602179055508180600101925050610bd4565b50505050565b610e0d6117a0565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ebc57602002820191906000526020600020906000905b82829054906101000a900460010b60010b81526020019060020190602082600101049283019260010382029150808411610e855790505b50505050509050919050565b6000600754905090565b610eda611752565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f705780601f10610f4557610100808354040283529160200191610f70565b820191906000526020600020905b815481529060010190602001808311610f5357829003601f168201915b5050505050905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561100b57600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b6110186117a0565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156110c757602002820191906000526020600020906000905b82829054906101000a900460010b60010b815260200190600201906020826001010492830192600103820291508084116110905790505b5050505050905090565b60006003544211156110e657600190506110eb565b600090505b90565b60008060ff16905090565b6000806000804289118061110d5750600089145b151561111857600080fd5b611123348a8a611428565b9350600184888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111a357600080fd5b5050602060405103519250600091505b87518210156113dd5787828151811015156111ca57fe5b9060200190602002015160010b90506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561122757fe5b90600052602060002090601091828204019190066002029054906101000a900460010b60010b13151561125957600080fd5b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816112aa9190611766565b9160005260206000209060109182820401919006600202600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110151561130d57fe5b90600052602060002090601091828204019190066002029054906101000a900460010b909190916101000a81548161ffff021916908360010b61ffff160217905550506000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110151561139e57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908360010b61ffff16021790555081806001019250506111b3565b8273ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561141d57600080fd5b505050505050505050565b60006114326117b4565b600080600285510260540160405180591061144a5750595b9080825280601f01601f191660200182016040525092506114696106e7565b9150600090505b60208110156114d15780600802879060020a02600102838281518110151561149457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080600101915050611470565b600090505b602081101561153a5780600802869060020a0260010283602083018151811015156114fd57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506114d6565b600090505b60148110156115be5780600802826c01000000000000000000000000026bffffffffffffffffffffffff19169060020a02838260400181518110151561158157fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808060010191505061153f565b600090505b84518110156116e357600885828151811015156115dc57fe5b9060200190602002015160010b9060020a90057f010000000000000000000000000000000000000000000000000000000000000002836002830260540181518110151561162557fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350848181518110151561166357fe5b906020019060200201517f01000000000000000000000000000000000000000000000000000000000000000283600160028402605401018151811015156116a657fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080806001019150506115c3565b826040518082805190602001908083835b60208310151561171957805182526020820191506020810190506020830392506116f4565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902093505050509392505050565b602060405190810160405280600081525090565b81548183558181151161179b57600f016010900481600f0160109004836000526020600020918201910161179a91906117c8565b5b505050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b6117ea91905b808211156117e65760008160009055506001016117ce565b5090565b905600a165627a7a72305820dd127bc67ffb3f56951a3ac13502a41674d74e88729115b207f44ce52b0a5978002900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000002636000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000cad0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000093200000000000000000000000000000000000000000000000000000000000000164170706c79696e6720666f72206d6f7274676167657300000000000000000000000000000000000000000000000000000000000000000000000000000000000341504d0000000000000000000000000000000000000000000000000000000000" + , "0x00" + , "0xdb0ec968000000000000000000000000d75124572589127bb6d8ab5ccc8acd215da1102a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000007" + , "0xdb0ec968000000000000000000000000b05a1573146372165c65f3f8ac7340fee7fa88c40000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013" + , "0x" + , "0x00" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a" + , "0xdb0ec968000000000000000000000000699657da752d806a5df9f8a12e25facd1b2215ca0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000017" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc46802090539840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000b" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000013" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc46802090539840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c" + , "0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001be638038062001be683398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000f9929190620001ca565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550856006819055508260099080519060200190620001619291906200027b565b5087600890805190602001906200017a9291906200027b565b5084600a9080519060200190620001939291906200027b565b5083600b9080519060200190620001ac9291906200027b565b5081600c8190555080600d819055505050505050505050506200035e565b82805482825590600052602060002090600f01601090048101928215620002685791602002820160005b838211156200023657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001f4565b8015620002665782816101000a81549061ffff021916905560020160208160010104928301926001030262000236565b505b50905062000277919062000302565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002be57805160ff1916838001178555620002ef565b82800160010185558215620002ef579182015b82811115620002ee578251825591602001919060010190620002d1565b5b509050620002fe919062000336565b5090565b6200033391905b808211156200032f57600081816101000a81549061ffff02191690555060010162000309565b5090565b90565b6200035b91905b80821115620003575760008160009055506001016200033d565b5090565b90565b611878806200036e6000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd14610228578063313ce56714610251578063323046b1146102805780634bfbe5df1461030e57806370a082311461039c57806372c5cb631461042a57806395d89b4114610453578063a0d8848c146104e1578063a270a7371461050a578063a6fb475f14610598578063ba9a909014610630578063c2bf17b014610664578063db0ec96814610712578063e22bda351461078b578063ea8b5ca314610819578063f0141d8414610846575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086f565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610879565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610921565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610ad3565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b610264610adc565b604051808260ff1660ff16815260200191505060405180910390f35b341561028b57600080fd5b610293610ae1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102d35780820151818401526020810190506102b8565b50505050905090810190601f1680156103005780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561031957600080fd5b610321610b7f565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103a757600080fd5b6103d3600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c27565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104165780820151818401526020810190506103fb565b505050509050019250505060405180910390f35b341561043557600080fd5b61043d610cec565b6040518082815260200191505060405180910390f35b341561045e57600080fd5b610466610cf6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104a657808201518184015260208101905061048b565b50505050905090810190601f1680156104d35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156104ec57600080fd5b6104f4610d9e565b6040518082815260200191505060405180910390f35b341561051557600080fd5b61051d610da8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561055d578082015181840152602081019050610542565b50505050905090810190601f16801561058a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105a357600080fd5b61062e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610e46565b005b61064a600480803561ffff1690602001909190505061113d565b604051808215151515815260200191505060405180910390f35b341561066f57600080fd5b6106af60048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506112db565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b341561071d57600080fd5b610789600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061144f565b005b341561079657600080fd5b61079e6116f5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107de5780820151818401526020810190506107c3565b50505050905090810190601f16801561080b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561082457600080fd5b61082c61179d565b604051808215151515815260200191505060405180910390f35b341561085157600080fd5b6108596117ba565b6040518082815260200191505060405180910390f35b6000600d54905090565b6108816117c5565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109175780601f106108ec57610100808354040283529160200191610917565b820191906000526020600020905b8154815290600101906020018083116108fa57829003601f168201915b5050505050905090565b6000806000806000806000806109398c8c8c8c6112db565b9650965096509650600d54600360009054906101000a900461ffff16870161ffff16111561096657600080fd5b8561ffff168502925083801561097b57508234145b15610abf576006543481151561098d57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109d557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a3757600080fd5b60076000815480929190600101919050555085600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555060019750610ac4565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b775780601f10610b4c57610100808354040283529160200191610b77565b820191906000526020600020905b815481529060010190602001808311610b5a57829003601f168201915b505050505081565b610b876117c5565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c1d5780601f10610bf257610100808354040283529160200191610c1d565b820191906000526020600020905b815481529060010190602001808311610c0057829003601f168201915b5050505050905090565b610c2f6117d9565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610ca75790505b50505050509050919050565b6000600754905090565b610cfe6117c5565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d945780601f10610d6957610100808354040283529160200191610d94565b820191906000526020600020905b815481529060010190602001808311610d7757829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e3e5780601f10610e1357610100808354040283529160200191610e3e565b820191906000526020600020905b815481529060010190602001808311610e2157829003601f168201915b505050505081565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ea457600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ef457600080fd5b600090505b81518110156110c957600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610f5391906117ed565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610fb757fe5b9060200190602002015161ffff16815481101515610fd157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561106157fe5b9060200190602002015161ffff1681548110151561107b57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610ef9565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555050505050565b6000808261ffff16600c54023414158061116c5750600060018461ffff1681151561116457fe5b0661ffff1614155b1561117657600080fd5b600360009054906101000a900461ffff1690505b600360009054906101000a900461ffff16830161ffff168161ffff16101561123f57600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816111fd91906117ed565b916000526020600020906010918282040191900660020283909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061118a565b82600360008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f1935050505015156112d157600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561138a57600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff16600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003101561143f5760009050611444565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905010156114a157600080fd5b600090505b81518161ffff16101561168257600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161150491906117ed565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff1681518110151561156c57fe5b9060200190602002015161ffff1681548110151561158657fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561161a57fe5b9060200190602002015161ffff1681548110151561163457fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060076000815480929190600101919050555080806001019150506114a6565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550505050565b6116fd6117c5565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117935780601f1061176857610100808354040283529160200191611793565b820191906000526020600020905b81548152906001019060200180831161177657829003601f168201915b5050505050905090565b60006004544211156117b257600190506117b7565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b81548183558181151161182257600f016010900481600f016010900483600052602060002091820191016118219190611827565b5b505050565b61184991905b8082111561184557600081600090555060010161182d565b5090565b905600a165627a7a7230582071adaa5e8b36a626e0271897ab2325b900e8063173d8a32e790db3c2e6fdead3002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000011496e74656e7365204c61626f7572696e67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a33302f30322f3230313700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e506173697220526973205061726b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003494e4c0000000000000000000000000000000000000000000000000000000000" + , "0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001be638038062001be683398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000f9929190620001ca565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550856006819055508260099080519060200190620001619291906200027b565b5087600890805190602001906200017a9291906200027b565b5084600a9080519060200190620001939291906200027b565b5083600b9080519060200190620001ac9291906200027b565b5081600c8190555080600d819055505050505050505050506200035e565b82805482825590600052602060002090600f01601090048101928215620002685791602002820160005b838211156200023657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001f4565b8015620002665782816101000a81549061ffff021916905560020160208160010104928301926001030262000236565b505b50905062000277919062000302565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002be57805160ff1916838001178555620002ef565b82800160010185558215620002ef579182015b82811115620002ee578251825591602001919060010190620002d1565b5b509050620002fe919062000336565b5090565b6200033391905b808211156200032f57600081816101000a81549061ffff02191690555060010162000309565b5090565b90565b6200035b91905b80821115620003575760008160009055506001016200033d565b5090565b90565b611878806200036e6000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd14610228578063313ce56714610251578063323046b1146102805780634bfbe5df1461030e57806370a082311461039c57806372c5cb631461042a57806395d89b4114610453578063a0d8848c146104e1578063a270a7371461050a578063a6fb475f14610598578063ba9a909014610630578063c2bf17b014610664578063db0ec96814610712578063e22bda351461078b578063ea8b5ca314610819578063f0141d8414610846575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086f565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610879565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610921565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610ad3565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b610264610adc565b604051808260ff1660ff16815260200191505060405180910390f35b341561028b57600080fd5b610293610ae1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102d35780820151818401526020810190506102b8565b50505050905090810190601f1680156103005780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561031957600080fd5b610321610b7f565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103a757600080fd5b6103d3600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c27565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104165780820151818401526020810190506103fb565b505050509050019250505060405180910390f35b341561043557600080fd5b61043d610cec565b6040518082815260200191505060405180910390f35b341561045e57600080fd5b610466610cf6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104a657808201518184015260208101905061048b565b50505050905090810190601f1680156104d35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156104ec57600080fd5b6104f4610d9e565b6040518082815260200191505060405180910390f35b341561051557600080fd5b61051d610da8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561055d578082015181840152602081019050610542565b50505050905090810190601f16801561058a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105a357600080fd5b61062e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610e46565b005b61064a600480803561ffff1690602001909190505061113d565b604051808215151515815260200191505060405180910390f35b341561066f57600080fd5b6106af60048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506112db565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b341561071d57600080fd5b610789600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061144f565b005b341561079657600080fd5b61079e6116f5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107de5780820151818401526020810190506107c3565b50505050905090810190601f16801561080b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561082457600080fd5b61082c61179d565b604051808215151515815260200191505060405180910390f35b341561085157600080fd5b6108596117ba565b6040518082815260200191505060405180910390f35b6000600d54905090565b6108816117c5565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109175780601f106108ec57610100808354040283529160200191610917565b820191906000526020600020905b8154815290600101906020018083116108fa57829003601f168201915b5050505050905090565b6000806000806000806000806109398c8c8c8c6112db565b9650965096509650600d54600360009054906101000a900461ffff16870161ffff16111561096657600080fd5b8561ffff168502925083801561097b57508234145b15610abf576006543481151561098d57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109d557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a3757600080fd5b60076000815480929190600101919050555085600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555060019750610ac4565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b775780601f10610b4c57610100808354040283529160200191610b77565b820191906000526020600020905b815481529060010190602001808311610b5a57829003601f168201915b505050505081565b610b876117c5565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c1d5780601f10610bf257610100808354040283529160200191610c1d565b820191906000526020600020905b815481529060010190602001808311610c0057829003601f168201915b5050505050905090565b610c2f6117d9565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610ca75790505b50505050509050919050565b6000600754905090565b610cfe6117c5565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d945780601f10610d6957610100808354040283529160200191610d94565b820191906000526020600020905b815481529060010190602001808311610d7757829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e3e5780601f10610e1357610100808354040283529160200191610e3e565b820191906000526020600020905b815481529060010190602001808311610e2157829003601f168201915b505050505081565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ea457600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ef457600080fd5b600090505b81518110156110c957600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610f5391906117ed565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610fb757fe5b9060200190602002015161ffff16815481101515610fd157fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561106157fe5b9060200190602002015161ffff1681548110151561107b57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610ef9565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff16021790555050505050565b6000808261ffff16600c54023414158061116c5750600060018461ffff1681151561116457fe5b0661ffff1614155b1561117657600080fd5b600360009054906101000a900461ffff1690505b600360009054906101000a900461ffff16830161ffff168161ffff16101561123f57600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816111fd91906117ed565b916000526020600020906010918282040191900660020283909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061118a565b82600360008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f1935050505015156112d157600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561138a57600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff16600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003101561143f5760009050611444565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905010156114a157600080fd5b600090505b81518161ffff16101561168257600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161150491906117ed565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858561ffff1681518110151561156c57fe5b9060200190602002015161ffff1681548110151561158657fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838361ffff1681518110151561161a57fe5b9060200190602002015161ffff1681548110151561163457fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff16021790555060076000815480929190600101919050555080806001019150506114a6565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550505050565b6116fd6117c5565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117935780601f1061176857610100808354040283529160200191611793565b820191906000526020600020905b81548152906001019060200180831161177657829003601f168201915b5050505050905090565b60006004544211156117b257600190506117b7565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b81548183558181151161182257600f016010900481600f016010900483600052602060002091820191016118219190611827565b5b505050565b61184991905b8082111561184557600081600090555060010161182d565b5090565b905600a165627a7a7230582071adaa5e8b36a626e0271897ab2325b900e8063173d8a32e790db3c2e6fdead3002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000005f8e288000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000011496e74656e7365204c61626f7572696e67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a33302f30322f3230313700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e506173697220526973205061726b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003494e4c0000000000000000000000000000000000000000000000000000000000" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000009" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000008" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" + , "0x" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000014" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000015" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000016" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000019" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001a" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000018" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0xa6fb475f000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000009" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000009" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000017" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000b" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000010" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000004" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc46802090539840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000f" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc4680209053984000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc468020905398400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e" + , "0xdb0ec96800000000000000000000000052a9bff41a0abd386f8998190fc46802090539840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" + , "0xba9a90900000000000000000000000000000000000000000000000000000000000000001" + , "0xa6fb475f000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x60606040526000600360006101000a81548161ffff021916908361ffff160217905550600060075534156200003357600080fd5b60405162001b6c38038062001b6c83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000f9929190620001ca565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550856006819055508260099080519060200190620001619291906200027b565b5087600890805190602001906200017a9291906200027b565b5084600a9080519060200190620001939291906200027b565b5083600b9080519060200190620001ac9291906200027b565b5081600c8190555080600d819055505050505050505050506200035e565b82805482825590600052602060002090600f01601090048101928215620002685791602002820160005b838211156200023657835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620001f4565b8015620002665782816101000a81549061ffff021916905560020160208160010104928301926001030262000236565b505b50905062000277919062000302565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002be57805160ff1916838001178555620002ef565b82800160010185558215620002ef579182015b82811115620002ee578251825591602001919060010190620002d1565b5b509050620002fe919062000336565b5090565b6200033391905b808211156200032f57600081816101000a81549061ffff02191690555060010162000309565b5090565b90565b6200035b91905b80821115620003575760008160009055506001016200033d565b5090565b90565b6117fe806200036e6000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd14610228578063313ce56714610251578063323046b1146102805780634bfbe5df1461030e57806370a082311461039c57806372c5cb631461042a57806395d89b4114610453578063a0d8848c146104e1578063a270a7371461050a578063a6fb475f14610598578063ba9a909014610630578063c2bf17b014610664578063db0ec96814610712578063e22bda351461078b578063ea8b5ca314610819578063f0141d8414610846575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086f565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610879565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610921565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610ab7565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b610264610ac0565b604051808260ff1660ff16815260200191505060405180910390f35b341561028b57600080fd5b610293610ac5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102d35780820151818401526020810190506102b8565b50505050905090810190601f1680156103005780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561031957600080fd5b610321610b63565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610361578082015181840152602081019050610346565b50505050905090810190601f16801561038e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103a757600080fd5b6103d3600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c0b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104165780820151818401526020810190506103fb565b505050509050019250505060405180910390f35b341561043557600080fd5b61043d610cd0565b6040518082815260200191505060405180910390f35b341561045e57600080fd5b610466610cda565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104a657808201518184015260208101905061048b565b50505050905090810190601f1680156104d35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156104ec57600080fd5b6104f4610d82565b6040518082815260200191505060405180910390f35b341561051557600080fd5b61051d610d8c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561055d578082015181840152602081019050610542565b50505050905090810190601f16801561058a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105a357600080fd5b61062e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610e2a565b005b61064a600480803561ffff16906020019091905050611101565b604051808215151515815260200191505060405180910390f35b341561066f57600080fd5b6106af60048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061129f565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b341561071d57600080fd5b610789600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050611401565b005b341561079657600080fd5b61079e61167b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107de5780820151818401526020810190506107c3565b50505050905090810190601f16801561080b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561082457600080fd5b61082c611723565b604051808215151515815260200191505060405180910390f35b341561085157600080fd5b610859611740565b6040518082815260200191505060405180910390f35b6000600d54905090565b61088161174b565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109175780601f106108ec57610100808354040283529160200191610917565b820191906000526020600020905b8154815290600101906020018083116108fa57829003601f168201915b5050505050905090565b6000806000806000806000806109398c8c8c8c61129f565b9650965096509650600d54600360009054906101000a900461ffff16870161ffff16111561096657600080fd5b8561ffff168502925083801561097b57508234145b15610aa3576006543481151561098d57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109d557600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a3757600080fd5b6007600081548092919060010191905055508561ffff16600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019750610aa8565b600080fd5b50505050505050949350505050565b60008054905090565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b5b5780601f10610b3057610100808354040283529160200191610b5b565b820191906000526020600020905b815481529060010190602001808311610b3e57829003601f168201915b505050505081565b610b6b61174b565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c015780601f10610bd657610100808354040283529160200191610c01565b820191906000526020600020905b815481529060010190602001808311610be457829003601f168201915b5050505050905090565b610c1361175f565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610cc457602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610c8b5790505b50505050509050919050565b6000600754905090565b610ce261174b565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d785780601f10610d4d57610100808354040283529160200191610d78565b820191906000526020600020905b815481529060010190602001808311610d5b57829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e225780601f10610df757610100808354040283529160200191610e22565b820191906000526020600020905b815481529060010190602001808311610e0557829003601f168201915b505050505081565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610e8857600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ed857600080fd5b600090505b81518110156110ad57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610f379190611773565b9160005260206000209060109182820401919006600202600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610f9b57fe5b9060200190602002015161ffff16815481101515610fb557fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561104557fe5b9060200190602002015161ffff1681548110151561105f57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050610edd565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555050505050565b6000808261ffff16600c5402341415806111305750600060018461ffff1681151561112857fe5b0661ffff1614155b1561113a57600080fd5b600360009054906101000a900461ffff1690505b600360009054906101000a900461ffff16830161ffff168161ffff16101561120357600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816111c19190611773565b916000526020600020906010918282040191900660020283909190916101000a81548161ffff021916908361ffff16021790555050808060010191505061114e565b82600360008282829054906101000a900461ffff160192506101000a81548161ffff021916908361ffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561129557600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561134e57600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490500310156113f157600090506113f6565b600190505b945094509450949050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050101561145357600080fd5b600090505b815181101561162857600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816114b29190611773565b9160005260206000209060109182820401919006600202600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020858581518110151561151657fe5b9060200190602002015161ffff1681548110151561153057fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff16909190916101000a81548161ffff021916908361ffff160217905550506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083838151811015156115c057fe5b9060200190602002015161ffff168154811015156115da57fe5b90600052602060002090601091828204019190066002026101000a81548161ffff021916908361ffff1602179055506007600081548092919060010191905055508080600101915050611458565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550505050565b61168361174b565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117195780601f106116ee57610100808354040283529160200191611719565b820191906000526020600020905b8154815290600101906020018083116116fc57829003601f168201915b5050505050905090565b6000600454421115611738576001905061173d565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b8154818355818115116117a857600f016010900481600f016010900483600052602060002091820191016117a791906117ad565b5b505050565b6117cf91905b808211156117cb5760008160009055506001016117b3565b5090565b905600a165627a7a723058206f42c96331c4810d2277882fd44b93547d9ef05d8fccc0216cc96a22b8c3f6e1002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000f47656f6361636865204d65657475700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a33302f30312f323031370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000134f6c64204368616e676920486f73706974616c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000347454f0000000000000000000000000000000000000000000000000000000000" + , "0x60606040526000600355600060075534156200001a57600080fd5b604051620019483803806200194883398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000e0929190620001b1565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560068190555082600990805190602001906200014892919062000203565b5087600890805190602001906200016192919062000203565b5084600a90805190602001906200017a92919062000203565b5083600b90805190602001906200019392919062000203565b5081600c8190555080600d81905550505050505050505050620002b2565b828054828255906000526020600020908101928215620001f0579160200282015b82811115620001ef578251825591602001919060010190620001d2565b5b509050620001ff91906200028a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024657805160ff191683800117855562000277565b8280016001018555821562000277579182015b828111156200027657825182559160200191906001019062000259565b5b5090506200028691906200028a565b5090565b620002af91905b80821115620002ab57600081600090555060010162000291565b5090565b90565b61168680620002c26000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd146102285780632b4e4e9614610251578063313ce567146102ca578063323046b1146102f95780634bfbe5df1461038757806370a082311461041557806372c5cb63146104a357806395d89b41146104cc578063a0d8848c1461055a578063a270a73714610583578063b4dbf64214610611578063c2bf17b014610641578063e22bda35146106ef578063ea8b5ca31461077d578063f0141d84146107aa578063fe60ebdc146107d3575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086b565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610875565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061091d565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610aa5565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b6102c8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610aae565b005b34156102d557600080fd5b6102dd610cc8565b604051808260ff1660ff16815260200191505060405180910390f35b341561030457600080fd5b61030c610ccd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561034c578082015181840152602081019050610331565b50505050905090810190601f1680156103795780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561039257600080fd5b61039a610d6b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103da5780820151818401526020810190506103bf565b50505050905090810190601f1680156104075780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561042057600080fd5b61044c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e13565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561048f578082015181840152602081019050610474565b505050509050019250505060405180910390f35b34156104ae57600080fd5b6104b6610eb0565b6040518082815260200191505060405180910390f35b34156104d757600080fd5b6104df610eba565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561051f578082015181840152602081019050610504565b50505050905090810190601f16801561054c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561056557600080fd5b61056d610f62565b6040518082815260200191505060405180910390f35b341561058e57600080fd5b610596610f6c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156105d65780820151818401526020810190506105bb565b50505050905090810190601f1680156106035780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610627600480803590602001909190505061100a565b604051808215151515815260200191505060405180910390f35b341561064c57600080fd5b61068c60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050611138565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156106fa57600080fd5b61070261129a565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610742578082015181840152602081019050610727565b50505050905090810190601f16801561076f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561078857600080fd5b610790611342565b604051808215151515815260200191505060405180910390f35b34156107b557600080fd5b6107bd61135f565b6040518082815260200191505060405180910390f35b34156107de57600080fd5b610869600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061136a565b005b6000600d54905090565b61087d6115e1565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109135780601f106108e857610100808354040283529160200191610913565b820191906000526020600020905b8154815290600101906020018083116108f657829003601f168201915b5050505050905090565b6000806000806000806000806109358c8c8c8c611138565b9650965096509650600d546003548761ffff1601111561095457600080fd5b8561ffff168502925083801561096957508234145b15610a91576006543481151561097b57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109c357600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a2557600080fd5b6007600081548092919060010191905055508561ffff16600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019750610a96565b600080fd5b50505050505050949350505050565b60008054905090565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610b0057600080fd5b600090505b8151811015610c7557600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610b5f91906115f5565b91600052602060002090016000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610bb957fe5b90602001906020020151815481101515610bcf57fe5b906000526020600020900154909190915055506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610c3157fe5b90602001906020020151815481101515610c4757fe5b9060005260206000209001819055506007600081548092919060010191905055508080600101915050610b05565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550505050565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d635780601f10610d3857610100808354040283529160200191610d63565b820191906000526020600020905b815481529060010190602001808311610d4657829003601f168201915b505050505081565b610d736115e1565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e095780601f10610dde57610100808354040283529160200191610e09565b820191906000526020600020905b815481529060010190602001808311610dec57829003601f168201915b5050505050905090565b610e1b611621565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ea457602002820191906000526020600020905b815481526020019060010190808311610e90575b50505050509050919050565b6000600754905090565b610ec26115e1565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f585780601f10610f2d57610100808354040283529160200191610f58565b820191906000526020600020905b815481529060010190602001808311610f3b57829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156110025780601f10610fd757610100808354040283529160200191611002565b820191906000526020600020905b815481529060010190602001808311610fe557829003601f168201915b505050505081565b60008082600c54023414158061102d5750600060018481151561102957fe5b0614155b1561103757600080fd5b60035490505b60035483018110156110bc57600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161109a91906115f5565b916000526020600020900160008390919091505550808060010191505061103d565b82600360008282540192505081905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561112e57600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e757600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003101561128a576000905061128f565b600190505b945094509450949050565b6112a26115e1565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113385780601f1061130d57610100808354040283529160200191611338565b820191906000526020600020905b81548152906001019060200180831161131b57829003601f168201915b5050505050905090565b6000600454421115611357576001905061135c565b600090505b90565b60008060ff16905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113c857600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050101561141857600080fd5b600090505b815181101561158d57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161147791906115f5565b91600052602060002090016000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002085858151811015156114d157fe5b906020019060200201518154811015156114e757fe5b906000526020600020900154909190915055506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561154957fe5b9060200190602002015181548110151561155f57fe5b906000526020600020900181905550600760008154809291906001019190505550808060010191505061141d565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555050505050565b602060405190810160405280600081525090565b81548183558181151161161c5781836000526020600020918201910161161b9190611635565b5b505050565b602060405190810160405280600081525090565b61165791905b8082111561165357600081600090555060010161163b565b5090565b905600a165627a7a72305820e5a23be67453636fe4b69894d7f2a63e90e8f89b6c7f2a44cc0831e57b4c9a24002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000f47656f6361636865204d65657475700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a33302f30312f323031370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000134f6c64204368616e676920486f73706974616c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000347454f0000000000000000000000000000000000000000000000000000000000" + , "0x23b872dd000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0xa9059cbb000000000000000000000000cb53390d32495163936ee451fee7089cd30be33c0000000000000000000000000000000000000000000000000000000000000002" + , "0x60606040526000600355600060075534156200001a57600080fd5b604051620019483803806200194883398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000e0929190620001b1565b508660048190555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560068190555082600990805190602001906200014892919062000203565b5087600890805190602001906200016192919062000203565b5084600a90805190602001906200017a92919062000203565b5083600b90805190602001906200019392919062000203565b5081600c8190555080600d81905550505050505050505050620002b2565b828054828255906000526020600020908101928215620001f0579160200282015b82811115620001ef578251825591602001919060010190620001d2565b5b509050620001ff91906200028a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024657805160ff191683800117855562000277565b8280016001018555821562000277579182015b828111156200027657825182559160200191906001019062000259565b5b5090506200028691906200028a565b5090565b620002af91905b80821115620002ab57600081600090555060010162000291565b5090565b90565b61168680620002c26000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd146102285780632b4e4e9614610251578063313ce567146102ca578063323046b1146102f95780634bfbe5df1461038757806370a082311461041557806372c5cb63146104a357806395d89b41146104cc578063a0d8848c1461055a578063a270a73714610583578063b4dbf64214610611578063c2bf17b014610641578063e22bda35146106ef578063ea8b5ca31461077d578063f0141d84146107aa578063fe60ebdc146107d3575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a61086b565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b610153610875565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061091d565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610aa5565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b6102c8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610aae565b005b34156102d557600080fd5b6102dd610cc8565b604051808260ff1660ff16815260200191505060405180910390f35b341561030457600080fd5b61030c610ccd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561034c578082015181840152602081019050610331565b50505050905090810190601f1680156103795780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561039257600080fd5b61039a610d6b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103da5780820151818401526020810190506103bf565b50505050905090810190601f1680156104075780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561042057600080fd5b61044c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e13565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561048f578082015181840152602081019050610474565b505050509050019250505060405180910390f35b34156104ae57600080fd5b6104b6610eb0565b6040518082815260200191505060405180910390f35b34156104d757600080fd5b6104df610eba565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561051f578082015181840152602081019050610504565b50505050905090810190601f16801561054c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561056557600080fd5b61056d610f62565b6040518082815260200191505060405180910390f35b341561058e57600080fd5b610596610f6c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156105d65780820151818401526020810190506105bb565b50505050905090810190601f1680156106035780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610627600480803590602001909190505061100a565b604051808215151515815260200191505060405180910390f35b341561064c57600080fd5b61068c60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050611138565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156106fa57600080fd5b61070261129a565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610742578082015181840152602081019050610727565b50505050905090810190601f16801561076f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561078857600080fd5b610790611342565b604051808215151515815260200191505060405180910390f35b34156107b557600080fd5b6107bd61135f565b6040518082815260200191505060405180910390f35b34156107de57600080fd5b610869600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061136a565b005b6000600d54905090565b61087d6115e1565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109135780601f106108e857610100808354040283529160200191610913565b820191906000526020600020905b8154815290600101906020018083116108f657829003601f168201915b5050505050905090565b6000806000806000806000806109358c8c8c8c611138565b9650965096509650600d546003548761ffff1601111561095457600080fd5b8561ffff168502925083801561096957508234145b15610a91576006543481151561097b57fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015156109c357600080fd5b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610a2557600080fd5b6007600081548092919060010191905055508561ffff16600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019750610a96565b600080fd5b50505050505050949350505050565b60008054905090565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610b0057600080fd5b600090505b8151811015610c7557600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610b5f91906115f5565b91600052602060002090016000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208585815181101515610bb957fe5b90602001906020020151815481101515610bcf57fe5b906000526020600020900154909190915055506000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208383815181101515610c3157fe5b90602001906020020151815481101515610c4757fe5b9060005260206000209001819055506007600081548092919060010191905055508080600101915050610b05565b8151600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550505050565b600081565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d635780601f10610d3857610100808354040283529160200191610d63565b820191906000526020600020905b815481529060010190602001808311610d4657829003601f168201915b505050505081565b610d736115e1565b600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e095780601f10610dde57610100808354040283529160200191610e09565b820191906000526020600020905b815481529060010190602001808311610dec57829003601f168201915b5050505050905090565b610e1b611621565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610ea457602002820191906000526020600020905b815481526020019060010190808311610e90575b50505050509050919050565b6000600754905090565b610ec26115e1565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f585780601f10610f2d57610100808354040283529160200191610f58565b820191906000526020600020905b815481529060010190602001808311610f3b57829003601f168201915b5050505050905090565b6000600c54905090565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156110025780601f10610fd757610100808354040283529160200191611002565b820191906000526020600020905b815481529060010190602001808311610fe557829003601f168201915b505050505081565b60008082600c54023414158061102d5750600060018481151561102957fe5b0614155b1561103757600080fd5b60035490505b60035483018110156110bc57600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161109a91906115f5565b916000526020600020900160008390919091505550808060010191505061103d565b82600360008282540192505081905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561112e57600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156111e757600080fd5b50506020604051035193508261ffff16600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905003101561128a576000905061128f565b600190505b945094509450949050565b6112a26115e1565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113385780601f1061130d57610100808354040283529160200191611338565b820191906000526020600020905b81548152906001019060200180831161131b57829003601f168201915b5050505050905090565b6000600454421115611357576001905061135c565b600090505b90565b60008060ff16905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113c857600080fd5b8151600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050101561141857600080fd5b600090505b815181101561158d57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480600101828161147791906115f5565b91600052602060002090016000600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002085858151811015156114d157fe5b906020019060200201518154811015156114e757fe5b906000526020600020900154909190915055506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838381518110151561154957fe5b9060200190602002015181548110151561155f57fe5b906000526020600020900181905550600760008154809291906001019190505550808060010191505061141d565b8151600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555050505050565b602060405190810160405280600081525090565b81548183558181151161161c5781836000526020600020918201910161161b9190611635565b5b505050565b602060405190810160405280600081525090565b61165791905b8082111561165357600081600090555060010161163b565b5090565b905600a165627a7a72305820d2f7d7b61cacd1e9d44d53fbe9eb95c0ae51787109504667e8403fd3a4f310ef002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000b4d4a20636f6d656261636b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a32312f31302f323032300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094d474d206772616e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d4a430000000000000000000000000000000000000000000000000000000000" + , "0x60606040526000600255600060065534156200001a57600080fd5b604051620016ea380380620016ea83398101604052808051820191906020018051820191906020018051906020019091908051906020019091908051820191906020018051820191906020018051820191906020018051906020019091908051906020019091905050885160008190555088600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190620000e0929190620001b1565b508660038190555033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560058190555082600890805190602001906200014892919062000203565b5087600790805190602001906200016192919062000203565b5084600990805190602001906200017a92919062000203565b5083600a90805190602001906200019392919062000203565b5081600b8190555080600c81905550505050505050505050620002b2565b828054828255906000526020600020908101928215620001f0579160200282015b82811115620001ef578251825591602001919060010190620001d2565b5b509050620001ff91906200028a565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024657805160ff191683800117855562000277565b8280016001018555821562000277579182015b828111156200027657825182559160200191906001019062000259565b5b5090506200028691906200028a565b5090565b620002af91905b80821115620002ab57600081600090555060010162000291565b5090565b90565b61142880620002c26000396000f300606060405260043610610107576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461011757806306fdde03146101405780630e1c2d46146101ce57806318160ddd1461022857806323b872dd146102515780632b4e4e96146102b2578063313ce5671461032b578063323046b11461035a5780634bfbe5df146103e857806370a082311461047657806372c5cb631461050457806395d89b411461052d578063a0d8848c146105bb578063a270a737146105e4578063b4dbf64214610672578063c2bf17b0146106a2578063e22bda3514610750578063ea8b5ca3146107de578063f0141d841461080b575b341561011257600080fd5b600080fd5b341561012257600080fd5b61012a610834565b6040518082815260200191505060405180910390f35b341561014b57600080fd5b61015361083e565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610193578082015181840152602081019050610178565b50505050905090810190601f1680156101c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020e60048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506108e6565b604051808215151515815260200191505060405180910390f35b341561023357600080fd5b61023b610a1d565b6040518082815260200191505060405180910390f35b341561025c57600080fd5b6102b0600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a26565b005b34156102bd57600080fd5b610329600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610bc6565b005b341561033657600080fd5b61033e610d22565b604051808260ff1660ff16815260200191505060405180910390f35b341561036557600080fd5b61036d610d27565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103ad578082015181840152602081019050610392565b50505050905090810190601f1680156103da5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103f357600080fd5b6103fb610dc5565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043b578082015181840152602081019050610420565b50505050905090810190601f1680156104685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561048157600080fd5b6104ad600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e6d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156104f05780820151818401526020810190506104d5565b505050509050019250505060405180910390f35b341561050f57600080fd5b610517610f0a565b6040518082815260200191505060405180910390f35b341561053857600080fd5b610540610f14565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610580578082015181840152602081019050610565565b50505050905090810190601f1680156105ad5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105c657600080fd5b6105ce610fbc565b6040518082815260200191505060405180910390f35b34156105ef57600080fd5b6105f7610fc6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561063757808201518184015260208101905061061c565b50505050905090810190601f1680156106645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6106886004808035906020019091905050611064565b604051808215151515815260200191505060405180910390f35b34156106ad57600080fd5b6106ed60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050611192565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b341561075b57600080fd5b6107636112b3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107a3578082015181840152602081019050610788565b50505050905090810190601f1680156107d05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156107e957600080fd5b6107f161135b565b604051808215151515815260200191505060405180910390f35b341561081657600080fd5b61081e611378565b6040518082815260200191505060405180910390f35b6000600c54905090565b610846611383565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108dc5780601f106108b1576101008083540402835291602001916108dc565b820191906000526020600020905b8154815290600101906020018083116108bf57829003601f168201915b5050505050905090565b6000806000806000806000806108fe8c8c8c8c611192565b9650965096509650600c546002548761ffff1601111561091d57600080fd5b8561ffff168502925083801561093257508234145b15610a09576005543481151561094457fe5b04915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561098c57600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f1935050505015156109ee57600080fd5b60066000815480929190600101919050555060019750610a0e565b600080fd5b50505050505050949350505050565b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610a8457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610ad357600080fd5b600090505b81811015610bc057600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610b319190611397565b916000526020600020900160008390919091505550600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081815481101515610b9257fe5b9060005260206000209001600090556006600081548092919060010191905055508080600101915050610ad8565b50505050565b60008151600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501015610c1857600080fd5b600090505b8151811015610d1d57600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806001018281610c779190611397565b916000526020600020900160008484815181101515610c9257fe5b9060200190602002015190919091505550600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081815481101515610cef57fe5b9060005260206000209001600090556006600081548092919060010191905055508080600101915050610c1d565b505050565b600081565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610dbd5780601f10610d9257610100808354040283529160200191610dbd565b820191906000526020600020905b815481529060010190602001808311610da057829003601f168201915b505050505081565b610dcd611383565b60098054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e635780601f10610e3857610100808354040283529160200191610e63565b820191906000526020600020905b815481529060010190602001808311610e4657829003601f168201915b5050505050905090565b610e756113c3565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610efe57602002820191906000526020600020905b815481526020019060010190808311610eea575b50505050509050919050565b6000600654905090565b610f1c611383565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fb25780601f10610f8757610100808354040283529160200191610fb2565b820191906000526020600020905b815481529060010190602001808311610f9557829003601f168201915b5050505050905090565b6000600b54905090565b600a8054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561105c5780601f106110315761010080835404028352916020019161105c565b820191906000526020600020905b81548152906001019060200180831161103f57829003601f168201915b505050505081565b60008082600b5402341415806110875750600060018481151561108357fe5b0614155b1561109157600080fd5b60025490505b600254830181101561111657600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816110f49190611397565b9160005260206000209001600083909190915055508080600101915050611097565b82600260008282540192505081905550600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561118857600080fd5b6001915050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561124157600080fd5b50506020604051035193508261ffff16600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054905010156112a357600090506112a8565b600190505b945094509450949050565b6112bb611383565b600a8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113515780601f1061132657610100808354040283529160200191611351565b820191906000526020600020905b81548152906001019060200180831161133457829003601f168201915b5050505050905090565b60006003544211156113705760019050611375565b600090505b90565b60008060ff16905090565b602060405190810160405280600081525090565b8154818355818115116113be578183600052602060002091820191016113bd91906113d7565b5b505050565b602060405190810160405280600081525090565b6113f991905b808211156113f55760008160009055506001016113dd565b5090565b905600a165627a7a7230582022cfd54936a82a7fa6bfc9a23f54bc20104eccb8ede93c36e4c2ab2cef5d17c5002900000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000b4d4a20636f6d656261636b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a32312f31302f323032300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094d474d206772616e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d4a430000000000000000000000000000000000000000000000000000000000" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x6060604052600060055534156200001557600080fd5b60405162001aee38038062001aee8339810160405280805190602001909190805182019190602001805190602001909190805190602001909190805182019190602001805182019190602001805182019190602001805190602001909190805190602001909190505088600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508660028190555033600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606486670de0b6b3a7640000028115156200012a57fe5b0460048190555082600790805190602001906200014992919062000234565b5087600690805190602001906200016292919062000234565b5084600890805190602001906200017b92919062000234565b5083600990805190602001906200019492919062000234565b5081600b8190555080600c81905550620001c1620001d06401000000000262001495176401000000009004565b505050505050505050620002e3565b6103e860016000727bee82bdd9e866b2bd114780a47f2261c684e373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200027757805160ff1916838001178555620002a8565b82800160010185558215620002a8579182015b82811115620002a75782518255916020019190600101906200028a565b5b509050620002b79190620002bb565b5090565b620002e091905b80821115620002dc576000816000905550600101620002c2565b5090565b90565b6117fb80620002f36000396000f300606060405260043610610128576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461013857806306fdde03146101615780630e1c2d46146101ef57806318160ddd1461029d57806323b872dd146102c6578063313ce5671461033f578063323046b11461036e578063454b6be1146103fc5780634bfbe5df146104bc57806370a082311461054a57806372c5cb63146105975780638043c9c0146105c057806395d89b411461064e578063a0d8848c146106dc578063a270a73714610705578063a9059cbb14610793578063aa6ca808146107ed578063b4dbf64214610802578063c2bf17b014610832578063e22bda35146108e0578063ea8b5ca31461096e578063f0141d841461099b575b341561013357600080fd5b600080fd5b341561014357600080fd5b61014b6109c4565b6040518082815260200191505060405180910390f35b341561016c57600080fd5b6101746109ce565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101b4578082015181840152602081019050610199565b50505050905090810190601f1680156101e15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156101fa57600080fd5b61023a60048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610a6c565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156102a857600080fd5b6102b0610b7a565b6040518082815260200191505060405180910390f35b34156102d157600080fd5b610325600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b83565b604051808215151515815260200191505060405180910390f35b341561034a57600080fd5b610352610d4f565b604051808260ff1660ff16815260200191505060405180910390f35b341561037957600080fd5b610381610d54565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c15780820151818401526020810190506103a6565b50505050905090810190601f1680156103ee5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040757600080fd5b61044760048080356000191690602001909190803560ff169060200190919080356000191690602001909190803560001916906020019091905050610df2565b604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018661ffff1661ffff1681526020018581526020018415151515815260200183815260200182151515158152602001965050505050505060405180910390f35b34156104c757600080fd5b6104cf6110a8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561050f5780820151818401526020810190506104f4565b50505050905090810190601f16801561053c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561055557600080fd5b610581600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611150565b6040518082815260200191505060405180910390f35b34156105a257600080fd5b6105aa611199565b6040518082815260200191505060405180910390f35b34156105cb57600080fd5b6105d36111a3565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106135780820151818401526020810190506105f8565b50505050905090810190601f1680156106405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561065957600080fd5b61066161124b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156106a1578082015181840152602081019050610686565b50505050905090810190601f1680156106ce5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156106e757600080fd5b6106ef6112e9565b6040518082815260200191505060405180910390f35b341561071057600080fd5b6107186112f3565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561075857808201518184015260208101905061073d565b50505050905090810190601f1680156107855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561079e57600080fd5b6107d3600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050611391565b604051808215151515815260200191505060405180910390f35b34156107f857600080fd5b610800611495565b005b61081860048080359060200190919050506114f9565b604051808215151515815260200191505060405180910390f35b341561083d57600080fd5b61087d60048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506115dd565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156108eb57600080fd5b6108f36116eb565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610933578082015181840152602081019050610918565b50505050905090810190601f1680156109605780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561097957600080fd5b610981611793565b604051808215151515815260200191505060405180910390f35b34156109a657600080fd5b6109ae6117b0565b6040518082815260200191505060405180910390f35b6000600c54905090565b60068054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a645780601f10610a3957610100808354040283529160200191610a64565b820191906000526020600020905b815481529060010190602001808311610a4757829003601f168201915b505050505081565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610b1b57600080fd5b50506020604051035193508261ffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410159050945094509450949050565b60008054905090565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610be157600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515610d435781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360056000815480929190600101919050555060019050610d48565b600090505b9392505050565b600081565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610dea5780601f10610dbf57610100808354040283529160200191610dea565b820191906000526020600020905b815481529060010190602001808311610dcd57829003601f168201915b505050505081565b60008060008060008060008061ffff6001028c166001900496506010808d600019169060020a9004600019169060020a0260019004955060018c8c8c8c604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f11515610ea757600080fd5b50506020604051035197508661ffff16600160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101594508661ffff16860293508334101515610f165760019250610f1b565b600092505b848015610f255750825b15611099578661ffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508661ffff16600160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600454606434811515610fdb57fe5b0402915081340390508773ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561102457600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050151561108657600080fd5b6005600081548092919060010191905055505b50509499939850945094509450565b6110b06117bb565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156111465780601f1061111b57610100808354040283529160200191611146565b820191906000526020600020905b81548152906001019060200180831161112957829003601f168201915b5050505050905090565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600554905090565b6111ab6117bb565b60068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112415780601f1061121657610100808354040283529160200191611241565b820191906000526020600020905b81548152906001019060200180831161122457829003601f168201915b5050505050905090565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112e15780601f106112b6576101008083540402835291602001916112e1565b820191906000526020600020905b8154815290600101906020018083116112c457829003601f168201915b505050505081565b6000600b54905090565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113895780601f1061135e57610100808354040283529160200191611389565b820191906000526020600020905b81548152906001019060200180831161136c57829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156113df57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506005600081548092919060010191905055506001905092915050565b6103e860016000727bee82bdd9e866b2bd114780a47f2261c684e373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550565b600081600b54023414158061151b5750600060018381151561151757fe5b0614155b1561152557600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050151561158757600080fd5b60018060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f1151561168c57600080fd5b50506020604051035193508261ffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410159050945094509450949050565b6116f36117bb565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117895780601f1061175e57610100808354040283529160200191611789565b820191906000526020600020905b81548152906001019060200180831161176c57829003601f168201915b5050505050905090565b60006002544211156117a857600190506117ad565b600090505b90565b60008060ff16905090565b6020604051908101604052806000815250905600a165627a7a72305820aa4ec49a3d3c615a410bf3e2805df4b0443a492f214dd4d73874911ebbb25efe002900000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000145472616e73706172656e7420506172616469676d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a32332f30352f3230313800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f53696e6761706f726520466c796572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035450470000000000000000000000000000000000000000000000000000000000" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x6060604052600060055534156200001557600080fd5b604051620016ca380380620016ca8339810160405280805190602001909190805182019190602001805190602001909190805190602001909190805182019190602001805182019190602001805182019190602001805190602001909190805190602001909190505088600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508660028190555033600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606486670de0b6b3a7640000028115156200012a57fe5b04600481905550826007908051906020019062000149929190620001b2565b50876006908051906020019062000162929190620001b2565b5084600890805190602001906200017b929190620001b2565b50836009908051906020019062000194929190620001b2565b5081600b8190555080600c8190555050505050505050505062000261565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001f557805160ff191683800117855562000226565b8280016001018555821562000226579182015b828111156200022557825182559160200191906001019062000208565b5b50905062000235919062000239565b5090565b6200025e91905b808211156200025a57600081600090555060010162000240565b5090565b90565b61145980620002716000396000f300606060405260043610610112576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301cff1741461012257806306fdde031461014b5780630e1c2d46146101d957806318160ddd1461023357806323b872dd1461025c578063313ce567146102d5578063323046b1146103045780634bfbe5df1461039257806370a082311461042057806372c5cb631461046d5780638043c9c01461049657806395d89b4114610524578063a0d8848c146105b2578063a270a737146105db578063a9059cbb14610669578063b4dbf642146106c3578063c2bf17b0146106f3578063e22bda35146107a1578063ea8b5ca31461082f578063f0141d841461085c575b341561011d57600080fd5b600080fd5b341561012d57600080fd5b610135610885565b6040518082815260200191505060405180910390f35b341561015657600080fd5b61015e61088f565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561019e578082015181840152602081019050610183565b50505050905090810190601f1680156101cb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61021960048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061092d565b604051808215151515815260200191505060405180910390f35b341561023e57600080fd5b610246610af2565b6040518082815260200191505060405180910390f35b341561026757600080fd5b6102bb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610afb565b604051808215151515815260200191505060405180910390f35b34156102e057600080fd5b6102e8610cc7565b604051808260ff1660ff16815260200191505060405180910390f35b341561030f57600080fd5b610317610ccc565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561035757808201518184015260208101905061033c565b50505050905090810190601f1680156103845780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561039d57600080fd5b6103a5610d6a565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103e55780820151818401526020810190506103ca565b50505050905090810190601f1680156104125780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561042b57600080fd5b610457600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e12565b6040518082815260200191505060405180910390f35b341561047857600080fd5b610480610e5b565b6040518082815260200191505060405180910390f35b34156104a157600080fd5b6104a9610e65565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104e95780820151818401526020810190506104ce565b50505050905090810190601f1680156105165780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561052f57600080fd5b610537610f0d565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561057757808201518184015260208101905061055c565b50505050905090810190601f1680156105a45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156105bd57600080fd5b6105c5610fab565b6040518082815260200191505060405180910390f35b34156105e657600080fd5b6105ee610fb5565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561062e578082015181840152602081019050610613565b50505050905090810190601f16801561065b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561067457600080fd5b6106a9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050611053565b604051808215151515815260200191505060405180910390f35b6106d96004808035906020019091905050611157565b604051808215151515815260200191505060405180910390f35b34156106fe57600080fd5b61073e60048080356000191690602001909190803560ff16906020019091908035600019169060200190919080356000191690602001909190505061123b565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018461ffff1661ffff1681526020018381526020018215151515815260200194505050505060405180910390f35b34156107ac57600080fd5b6107b4611349565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107f45780820151818401526020810190506107d9565b50505050905090810190601f1680156108215780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561083a57600080fd5b6108426113f1565b604051808215151515815260200191505060405180910390f35b341561086757600080fd5b61086f61140e565b6040518082815260200191505060405180910390f35b6000600c54905090565b60068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109255780601f106108fa57610100808354040283529160200191610925565b820191906000526020600020905b81548152906001019060200180831161090857829003601f168201915b505050505081565b6000806000806000806000806109458c8c8c8c61123b565b96509650965096508561ffff168502925083801561096257508234145b15610ade578561ffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508561ffff16600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600454606434811515610a1857fe5b0402915081340390508673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501515610a6157600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501515610ac357600080fd5b60056000815480929190600101919050555060019750610ae3565b600080fd5b50505050505050949350505050565b60008054905090565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610b5957600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515610cbb5781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360056000815480929190600101919050555060019050610cc0565b600090505b9392505050565b600081565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d625780601f10610d3757610100808354040283529160200191610d62565b820191906000526020600020905b815481529060010190602001808311610d4557829003601f168201915b505050505081565b610d72611419565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e085780601f10610ddd57610100808354040283529160200191610e08565b820191906000526020600020905b815481529060010190602001808311610deb57829003601f168201915b5050505050905090565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600554905090565b610e6d611419565b60068054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f035780601f10610ed857610100808354040283529160200191610f03565b820191906000526020600020905b815481529060010190602001808311610ee657829003601f168201915b5050505050905090565b60078054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610fa35780601f10610f7857610100808354040283529160200191610fa3565b820191906000526020600020905b815481529060010190602001808311610f8657829003601f168201915b505050505081565b6000600b54905090565b60098054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561104b5780601f106110205761010080835404028352916020019161104b565b820191906000526020600020905b81548152906001019060200180831161102e57829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156110a157600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506005600081548092919060010191905055506001905092915050565b600081600b5402341415806111795750600060018381151561117557fe5b0614155b1561118357600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f1935050505015156111e557600080fd5b60018060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060019050919050565b60008060008061ffff600102881660019004925060108089600019169060020a9004600019169060020a02600190049150600188888888604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156112ea57600080fd5b50506020604051035193508261ffff16600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410159050945094509450949050565b611351611419565b60098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156113e75780601f106113bc576101008083540402835291602001916113e7565b820191906000526020600020905b8154815290600101906020018083116113ca57829003601f168201915b5050505050905090565b6000600254421115611406576001905061140b565b600090505b90565b60008060ff16905090565b6020604051908101604052806000815250905600a165627a7a72305820a031d8b8554004fd703791c0c564d2ec4cb2edcb93a3425b0b36d61fe6ede01f002900000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000005f8e28800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b4d4a20636f6d656261636b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a32312f31302f323032300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094d474d206772616e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d4a430000000000000000000000000000000000000000000000000000000000" + , "0xf2fde38b0000000000000000000000000000000000000000000000000000000000000000" + , "0xad8733ca000000000000000000000000352505482ceaf9d95f76da5d3f84e8d630b78c3b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000006000000000000000000000000dacc9c61754a0c4616fc5323dc946e89eb27230200000000000000000000000027af1b9c0490a8d656ffa32a7e56b85cdf211ea8000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000021acfd9f199fa91213a23193c9504f10cac2f06300000000000000000000000081b7e08f65bdf5648606c89998a9cc8164397647000000000000000000000000efde75ccae5c0f8fe856b22e2a175254e7f2b7330000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002710" + , "0x" + , "0xa9059cbb000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000008ac7230489e80000" + , "0x" + , "0x" + , "0x299251cd00000000000000000000000074ab01a13bb912c73415d1e65a167108627f6ada00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000032000000000000000000000000cca455208df89d37ddc1a82aec0fda159137517b0000000000000000000000002e863634ec7d9f2b5c841ea4e2e83d8e32846e8500000000000000000000000095c3d3d6b571549bb2cbf9d0587c3e979a62a1990000000000000000000000002be55849cc424dacb12bdfc199fdceeeab0ef705000000000000000000000000011e8238342f403eb24bb599b3a4f86a87de6282000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000016de4774f2542a1bc49b9cd0b8a80b769468ebd4000000000000000000000000a240b902887e16759d679aaa8292cb84c6f6c2c6000000000000000000000000dd50c2060939ac1f94e201278286b0a0d03037c80000000000000000000000008aa76da4127d74923d2cf0f9e97aa3afcb747d18000000000000000000000000085be78299d6271939e7b732e87643d7367f60a5000000000000000000000000465dc984a581e40d4f29f69e00afff07042b2c310000000000000000000000008f7f202a7ec7e24118e0c5426397fb3eb5a59a15000000000000000000000000288fff976c024d3115bcd05e5e7578a19f60b1130000000000000000000000008042ebcc8217bb4271bd32ec7408fb60a6a35e3400000000000000000000000024f3f53c77f82ed99f72b09be92f3a477d82b5b70000000000000000000000007c34db57c20eab8f1fca9b76b93d44f65338dae7000000000000000000000000305d44857dae0197551e7c3597c9a03c8bd43e830000000000000000000000006c5ed14e0ba5e8f98bfbe08d8d31741aa6ee3fdb00000000000000000000000055e2780588aa5000f464f700d2676fd0a22ee1600000000000000000000000000af34f7ed6e29f5f08a6538f6588e8fb3d03601500000000000000000000000084dd81652899327ecf0ced2ecc704f208059834100000000000000000000000044601662c4888248a523cb742610c0a5cabd2648000000000000000000000000d136e8878fbc8a1cae779760b4b70447b4a5ef5d000000000000000000000000af1e444ec82f3c4b0a9f3b6f1a41b0f42b78303e00000000000000000000000000503510c51624c67ae3aa37b47af2ca270b586a000000000000000000000000433b4cc2b6dd3e8953ba9ba9a0c169a45125596a000000000000000000000000fc15859aee77be7de9d6d45478b0265988e3c9370000000000000000000000000080da07a81ba604f040d6f3050f913e33a0f9ab000000000000000000000000cade8041a96a65bdd95d44df5ccdf67e82c6da5b000000000000000000000000f657830abdcef58aa3fc1b7594dc85fc8aa6a5c5000000000000000000000000004e5b2467a8f1861e920c384ceb03f771a35cb60000000000000000000000002e2ae2675b929f81326d5960b8d8063ed96418e00000000000000000000000008b93db60ab13819dcc0428cb5cbe5389e361f57300000000000000000000000059a15efa6b3326cfced0ffdb398a500478081302000000000000000000000000e441aba5aef9081d76c01b0767d0bfd934c04410000000000000000000000000e55f33961a656255d1870750a931c6af97e2e67b0000000000000000000000001534c5916595197c8dd270af3167b90a84a64ae2000000000000000000000000ce31dfe738fcb8272bb275ad6b199a2fbae71b9c0000000000000000000000007ee90046baff191a86a716de3a110faccc53a894000000000000000000000000edbc6ec9d2fb3f63a45502f66283bad1061150b8000000000000000000000000be969db1c039ce0203c9c4c27cf5c6e0d3c318be0000000000000000000000001278302a6d8c8cf0bf68409b1719208b2a18086a0000000000000000000000005ef9f1cf1acab0638a65bd969471a7a7754899950000000000000000000000009b86ce9d21c1394c2f9d9cf7f86415258ee4d6ae0000000000000000000000006594d8ab68a8192a82a4642436c24f76952fbaf30000000000000000000000005d1d6ff025e471e0a76058fde9ec01e979d749ac0000000000000000000000006d75461234a0898ce365c44b38f43cbc714d1431000000000000000000000000a160b0be09922d071bffaaa4be111ad93052b5e40000000000000000000000002601a089b9fc228c4a053ad1d96e52571824d468" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000027e4e09fe9743d6497b31504bfe2ad00d9567afd0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000092b6becccfb777223afd6d4f28461ad5469435be0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000ff7b12fff896f572e9e4dd31c3c2e8bcef8328980000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd00000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c830902000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c830902000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000079888add20834984e6b5a3d0676542c69c03b6740000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c8309020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c8309020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c8309020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000079888add20834984e6b5a3d0676542c69c03b6740000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd00000000000000000000000079888add20834984e6b5a3d0676542c69c03b674000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000038ea88b8e0d500206ff14af50c04bdc28c8309020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000001a68f5e645573c182a263a6d9391729789a7d1640000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000149512264d5077c092cc46472d6042e5006ae40b0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000001a68f5e645573c182a263a6d9391729789a7d1640000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000072d1ff0ecd51509f251d577891d686c7885aacff0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e9e6716d6458c334bb55cf70e19507df7bb816d90000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd0000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea7000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd0000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea7000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd0000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea7000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0xa9059cbb00000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a0200000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x60606040526000600655341561001457600080fd5b60405160808061069f8339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550809050505050506105a2806100fd6000396000f30060606040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007d57806323b872dd146100a657806370a082311461011f57806372c5cb631461016c578063a9059cbb14610195575b341561007857600080fd5b600080fd5b341561008857600080fd5b6100906101ef565b6040518082815260200191505060405180910390f35b34156100b157600080fd5b610105600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101f8565b604051808215151515815260200191505060405180910390f35b341561012a57600080fd5b610156600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506103ae565b6040518082815260200191505060405180910390f35b341561017757600080fd5b61017f6103f7565b6040518082815260200191505060405180910390f35b34156101a057600080fd5b6101d5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610401565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561025657600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103a65781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a3600190506103a7565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600654905090565b6000600554341080610451575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561045b57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360066000815480929190600101919050555060019050929150505600a165627a7a72305820723c6a75fca5e9610e120968d3f6d449318cef0110af304030cba3261381f4f10029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f706572610000000000000000000000000000000000000000000000000000000000000000000000005f751c000000000000000000000000000000000000000000000000000000000000000000" + , "0x60606040526000600655341561001457600080fd5b60405160808061069f8339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550809050505050506105a2806100fd6000396000f30060606040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007d57806323b872dd146100a657806370a082311461011f57806372c5cb631461016c578063a9059cbb14610195575b341561007857600080fd5b600080fd5b341561008857600080fd5b6100906101ef565b6040518082815260200191505060405180910390f35b34156100b157600080fd5b610105600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101f8565b604051808215151515815260200191505060405180910390f35b341561012a57600080fd5b610156600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506103ae565b6040518082815260200191505060405180910390f35b341561017757600080fd5b61017f6103f7565b6040518082815260200191505060405180910390f35b34156101a057600080fd5b6101d5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610401565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561025657600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103a65781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a3600190506103a7565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600654905090565b6000600554341080610451575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561045b57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360066000815480929190600101919050555060019050929150505600a165627a7a72305820723c6a75fca5e9610e120968d3f6d449318cef0110af304030cba3261381f4f10029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f706572610000000000000000000000000000000000000000000000000000000000000000000000005f751c000000000000000000000000000000000000000000000000000000000000000000" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007ce4cb3e0e4463872d0fa98ebe7c822600b44ea70000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x6060604052341561000f57600080fd5b60405160808061064a8339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080905050505050610552806100f86000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007257806323b872dd1461009b57806370a0823114610114578063a9059cbb14610161575b341561006d57600080fd5b600080fd5b341561007d57600080fd5b6100856101bb565b6040518082815260200191505060405180910390f35b34156100a657600080fd5b6100fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c4565b604051808215151515815260200191505060405180910390f35b341561011f57600080fd5b61014b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061037a565b6040518082815260200191505060405180910390f35b341561016c57600080fd5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103c3565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022257600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103725781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360019050610373565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000600554341080610413575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561041d57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050929150505600a165627a7a72305820fc6fe2b69ea1605361d5a2b9bd4cc8ef4e0426df34f8a1402caa8b2d90649b850029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f706572610000000000000000000000000000000000000000000000000000000000000000000000005f751c000000000000000000000000000000000000000000000000000000000000000000" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x6060604052341561000f57600080fd5b6040516080806106598339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080905050505050610561806100f86000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007257806323b872dd1461009b57806370a0823114610114578063a9059cbb14610161575b341561006d57600080fd5b600080fd5b341561007d57600080fd5b6100856101bb565b6040518082815260200191505060405180910390f35b34156100a657600080fd5b6100fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c4565b604051808215151515815260200191505060405180910390f35b341561011f57600080fd5b61014b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061037a565b6040518082815260200191505060405180910390f35b341561016c57600080fd5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103c3565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022257600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103725781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360019050610373565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006003544211156103d457600080fd5b600554341080610422575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561042c57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050929150505600a165627a7a72305820081acc60d332bcea2f22d1abd81dc46314c54c9c2d71482c0214b3aa2d112ee70029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f70657261000000000000000000000000000000000000000000000000000000000000000000000174e17560000000000000000000000000000000000000000000000000000000000000000000" + , "0xa9059cbb000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f42956738a7c308193772298cd25dea5172b269c0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd00000000000000000000000056c35ccfd4d5c7b4c900c77f886c0e65772eff67000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000056c35ccfd4d5c7b4c900c77f886c0e65772eff670000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000002" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x2e1b8e21000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004d2000000000000000000000000000000000000000000000000000000000000000b3132333431323334323334000000000000000000000000000000000000000000" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x3078000000000000000000000000007bee82bdefbfbdefbfbd66efbfbdefbfbd1147efbfbdefbfbd7f2261c684efbfbd000000000000000000000000efbfbd6d4befbfbdefbfbd2d0b0e6fefbfbd7f08efbfbdefbfbdefbfbd2fefbfbd052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000052ac85518e73102c20ecf82e08df0a396e4e518a0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x6060604052341561000f57600080fd5b6040516080806106598339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080905050505050610561806100f86000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007257806323b872dd1461009b57806370a0823114610114578063a9059cbb14610161575b341561006d57600080fd5b600080fd5b341561007d57600080fd5b6100856101bb565b6040518082815260200191505060405180910390f35b34156100a657600080fd5b6100fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c4565b604051808215151515815260200191505060405180910390f35b341561011f57600080fd5b61014b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061037a565b6040518082815260200191505060405180910390f35b341561016c57600080fd5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103c3565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022257600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015156103725781600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc0d84ce5c7ff9ca21adb0f8436ff3f4951b4bb78c4e2fae2b6837958b3946ffd846040518082815260200191505060405180910390a360019050610373565b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006003544211156103d457600080fd5b600554341080610422575081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561042c57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050929150505600a165627a7a72305820081acc60d332bcea2f22d1abd81dc46314c54c9c2d71482c0214b3aa2d112ee70029000000000000000000000000000000000000000000000000000000000000c350546865207068616e746f6d206f6620746865206f706572610000000000000000000000000000000000000000000000000000000000000000000000005f751c000000000000000000000000000000000000000000000000000000000000000000" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe20000000000000000000000005bb8d47bb262aaeabef2207d1d4af3b13fb8d8e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe20000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd0000000000000000000000005bb8d47bb262aaeabef2207d1d4af3b13fb8d8e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000005bb8d47bb262aaeabef2207d1d4af3b13fb8d8e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000005bb8d47bb262aaeabef2207d1d4af3b13fb8d8e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c00000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e66a51f8e269e6c6354bb61f0a3904b447e0057c0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000091a706cac5e3518304c120b37abedf19a119c48c0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe2000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe20000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe2000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000762951843c1ec71b7584185cc48ccb2eb3b47fe20000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000548c014de6a4a6511bd33dfaea0cfb0069d09baf0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000f0c41dfeda441aaeafb5b7b3174001ea7acb4aab0000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fea78a32aaedb0908857ac74598c078f73adeee00000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000b1c36cac20c0127d9c24271d1d97ee45002056650000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000617ded54ec054f8be89147e9def2f68a24be101d0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000264a2629bc956327b37657b50306d83543a51c57000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000009d6268a6a7f62b73c3a55ccddde2f2796db497750000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000002f48d567cebe41df9f2e5093fb8962b5ae9517760000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000bece95c79dd839dacb162cc70fd408a5596cbf9e0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000264a2629bc956327b37657b50306d83543a51c570000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000edf94b3c304217f6e8b89cd8c6330ee027e12f360000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000455e83b7c3a2f264ba2fb0bc96b3cf315c8591f6000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000455e83b7c3a2f264ba2fb0bc96b3cf315c8591f6000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000455e83b7c3a2f264ba2fb0bc96b3cf315c8591f60000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000007b91f7618a158137f23b09c4e2190cc27587c2570000000000000000000000000000000000000000000000000000000000000001" + , "0x6060604052341561000f57600080fd5b6040516080806105438339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505050505061044b806100f86000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007057806323b872dd1461009957806370a0823114610112578063a9059cbb1461015f575b341561006b57600080fd5b600080fd5b341561007b57600080fd5b6100836101b9565b6040518082815260200191505060405180910390f35b34156100a457600080fd5b6100f8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c2565b604051808215151515815260200191505060405180910390f35b341561011d57600080fd5b610149600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102c5565b6040518082815260200191505060405180910390f35b341561016a57600080fd5b61019f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061030e565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022057600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190509392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600060035442111561031f57600080fd5b60055434108061037157506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561037b57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050929150505600a165627a7a72305820af0e8d60e0b80d2599f4b5d2996c65865e2fc9fb93028e319a6a8ff525058f6f002900000000000000000000000000000000000000000000000000000000000061a844616e6765726f757320776f6d616e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b9dddb80000000000000000000000000000000000000000000000000000000000000001" + , "0x6060604052341561000f57600080fd5b6040516080806105438339810160405280805190602001909190805190602001909190805190602001909190805190602001909190505083600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505050505061044b806100f86000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007057806323b872dd1461009957806370a0823114610112578063a9059cbb1461015f575b341561006b57600080fd5b600080fd5b341561007b57600080fd5b6100836101b9565b6040518082815260200191505060405180910390f35b34156100a457600080fd5b6100f8600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c2565b604051808215151515815260200191505060405180910390f35b341561011d57600080fd5b610149600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102c5565b6040518082815260200191505060405180910390f35b341561016a57600080fd5b61019f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061030e565b604051808215151515815260200191505060405180910390f35b60008054905090565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022057600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190509392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600060035442111561031f57600080fd5b60055434108061037157506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561037b57600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050929150505600a165627a7a72305820af0e8d60e0b80d2599f4b5d2996c65865e2fc9fb93028e319a6a8ff525058f6f00290000000000000000000000000000000000000000000000000000000000004e204d6973616476656e747572657320696e20616e20616d7374657264616d20636f000000000000000000000000000000000000000000000000000000005b9dddb80000000000000000000000000000000000000000000000000000000000000000" + , "0x23b872dd000000000000000000000000dd35094c66be5822bdf2b4aae1491a5b7bfc6b76000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000dd35094c66be5822bdf2b4aae1491a5b7bfc6b760000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000005cb81c966f6a97bf6c9f868592d34f22868710080000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000278b94a77b870c3c4333119dc460caa9e69ddf830000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000041cd0acccc289eb713e0373962467e96b69967f7000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000041cd0acccc289eb713e0373962467e96b69967f70000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fb1b9b41040d16564a0101242c6ff78734e370a6000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fb1b9b41040d16564a0101242c6ff78734e370a60000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000087d0ec46e87b161411ab5b26df61846760049c370000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000535ef2a55cd79440b5b10f679404a5f2598538f80000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000076d45f3d3798808cf30461cf503ec0ba033861fb0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000030362ef7ed13d5f29ffd4931ad53c845fb4d11440000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000005657fd0af3a9efbc32cb070576f58f6c9d7d7cd0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000059691de7d4094bb2ffb71d500611180001b87b450000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000006580b7bde7205c45fcbace09eba71220a76f93850000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000056bd8aed482ec9ebce28f0616b4673a33b46f9840000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000004de70b13e2da1d393c35110a5c856a8af53127260000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000a8c19e4ba5ce3a1dabe72d2054d28f507b9005b80000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000006981ff3868fe463a827b858d3bf2dd985f6ef5600000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000b038c5e29400e184649cf176465d0c948ffa2ad7000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000b038c5e29400e184649cf176465d0c948ffa2ad70000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000b1741048d1e7d218ea49025530b68059b76396ec000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000e2ffd2e1cffc7688315912856c255889371e76590000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000b1741048d1e7d218ea49025530b68059b76396ec0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd0000000000000000000000008119bde86bb60d17e307ef38a908e4ce06b34cfc000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000008119bde86bb60d17e307ef38a908e4ce06b34cfc0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd0000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd0000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd0000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd0000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd00000000000000000000000061b205f0d383f24b8fe675d54bdd00f0f7a1526b000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000006adeb6cb70158354b09a6cc19bf3d7591eab65af0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000d9126a6cd1afab5186bc72bfaaa7a5a58440861a0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e30000000000000000000000000000000000000000000000000000000000000001" + , "0x" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000064" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000015" + , "0x18160ddd" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02000000000000000000000000fde7b48f097102e736b45296d1ac6cb8a51426eb0000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e3000000000000000000000000fe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020000000000000000000000000000000000000000000000000000000000000001" + , "0x6060604052341561000f57600080fd5b604051608080610551833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b610456806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550600190505b5b5b929150505600a165627a7a723058205b86e848a779bf6ec997f3d2783ce089388f0791003bb8714419eb3898926f2d00290000000000000000000000000000000000000000000000000000000000001388706c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005b9dddb80000000000000000000000000000000000000000000000000000000000000000" + , "0x23b872dd000000000000000000000000007bee82bdd9e866b2bd114780a47f2261c684e300000000000000000000000000000030694cff4ba44800247afc3a517c54d5ca0000000000000000000000000000000000000000000000000000000000000001" + , "0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc00290000000000000000000000000000000000000000000000000000000000001388706c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005b9dddb80000000000000000000000000000000000000000000000000000000000000000" + , "0x" + , "0x23b872dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , "0x23b872dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , "0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" + , "0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" + , "0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" + , "0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" + , "0x6060604052341561000f57600080fd5b6040516080806105a7833981016040528080519060200190919080519060200190919080519060200190919080519060200190919050505b83600081905550600054600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550826002816000191690555081915033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508090505b505050505b6104ac806100fb6000396000f30060606040523615610060576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806318160ddd1461007357806323b872dd1461009c57806370a0823114610115578063a9059cbb14610162575b341561006b57600080fd5b5b600080fd5b005b341561007e57600080fd5b6100866101bc565b6040518082815260200191505060405180910390f35b34156100a757600080fd5b6100fb600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101c6565b604051808215151515815260200191505060405180910390f35b341561012057600080fd5b61014c600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506102cc565b6040518082815260200191505060405180910390f35b341561016d57600080fd5b6101a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610316565b604051808215151515815260200191505060405180910390f35b6000805490505b90565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561022457600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600190505b5b5b9392505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600060035442111561032757600080fd5b60055434108061037957506005548201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054105b1561038357600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151561046e5781600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555060019050610478565b60009050610478565b5b5b5b929150505600a165627a7a7230582041309930ddc897b1b3467a93b970e18169a9f10b51082be4a94e865eab1db0dc0029000000000000000000000000000000000000000000000000000000000007a120506c656173696e6720746865206c6f7264730000000000000000000000000000000000000000000000000000000000000000000000000000000000005d7c916c0000000000000000000000000000000000000000000000000000000000000000" + , "0x" + , "0x6060604052341561000f57600080fd5b604051610dd1380380610dd18339810160405280805190602001909190805182019190602001805190602001909190805182019190505083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508360008190555082600390805190602001906100a79291906100e3565b5081600460006101000a81548160ff021916908360ff16021790555080600590805190602001906100d99291906100e3565b5050505050610188565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061012457805160ff1916838001178555610152565b82800160010185558215610152579182015b82811115610151578251825591602001919060010190610136565b5b50905061015f9190610163565b5090565b61018591905b80821115610181576000816000905550600101610169565b5090565b90565b610c3a806101976000396000f3006060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014257806318160ddd1461019c57806323b872dd146101c557806327e235e31461023e578063313ce5671461028b5780635c658165146102ba57806370a082311461032657806395d89b4114610373578063a9059cbb14610401578063dd62ed3e1461045b575b600080fd5b34156100bf57600080fd5b6100c76104c7565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101075780820151818401526020810190506100ec565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610182600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610565565b604051808215151515815260200191505060405180910390f35b34156101a757600080fd5b6101af610657565b6040518082815260200191505060405180910390f35b34156101d057600080fd5b610224600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061065d565b604051808215151515815260200191505060405180910390f35b341561024957600080fd5b610275600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506108f7565b6040518082815260200191505060405180910390f35b341561029657600080fd5b61029e61090f565b604051808260ff1660ff16815260200191505060405180910390f35b34156102c557600080fd5b610310600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610922565b6040518082815260200191505060405180910390f35b341561033157600080fd5b61035d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610947565b6040518082815260200191505060405180910390f35b341561037e57600080fd5b610386610990565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c65780820151818401526020810190506103ab565b50505050905090810190601f1680156103f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040c57600080fd5b610441600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a2e565b604051808215151515815260200191505060405180910390f35b341561046657600080fd5b6104b1600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b87565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561055d5780601f106105325761010080835404028352916020019161055d565b820191906000526020600020905b81548152906001019060200180831161054057829003601f168201915b505050505081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561072e5750828110155b151561073957600080fd5b82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156108865782600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b60016020528060005260406000206000915090505481565b600460009054906101000a900460ff1681565b6002602052816000526040600020602052806000526040600020600091509150505481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7e57600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a723058208867cc817b5728cc1c034e415ddc65b88add0ad41a9d9827b2ba80ba0ac9f1e6002900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000104f67757a68616e4c69666556616c75650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034f43470000000000000000000000000000000000000000000000000000000000" }; } diff --git a/app/src/test/resources/transaction-decoding-baseline.txt b/app/src/test/resources/transaction-decoding-baseline.txt new file mode 100644 index 0000000000..cbfcd6cb3b --- /dev/null +++ b/app/src/test/resources/transaction-decoding-baseline.txt @@ -0,0 +1,834 @@ +trade(5aab55ba, 1b, 3b001a70e389356e7bb9dcf89ae132771fbebb0aadc84d2da54083a9f84a52c3, 79d0ba25d819da836204269eb742e777fe27e3364220bc07bb7ebb8f3b55260a, 21, 22, 23, 24) +transfer(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, b9) +transfer(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, de0b6b3a7640000) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 1c) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, e) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, c0) +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 1, 2, 3) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x93922cdabaa26d50e7c6cb19ee3bcd03462ed334, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0xc9034ff4266b1690d2b579584e5c3259009ed13c, 0x000000000000000000000000000000000000dead, 3) +transferFrom(0xc9034ff4266b1690d2b579584e5c3259009ed13c, 0x000000000000000000000000000000000000dead, 1, 2) +transfer(0xc9034ff4266b1690d2b579584e5c3259009ed13c, d1, d2) +trade(0, 1b, f9cadbff0499fbd2afb4c25289c8fc17518bd22060526b619d4645fcc4c94c53, 57dcccf6e3e9f20533b6343e7d0e88fa37e9e23790e0ecbc57b4b85a3b421d1f, c, d) +transferFrom(0x000000000000000000000000000000000000dead, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, a, b, c, d, e) +transferFrom(0x000000000000000000000000000000000000dead, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, d) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, c) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, b) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, a) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, d6) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, bf) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, bf) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 5) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 5) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0xc9034ff4266b1690d2b579584e5c3259009ed13c, 0x000000000000000000000000000000000000dead, 0) +transfer(0xc9034ff4266b1690d2b579584e5c3259009ed13c, 1, 2, 3, 4) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, eb, ec) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, be) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, be) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, b7) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, b7) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, e7) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, c7) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, b6) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 9) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 8) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 8) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, b5) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, b4) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, b3) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 7) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 7) +transfer(0xcc5490a4b584ef7450492d45022ff017da5a35cc, 7) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 6) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 21) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, bd) +Contract Call() +trade(0, 1c, 15f77da29e4cfb5ff799df4e952958333647d0c33d815690a5f0982877e29d75, 4e78ee4110d069f3218808affd075a5bb98a475bcfcbcf48e5f55e4d402a72bd, ad, ae) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, e9, ea) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, e8) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 5) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 4) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 4) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 3) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 3) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 2) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 2) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 0) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 20) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, a6) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x99f05a668119d8938d79f85add73c9ab8ff719b1, 52, 53) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 52, 53, 54, 55, 56, 57, 58, 59, 5a, 5b, 5c, 5d, 5e, 5f, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 6a, 6b, 6c, 6d, 6e, 6f, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 7a, 7b, 7c, 7d, 7e, 7f, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 8a, 8b, 8c, 8d, 8e, 8f, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 9a, 9b, 9c, 9d, 9e, 9f, a0, a1, a2, a3) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +transfer(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 4f) +Contract Call() +trade(0, 1b, 9caf1c785074f5948310cd1aa44ce2efda0ab19c308307610d7ba2c74604ae98, 23d8d97ab44a2389043ecb3c1fb29c40ec702282db6ee1d2b2204f8954e4b451, 3, 4) +transferFrom(0x4b0b2389900d2638b684f037d6ec8efa61cf3ec9, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 49, 4a) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, a9, ab, ac) +transfer(0x4b0b2389900d2638b684f037d6ec8efa61cf3ec9, 42, 43, 44, 47, 48) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 46) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 45) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 41) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, e2) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, d5) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, e6) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 3e) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, e5) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 40) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 37, 38, 39, 3a) +trade(5a9d16ba, 1b, 607bc2ebbbc0ef7a3b1f520f5f5eea7a5a0dd3959e7013588020d2732d0cfc56, 47990dae807d0d1509186a0e4f4773d7569d906abe97829a3925350e62f6f116, 9, a, b, c, d, e, f, 10, 11, 12) +transfer(0x21acfd9f199fa91213a23193c9504f10cac2f063, 35, 36) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 1f) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 3d) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 33, 34) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, e3, e4) +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 2e, 2f, 30) +transfer(0x21acfd9f199fa91213a23193c9504f10cac2f063, 2b, 2c, 2d) +transfer(0xf8523f7cae2254d27efb50be22c118b31b790562, 25, 26, 29, 2a) +transfer(0xf8523f7cae2254d27efb50be22c118b31b790562, 25, 26, 29, 2a, 2b, 2c) +transferFrom(0xc830f48cf39419f0d01a125396ebf8dc6b61b65f, 0x000000000000000000000000000000000000dead, 0, 1) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 1e) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 1d) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 21, 22, 23, 24) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 21, 22, 24, 25) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 18) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, a) +transfer(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 31, 32) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 1c) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 1b) +trade(5a9a00e2, 1b, c59d6718734043600a49ec2419e566fa03676058e88326ff1161c579c6b8e799, 51d22461ab6f27bedd72d6b56c1fecf9f4cbb79a7728c510022617a9e42782ea, 9, a, b, c, d, e, f, 10, 11, 12) +trade(5a9a001f, 1c, 8ee5c1b644deba36a536a9ba32ca200af2914e212d725b6c2b4837bc9fdcb81f, 1658bfa9f6e7a8ea82a14efaa84bb1cf079b5ca5595f2dcd6a2adb5b89012c78, 71, 72, 73, 74, 75, 76, 77, 78, 79, 7a) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 19) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 17) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 14) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 8, 9) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 6, 7) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 4, 5) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, d, e, f) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 10, 11, 1a) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 1f, 20) +transfer(0x21acfd9f199fa91213a23193c9504f10cac2f063, 96) +transfer(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 95) +transfer(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1a, 1b) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 2, 3) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 12, 13) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, b, c) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, df) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 19) +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 15, 16) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, c6) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 18) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 17) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, dc, db) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, e0, e1) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 8, dd, de) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 6, 7) +Contract Call() +transferFrom(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 0x000000000000000000000000000000000000dead, 0, 1) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, c1, c2) +transfer(0x99f05a668119d8938d79f85add73c9ab8ff719b1, 89) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +trade(5a916f43, 1b, 16e9d2a4a45ec33193fc04d3ffc4786b5d636f7b63127a81c4b9ae87109abc02, 798aeb53b47c30ab8ac1eb6231fc2990a2f2bc21dfecc698e5cdb6de1bd0ff06, 1c, 1d, 1e) +trade(5a9002c0, 1b, 7e92d67d8443d0cf548be4ab6c29ae910b7996b248d876687d79bd5df9786cbd, 34797d008f639ce56189ad26555ee18ab16bf23b9a0cb9e3a0d60bbb4556770d, 0, 1) +trade(5a8ff7b3, 1b, 929cbfe005791c7fba07d03b27f5b7ecf712ab0744cda025d2782590b78770d4, 6e828ae6f3217ea3a0c9cd4a77a443cb3de037aa5ba7dd205b56a04aa341bbd, 1, 2) +trade(5a8ff7b3, 1b, 929cbfe005791c7fba07d03b27f5b7ecf712ab0744cda025d2782590b78770d4, 6e828ae6f3217ea3a0c9cd4a77a443cb3de037aa5ba7dd205b56a04aa341bbd, 1, 2) +Contract Call() +transfer(0x9b9d498ce067f4dc2a971f2abd533182c309bf71, 0) +transfer(0xe56c880c8e0f8869f7fcb2f7f774d923578f9f5d, 64) +Contract Call() +transfer(0xa2845ed453b15beb7aaf3f01adabf69e79270838, 13, 14, 15, 16) +transfer(0x9f75b16cfb79f0bc11dacf149e342637864d89c8, d3, d4) +transfer(0x9f75b16cfb79f0bc11dacf149e342637864d89c8, 0, 1, 5) +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, d1, d2) +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 4b) +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 4e, 4d, 4c) +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 27, 28) +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 3b, 3c, 3f) +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 2, 3, 4) +Contract Call() +endContract() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 1, 2, 3) +Contract Call() +Contract Call() +endContract() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 9, a, b) +Contract Call() +Contract Call() +Contract Call() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 1, 2) +Contract Call() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 1, 2) +Contract Call() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 1, 2) +Contract Call() +Contract Call() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 1, 2) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 1, 2) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transfer(0xd75124572589127bb6d8ab5ccc8acd215da1102a, 6, 7) +transfer(0xb05a1573146372165c65f3f8ac7340fee7fa88c4, 12, 13) +Contract Call() +Contract Call() +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, a) +transfer(0x699657da752d806a5df9f8a12e25facd1b2215ca, 0, 1, 2, 15, 17) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 10, 11) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 5, 6, 7, 8, 9, b) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 7) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 6) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 5) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 4) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 3) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 2) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 0) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, a, 4, d, 13) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 0, 1, 2, 3) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 0, 1, 2, 3, 4, 5, 6) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c) +Contract Call() +Contract Call() +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 9) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 8) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 7) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 5) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 6) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 6) +Contract Call() +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 4) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 4) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 3) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 14) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 15) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 16) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 19) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 1a) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 18) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 0, 2) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 0, 2) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 7, a, e) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, f, 2, 6, 0, b, c, 9) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, f, 2, 6, 0, b, c, 9) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 17) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x000000000000000000000000000000000000dead, 1) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 13, 11, 12) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 0, c) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 7, b) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 10) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, d, 4) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 8, 9) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, f) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 6) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 6) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 5) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 1) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 1) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, a, e) +transfer(0x52a9bff41a0abd386f8998190fc4680209053984, 2, 3) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +Contract Call() +Contract Call() +transferFrom(0xcb53390d32495163936ee451fee7089cd30be33c, 0x000000000000000000000000000000000000dead, 1) +transfer(0xcb53390d32495163936ee451fee7089cd30be33c, 2) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transfer(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 8ac7230489e80000) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x27e4e09fe9743d6497b31504bfe2ad00d9567afd, 1) +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x92b6becccfb777223afd6d4f28461ad5469435be, 1) +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xff7b12fff896f572e9e4dd31c3c2e8bcef832898, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x38ea88b8e0d500206ff14af50c04bdc28c830902, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x38ea88b8e0d500206ff14af50c04bdc28c830902, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x79888add20834984e6b5a3d0676542c69c03b674, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x38ea88b8e0d500206ff14af50c04bdc28c830902, 1) +Contract Call() +transferFrom(0x79888add20834984e6b5a3d0676542c69c03b674, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x38ea88b8e0d500206ff14af50c04bdc28c830902, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x79888add20834984e6b5a3d0676542c69c03b674, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x38ea88b8e0d500206ff14af50c04bdc28c830902, 1) +Contract Call() +transferFrom(0x79888add20834984e6b5a3d0676542c69c03b674, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x79888add20834984e6b5a3d0676542c69c03b674, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x79888add20834984e6b5a3d0676542c69c03b674, 1) +Contract Call() +transferFrom(0x79888add20834984e6b5a3d0676542c69c03b674, 0x000000000000000000000000000000000000dead, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x38ea88b8e0d500206ff14af50c04bdc28c830902, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x1a68f5e645573c182a263a6d9391729789a7d164, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x149512264d5077c092cc46472d6042e5006ae40b, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x1a68f5e645573c182a263a6d9391729789a7d164, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x72d1ff0ecd51509f251d577891d686c7885aacff, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xe9e6716d6458c334bb55cf70e19507df7bb816d9, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 1) +Contract Call() +transferFrom(0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 0x000000000000000000000000000000000000dead, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 1) +Contract Call() +transferFrom(0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transfer(0xe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a020, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x7ce4cb3e0e4463872d0fa98ebe7c822600b44ea7, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +Contract Call() +transfer(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf42956738a7c308193772298cd25dea5172b269c, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +transferFrom(0x56c35ccfd4d5c7b4c900c77f886c0e65772eff67, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x56c35ccfd4d5c7b4c900c77f886c0e65772eff67, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 2) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x52ac85518e73102c20ecf82e08df0a396e4e518a, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0x762951843c1ec71b7584185cc48ccb2eb3b47fe2, 0x5bb8d47bb262aaeabef2207d1d4af3b13fb8d8e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x762951843c1ec71b7584185cc48ccb2eb3b47fe2, 1) +transferFrom(0x5bb8d47bb262aaeabef2207d1d4af3b13fb8d8e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x5bb8d47bb262aaeabef2207d1d4af3b13fb8d8e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x5bb8d47bb262aaeabef2207d1d4af3b13fb8d8e3, 1) +transferFrom(0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 1) +transferFrom(0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x91a706cac5e3518304c120b37abedf19a119c48c, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xe66a51f8e269e6c6354bb61f0a3904b447e0057c, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x91a706cac5e3518304c120b37abedf19a119c48c, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x762951843c1ec71b7584185cc48ccb2eb3b47fe2, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x762951843c1ec71b7584185cc48ccb2eb3b47fe2, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x762951843c1ec71b7584185cc48ccb2eb3b47fe2, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x762951843c1ec71b7584185cc48ccb2eb3b47fe2, 1) +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +Contract Call() +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +Contract Call() +Contract Call() +transferFrom(0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x548c014de6a4a6511bd33dfaea0cfb0069d09baf, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xf0c41dfeda441aaeafb5b7b3174001ea7acb4aab, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfea78a32aaedb0908857ac74598c078f73adeee0, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xb1c36cac20c0127d9c24271d1d97ee4500205665, 1) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x617ded54ec054f8be89147e9def2f68a24be101d, 1) +transferFrom(0x264a2629bc956327b37657b50306d83543a51c57, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x9d6268a6a7f62b73c3a55ccddde2f2796db49775, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x2f48d567cebe41df9f2e5093fb8962b5ae951776, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xbece95c79dd839dacb162cc70fd408a5596cbf9e, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x264a2629bc956327b37657b50306d83543a51c57, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xedf94b3c304217f6e8b89cd8c6330ee027e12f36, 1) +transferFrom(0x455e83b7c3a2f264ba2fb0bc96b3cf315c8591f6, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x455e83b7c3a2f264ba2fb0bc96b3cf315c8591f6, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x455e83b7c3a2f264ba2fb0bc96b3cf315c8591f6, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x7b91f7618a158137f23b09c4e2190cc27587c257, 1) +Contract Call() +Contract Call() +transferFrom(0xdd35094c66be5822bdf2b4aae1491a5b7bfc6b76, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xdd35094c66be5822bdf2b4aae1491a5b7bfc6b76, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x5cb81c966f6a97bf6c9f868592d34f2286871008, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x278b94a77b870c3c4333119dc460caa9e69ddf83, 1) +transferFrom(0x41cd0acccc289eb713e0373962467e96b69967f7, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x41cd0acccc289eb713e0373962467e96b69967f7, 1) +transferFrom(0xfb1b9b41040d16564a0101242c6ff78734e370a6, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfb1b9b41040d16564a0101242c6ff78734e370a6, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x87d0ec46e87b161411ab5b26df61846760049c37, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x535ef2a55cd79440b5b10f679404a5f2598538f8, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x76d45f3d3798808cf30461cf503ec0ba033861fb, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x30362ef7ed13d5f29ffd4931ad53c845fb4d1144, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x05657fd0af3a9efbc32cb070576f58f6c9d7d7cd, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x59691de7d4094bb2ffb71d500611180001b87b45, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x6580b7bde7205c45fcbace09eba71220a76f9385, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x56bd8aed482ec9ebce28f0616b4673a33b46f984, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x4de70b13e2da1d393c35110a5c856a8af5312726, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xa8c19e4ba5ce3a1dabe72d2054d28f507b9005b8, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x6981ff3868fe463a827b858d3bf2dd985f6ef560, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0xb038c5e29400e184649cf176465d0c948ffa2ad7, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xb038c5e29400e184649cf176465d0c948ffa2ad7, 1) +transferFrom(0xb1741048d1e7d218ea49025530b68059b76396ec, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xe2ffd2e1cffc7688315912856c255889371e7659, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xb1741048d1e7d218ea49025530b68059b76396ec, 1) +transferFrom(0x8119bde86bb60d17e307ef38a908e4ce06b34cfc, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x8119bde86bb60d17e307ef38a908e4ce06b34cfc, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x6adeb6cb70158354b09a6cc19bf3d7591eab65af, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x6adeb6cb70158354b09a6cc19bf3d7591eab65af, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x6adeb6cb70158354b09a6cc19bf3d7591eab65af, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x6adeb6cb70158354b09a6cc19bf3d7591eab65af, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x61b205f0d383f24b8fe675d54bdd00f0f7a1526b, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x6adeb6cb70158354b09a6cc19bf3d7591eab65af, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x6adeb6cb70158354b09a6cc19bf3d7591eab65af, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xd9126a6cd1afab5186bc72bfaaa7a5a58440861a, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x007bee82bdd9e866b2bd114780a47f2261c684e3, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 64) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfde7b48f097102e736b45296d1ac6cb8a51426eb, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfde7b48f097102e736b45296d1ac6cb8a51426eb, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfde7b48f097102e736b45296d1ac6cb8a51426eb, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfde7b48f097102e736b45296d1ac6cb8a51426eb, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfde7b48f097102e736b45296d1ac6cb8a51426eb, 15) +Contract Call() +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfde7b48f097102e736b45296d1ac6cb8a51426eb, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfde7b48f097102e736b45296d1ac6cb8a51426eb, 1) +transferFrom(0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 0xfde7b48f097102e736b45296d1ac6cb8a51426eb, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0xfe6d4bc2de2d0b0e6fe47f08a28ed52f9d052a02, 1) +Contract Call() +transferFrom(0x007bee82bdd9e866b2bd114780a47f2261c684e3, 0x00000030694cff4ba44800247afc3a517c54d5ca, 1) +Contract Call() +Contract Call() +transferFrom(0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000, 0) +transferFrom(0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000, 0) +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() +Contract Call() From bd1bc80953288a28275c98ccdac21d1c9b23fa51 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 30 Aug 2022 19:46:55 +0800 Subject: [PATCH 077/183] Increase e2e test timeout period --- .github/workflows/e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 26e3a470e9..083c07df1f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,7 +7,7 @@ on: jobs: test: runs-on: self-hosted - timeout-minutes: 5 + timeout-minutes: 8 strategy: matrix: api-level: [30] From 0b918fea8d41de7de94557fce72f900f31faea30 Mon Sep 17 00:00:00 2001 From: justindg Date: Tue, 30 Aug 2022 22:56:20 -0700 Subject: [PATCH 078/183] Allow users to purchase assets via Coinbase Pay (#2781) * Allow users to buy assets with Coinbase Pay * Remove unused methods/tests * Update test * Add router test * Move Coinbase Pay App ID to keys --- .github/workflows/ci.yml | 6 +- app/build.gradle | 2 +- .../com/alphawallet/app/CoinbasePayTest.java | 39 ++++ app/src/main/AndroidManifest.xml | 4 + app/src/main/cpp/keys.c | 11 + app/src/main/java/com/alphawallet/app/C.java | 1 + .../app/di/RepositoriesModule.java | 8 + .../alphawallet/app/di/ViewModelModule.java | 6 + .../entity/coinbasepay/DestinationWallet.java | 31 +++ .../app/repository/CoinbasePayRepository.java | 56 +++++ .../repository/CoinbasePayRepositoryType.java | 9 + .../app/repository/KeyProvider.java | 1 + .../app/repository/KeyProviderJNIImpl.java | 1 + .../app/router/CoinbasePayRouter.java | 44 ++++ .../com/alphawallet/app/ui/BaseActivity.java | 1 + .../app/ui/CoinbasePayActivity.java | 101 +++++++++ .../alphawallet/app/ui/WalletFragment.java | 191 +++++++++--------- .../app/util/CoinbasePayUtils.java | 17 ++ .../app/viewmodel/CoinbasePayViewModel.java | 68 +++++++ .../app/viewmodel/WalletViewModel.java | 11 + .../app/widget/BuyEthOptionsView.java | 64 ++++++ app/src/main/res/anim/hold.xml | 5 + app/src/main/res/anim/slide_in_right.xml | 8 + app/src/main/res/anim/slide_out_right.xml | 8 + .../main/res/layout/activity_coinbase_pay.xml | 14 ++ .../res/layout/dialog_buy_eth_options.xml | 23 +++ app/src/main/res/values-es/strings.xml | 3 + app/src/main/res/values-fr/strings.xml | 3 + app/src/main/res/values-my/strings.xml | 3 + app/src/main/res/values-vi/strings.xml | 3 + app/src/main/res/values-zh/strings.xml | 3 + app/src/main/res/values/strings.xml | 3 + .../app/di/mock/KeyProviderMockImpl.java | 6 + .../KeyProviderMockNonProductionImpl.java | 6 + .../repository/CoinbasePayRepositoryTest.java | 37 ++++ .../app/router/CoinbasePayRouterTest.java | 62 ++++++ .../app/util/CoinbasePayUtilsTest.java | 23 +++ .../app/widget/BuyEthOptionsViewTest.java | 48 +++++ 38 files changed, 834 insertions(+), 96 deletions(-) create mode 100644 app/src/androidTest/java/com/alphawallet/app/CoinbasePayTest.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/coinbasepay/DestinationWallet.java create mode 100644 app/src/main/java/com/alphawallet/app/repository/CoinbasePayRepository.java create mode 100644 app/src/main/java/com/alphawallet/app/repository/CoinbasePayRepositoryType.java create mode 100644 app/src/main/java/com/alphawallet/app/router/CoinbasePayRouter.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/CoinbasePayActivity.java create mode 100644 app/src/main/java/com/alphawallet/app/util/CoinbasePayUtils.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/CoinbasePayViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/widget/BuyEthOptionsView.java create mode 100644 app/src/main/res/anim/hold.xml create mode 100644 app/src/main/res/anim/slide_in_right.xml create mode 100644 app/src/main/res/anim/slide_out_right.xml create mode 100644 app/src/main/res/layout/activity_coinbase_pay.xml create mode 100644 app/src/main/res/layout/dialog_buy_eth_options.xml create mode 100644 app/src/test/java/com/alphawallet/app/repository/CoinbasePayRepositoryTest.java create mode 100644 app/src/test/java/com/alphawallet/app/router/CoinbasePayRouterTest.java create mode 100644 app/src/test/java/com/alphawallet/app/util/CoinbasePayUtilsTest.java create mode 100644 app/src/test/java/com/alphawallet/app/widget/BuyEthOptionsViewTest.java diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8818269b9e..0aab75e294 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,16 +6,16 @@ on: pull_request: jobs: test: - runs-on: macos-latest + runs-on: self-hosted steps: - uses: actions/checkout@v3 - + - name: Set up JDK uses: actions/setup-java@v3 with: distribution: zulu java-version: 11 - cache: gradle + architecture: arm64 - name: Run unit tests run: sh ./build.sh diff --git a/app/build.gradle b/app/build.gradle index 684101d823..8ac165b989 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -289,7 +289,7 @@ dependencies { testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9' // Component tests - testImplementation 'org.robolectric:robolectric:4.8.1' + testImplementation 'org.robolectric:robolectric:4.8.2' testImplementation 'androidx.test:core:1.4.0' testImplementation 'androidx.test.ext:junit:1.1.3' diff --git a/app/src/androidTest/java/com/alphawallet/app/CoinbasePayTest.java b/app/src/androidTest/java/com/alphawallet/app/CoinbasePayTest.java new file mode 100644 index 0000000000..d992831fab --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/CoinbasePayTest.java @@ -0,0 +1,39 @@ +package com.alphawallet.app; + +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.alphawallet.app.assertions.Should.shouldSee; +import static com.alphawallet.app.steps.Steps.addNewNetwork; +import static com.alphawallet.app.steps.Steps.assertBalanceIs; +import static com.alphawallet.app.steps.Steps.createNewWallet; +import static com.alphawallet.app.steps.Steps.ensureTransactionConfirmed; +import static com.alphawallet.app.steps.Steps.getWalletAddress; +import static com.alphawallet.app.steps.Steps.gotoSettingsPage; +import static com.alphawallet.app.steps.Steps.importWalletFromSettingsPage; +import static com.alphawallet.app.steps.Steps.selectTestNet; +import static com.alphawallet.app.steps.Steps.sendBalanceTo; +import static com.alphawallet.app.steps.Steps.switchToWallet; +import static com.alphawallet.app.steps.Steps.toggleSwitch; +import static com.alphawallet.app.util.Helper.click; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; + +import android.os.Build; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class CoinbasePayTest extends BaseE2ETest { + @Test + public void should_see_coinbase_pay_window() + { + createNewWallet(); + click(withText("Buy ETH")); + shouldSee("Buy with Coinbase Pay"); + click(withId(R.id.buy_with_coinbase_pay)); + shouldSee("Buy with Coinbase Pay"); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 953d3be20a..d3bdc3f18a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -311,6 +311,10 @@ android:name=".ui.NodeStatusActivity" android:label="@string/action_node_status" /> + + diff --git a/app/src/main/cpp/keys.c b/app/src/main/cpp/keys.c index 147dc8a361..739761e4aa 100644 --- a/app/src/main/cpp/keys.c +++ b/app/src/main/cpp/keys.c @@ -68,6 +68,17 @@ Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getRampKey( JNIEnv* env, #endif } +JNIEXPORT jstring JNICALL +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getCoinbasePayAppId( JNIEnv* env, jobject thiz ) +{ +#if (HAS_KEYS == 1) + return getDecryptedKey(env, coinbasePayAppId); +#else + const jstring key = ""; // <-- replace with your Coinbase Pay app id + return (*env)->NewStringUTF(env, key); +#endif +} + JNIEXPORT jstring JNICALL Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getSecondaryInfuraKey( JNIEnv* env, jobject thiz ) { diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index affa0f39ed..456c00069d 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -299,6 +299,7 @@ public enum TokenStatus { public static final String AN_USE_GAS = "Gas Settings"; public static final String AN_CALL_ACTIONSHEET = "Use ActionSheet"; public static final String AN_USE_ONRAMP = "Use OnRamp"; + public static final String AN_USE_COINBASE_PAY = "Use Coinbase Pay"; public static final String APP_NAME = "PACKAGE_NAME"; public static final String ALPHAWALLET_LOGO_URI = "https://alphawallet.com/wp-content/themes/alphawallet/img/alphawallet-logo.svg"; diff --git a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java index 58edfca635..127d9e6be5 100644 --- a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java +++ b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java @@ -4,6 +4,8 @@ import android.content.Context; +import com.alphawallet.app.repository.CoinbasePayRepository; +import com.alphawallet.app.repository.CoinbasePayRepositoryType; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; import com.alphawallet.app.repository.OnRampRepository; @@ -115,6 +117,12 @@ OnRampRepositoryType provideOnRampRepository(@ApplicationContext Context context return new OnRampRepository(context, analyticsServiceType); } + @Singleton + @Provides + CoinbasePayRepositoryType provideCoinbasePayRepository() { + return new CoinbasePayRepository(); + } + @Singleton @Provides TransactionLocalSource provideTransactionInDiskCache(RealmManager realmManager) { diff --git a/app/src/main/java/com/alphawallet/app/di/ViewModelModule.java b/app/src/main/java/com/alphawallet/app/di/ViewModelModule.java index df5275c8c8..7e846157d2 100644 --- a/app/src/main/java/com/alphawallet/app/di/ViewModelModule.java +++ b/app/src/main/java/com/alphawallet/app/di/ViewModelModule.java @@ -22,6 +22,7 @@ import com.alphawallet.app.repository.TokenRepositoryType; import com.alphawallet.app.repository.TransactionRepositoryType; import com.alphawallet.app.repository.WalletRepositoryType; +import com.alphawallet.app.router.CoinbasePayRouter; import com.alphawallet.app.router.ExternalBrowserRouter; import com.alphawallet.app.router.HomeRouter; import com.alphawallet.app.router.ImportTokenRouter; @@ -98,6 +99,11 @@ MyAddressRouter provideMyAddressRouter() { return new MyAddressRouter(); } + @Provides + CoinbasePayRouter provideCoinbasePayRouter() { + return new CoinbasePayRouter(); + } + @Provides FetchTokensInteract provideFetchTokensInteract(TokenRepositoryType tokenRepository) { return new FetchTokensInteract(tokenRepository); diff --git a/app/src/main/java/com/alphawallet/app/entity/coinbasepay/DestinationWallet.java b/app/src/main/java/com/alphawallet/app/entity/coinbasepay/DestinationWallet.java new file mode 100644 index 0000000000..44ef08699c --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/coinbasepay/DestinationWallet.java @@ -0,0 +1,31 @@ +package com.alphawallet.app.entity.coinbasepay; + +import java.util.List; + +public class DestinationWallet +{ + final transient Type type; + String address; + List blockchains; + List assets; + + public DestinationWallet(Type type, String address, List list) + { + this.type = type; + this.address = address; + if (type.equals(Type.ASSETS)) + { + this.assets = list; + } + else + { + this.blockchains = list; + } + } + + public enum Type + { + ASSETS, + BLOCKCHAINS + } +} diff --git a/app/src/main/java/com/alphawallet/app/repository/CoinbasePayRepository.java b/app/src/main/java/com/alphawallet/app/repository/CoinbasePayRepository.java new file mode 100644 index 0000000000..a1bf99cf23 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/repository/CoinbasePayRepository.java @@ -0,0 +1,56 @@ +package com.alphawallet.app.repository; + +import android.net.Uri; +import android.text.TextUtils; + +import com.alphawallet.app.entity.coinbasepay.DestinationWallet; +import com.alphawallet.app.util.CoinbasePayUtils; + +import java.util.List; + +public class CoinbasePayRepository implements CoinbasePayRepositoryType +{ + private static final String SCHEME = "https"; + private static final String AUTHORITY = "pay.coinbase.com"; + private static final String BUY_PATH = "buy"; + private static final String SELECT_ASSET_PATH = "select-asset"; + private final KeyProvider keyProvider = KeyProviderFactory.get(); + + @Override + public String getUri(DestinationWallet.Type type, String address, List list) + { + String appId = keyProvider.getCoinbasePayAppId(); + if (TextUtils.isEmpty(appId)) + { + return ""; + } + else + { + Uri.Builder builder = new Uri.Builder(); + builder.scheme(SCHEME) + .authority(AUTHORITY) + .appendPath(BUY_PATH) + .appendPath(SELECT_ASSET_PATH) + .appendQueryParameter(RequestParams.APP_ID, keyProvider.getCoinbasePayAppId()) + .appendQueryParameter(RequestParams.DESTINATION_WALLETS, CoinbasePayUtils.getDestWalletJson(type, address, list)); + + return builder.build().toString(); + } + } + + public static class Blockchains + { + public static final String ETHEREUM = "ethereum"; + public static final String SOLANA = "solana"; + public static final String AVALANCHE_C_CHAIN = "avalanche-c-chain"; + } + + private static class RequestParams + { + public static final String APP_ID = "appId"; + public static final String ADDRESS = "address"; + public static final String DESTINATION_WALLETS = "destinationWallets"; + public static final String ASSETS = "assets"; + public static final String BLOCKCHAINS = "blockchains"; + } +} diff --git a/app/src/main/java/com/alphawallet/app/repository/CoinbasePayRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/CoinbasePayRepositoryType.java new file mode 100644 index 0000000000..f0b8136e13 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/repository/CoinbasePayRepositoryType.java @@ -0,0 +1,9 @@ +package com.alphawallet.app.repository; + +import com.alphawallet.app.entity.coinbasepay.DestinationWallet; + +import java.util.List; + +public interface CoinbasePayRepositoryType { + String getUri(DestinationWallet.Type type, String json, List list); +} diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java index ea4635814c..848353be7f 100644 --- a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java @@ -14,4 +14,5 @@ public interface KeyProvider String getRampKey(); String getOpenSeaKey(); String getMailchimpKey(); + String getCoinbasePayAppId(); } diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java index 908d293530..48f65d7170 100644 --- a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java @@ -19,4 +19,5 @@ public KeyProviderJNIImpl() public native String getRampKey(); public native String getOpenSeaKey(); public native String getMailchimpKey(); + public native String getCoinbasePayAppId(); } diff --git a/app/src/main/java/com/alphawallet/app/router/CoinbasePayRouter.java b/app/src/main/java/com/alphawallet/app/router/CoinbasePayRouter.java new file mode 100644 index 0000000000..ad98deae04 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/router/CoinbasePayRouter.java @@ -0,0 +1,44 @@ +package com.alphawallet.app.router; + +import android.app.Activity; +import android.content.Intent; + +import com.alphawallet.app.R; +import com.alphawallet.app.ui.CoinbasePayActivity; + +public class CoinbasePayRouter +{ + /** + * @param activity - Calling activity + * @param tokenSymbol - Token symbol of the asset you wish to purchase, e.g. "ETH", "USDC" + */ + public void buyAsset(Activity activity, String tokenSymbol) + { + Intent intent = new Intent(activity, CoinbasePayActivity.class); + intent.putExtra("asset", tokenSymbol); + intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activity.startActivity(intent); + activity.overridePendingTransition(R.anim.slide_in_right, R.anim.hold); + } + + /** + * @param activity - Calling activity + * @param blockchain - Select from supported chains from `CoinbasePayRepository.Blockchains` + */ + public void buyFromSelectedChain(Activity activity, String blockchain) + { + Intent intent = new Intent(activity, CoinbasePayActivity.class); + intent.putExtra("blockchain", blockchain); + intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activity.startActivity(intent); + activity.overridePendingTransition(R.anim.slide_in_right, R.anim.hold); + } + + public void open(Activity activity) + { + Intent intent = new Intent(activity, CoinbasePayActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activity.startActivity(intent); + activity.overridePendingTransition(R.anim.slide_in_right, R.anim.hold); + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java b/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java index 20030baeba..1b4ed26388 100644 --- a/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java @@ -91,6 +91,7 @@ protected void showToolbar() { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: + onBackPressed(); finish(); break; } diff --git a/app/src/main/java/com/alphawallet/app/ui/CoinbasePayActivity.java b/app/src/main/java/com/alphawallet/app/ui/CoinbasePayActivity.java new file mode 100644 index 0000000000..1a21889fe4 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/CoinbasePayActivity.java @@ -0,0 +1,101 @@ +package com.alphawallet.app.ui; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.text.TextUtils; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.Toast; + +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.coinbasepay.DestinationWallet; +import com.alphawallet.app.viewmodel.CoinbasePayViewModel; + +import java.util.ArrayList; +import java.util.List; + +import dagger.hilt.android.AndroidEntryPoint; + +@AndroidEntryPoint +public class CoinbasePayActivity extends BaseActivity +{ + private CoinbasePayViewModel viewModel; + private WebView webView; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_coinbase_pay); + + toolbar(); + + setTitle(getString(R.string.title_buy_with_coinbase_pay)); + + initViewModel(); + + initWebView(); + + viewModel.prepare(); + } + + @SuppressLint("SetJavaScriptEnabled") + private void initWebView() + { + webView = findViewById(R.id.web_view); + webView.setWebViewClient(new WebViewClient()); + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); + webView.getSettings().setAppCacheEnabled(false); + webView.clearCache(true); + webView.clearHistory(); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this).get(CoinbasePayViewModel.class); + viewModel.defaultWallet().observe(this, this::onDefaultWallet); + } + + private void onDefaultWallet(Wallet wallet) + { + DestinationWallet.Type type; + List list = new ArrayList<>(); + String asset = getIntent().getStringExtra("asset"); + if (!TextUtils.isEmpty(asset)) + { + type = DestinationWallet.Type.ASSETS; + list.add(asset); + } + else + { + type = DestinationWallet.Type.BLOCKCHAINS; + String blockchain = getIntent().getStringExtra("blockchain"); + list.add(blockchain); + } + + String uri = viewModel.getUri(type, wallet.address, list); + if (TextUtils.isEmpty(uri)) + { + Toast.makeText(this, "Missing Coinbase Pay App ID.", Toast.LENGTH_LONG).show(); + finish(); + } + else + { + webView.loadUrl(uri); + } + } + + @Override + public void onBackPressed() + { + webView.clearCache(true); + super.onBackPressed(); + overridePendingTransition(R.anim.hold, R.anim.slide_out_right); + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java index ba7b772e39..44faff12c1 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java @@ -52,6 +52,7 @@ import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; import com.alphawallet.app.interact.GenericWalletInteract; +import com.alphawallet.app.repository.CoinbasePayRepository; import com.alphawallet.app.repository.TokensRealmSource; import com.alphawallet.app.repository.entity.RealmToken; import com.alphawallet.app.service.TickerService; @@ -65,11 +66,13 @@ import com.alphawallet.app.ui.widget.holder.WarningHolder; import com.alphawallet.app.util.LocaleUtils; import com.alphawallet.app.viewmodel.WalletViewModel; +import com.alphawallet.app.widget.BuyEthOptionsView; import com.alphawallet.app.widget.LargeTitleView; import com.alphawallet.app.widget.NotificationView; import com.alphawallet.app.widget.ProgressView; import com.alphawallet.app.widget.SystemView; import com.alphawallet.app.widget.UserAvatar; +import com.google.android.material.bottomsheet.BottomSheetDialog; import com.google.android.material.snackbar.Snackbar; import com.google.android.material.tabs.TabLayout; @@ -96,17 +99,40 @@ public class WalletFragment extends BaseFragment implements AvatarWriteCallback, ServiceSyncCallback { - private static final String TAG = "WFRAG"; - public static final String SEARCH_FRAGMENT = "w_search"; - + private static final String TAG = "WFRAG"; + final ActivityResultLauncher tokenManagementLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + if (result.getData() == null) return; + ArrayList tokenData = result.getData().getParcelableArrayListExtra(ADDED_TOKEN); + Bundle b = new Bundle(); + b.putParcelableArrayList(C.ADDED_TOKEN, tokenData); + getParentFragmentManager().setFragmentResult(C.ADDED_TOKEN, b); + }); + private final Handler handler = new Handler(Looper.getMainLooper()); private WalletViewModel viewModel; - private SystemView systemView; private TokensAdapter adapter; + ActivityResultLauncher handleBackupClick = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + String keyBackup = null; + boolean noLockScreen = false; + Intent data = result.getData(); + if (data != null) keyBackup = data.getStringExtra("Key"); + if (data != null) noLockScreen = data.getBooleanExtra("nolock", false); + if (result.getResultCode() == RESULT_OK) + { + ((HomeActivity) getActivity()).backupWalletSuccess(keyBackup); + } + else + { + ((HomeActivity) getActivity()).backupWalletFail(keyBackup, noLockScreen); + } + }); private UserAvatar addressAvatar; private View selectedToken; - private final Handler handler = new Handler(Looper.getMainLooper()); private String importFileName; private RecyclerView recyclerView; private SwipeRefreshLayout refreshLayout; @@ -116,7 +142,6 @@ public class WalletFragment extends BaseFragment implements private RealmResults realmUpdates; private LargeTitleView largeTitleView; private long realmUpdateTime; - private ActivityResultLauncher networkSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { @@ -494,8 +519,18 @@ public void reloadTokens() @Override public void onBuyToken() { - Intent intent = viewModel.getBuyIntent(getCurrentWallet().address); - ((HomeActivity) getActivity()).onActivityResult(C.TOKEN_SEND_ACTIVITY, RESULT_OK, intent); + BottomSheetDialog buyEthDialog = new BottomSheetDialog(getActivity()); + BuyEthOptionsView buyEthOptionsView = new BuyEthOptionsView(getActivity()); + buyEthOptionsView.setOnBuyWithRampListener(v -> { + Intent intent = viewModel.getBuyIntent(getCurrentWallet().address); + ((HomeActivity) getActivity()).onActivityResult(C.TOKEN_SEND_ACTIVITY, RESULT_OK, intent); + buyEthDialog.dismiss(); + }); + buyEthOptionsView.setOnBuyWithCoinbasePayListener(v -> { + viewModel.showBuyEthOptions(getActivity()); + }); + buyEthDialog.setContentView(buyEthOptionsView); + buyEthDialog.show(); } @Override @@ -662,24 +697,6 @@ public void run() selectedToken = null; } - ActivityResultLauncher handleBackupClick = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - String keyBackup = null; - boolean noLockScreen = false; - Intent data = result.getData(); - if (data != null) keyBackup = data.getStringExtra("Key"); - if (data != null) noLockScreen = data.getBooleanExtra("nolock", false); - if (result.getResultCode() == RESULT_OK) - { - ((HomeActivity) getActivity()).backupWalletSuccess(keyBackup); - } - else - { - ((HomeActivity) getActivity()).backupWalletFail(keyBackup, noLockScreen); - } - }); - @Override public void backUpClick(Wallet wallet) { @@ -710,16 +727,6 @@ public void remindMeLater(Wallet wallet) }); } - final ActivityResultLauncher tokenManagementLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - if (result.getData() == null) return; - ArrayList tokenData = result.getData().getParcelableArrayListExtra(ADDED_TOKEN); - Bundle b = new Bundle(); - b.putParcelableArrayList(C.ADDED_TOKEN, tokenData); - getParentFragmentManager().setFragmentResult(C.ADDED_TOKEN, b); - }); - public void storeWalletBackupTime(String backedUpKey) { handler.post(() -> @@ -741,6 +748,62 @@ public void avatarFound(Wallet wallet) viewModel.saveAvatar(wallet); } + public Wallet getCurrentWallet() + { + return viewModel.getWallet(); + } + + @Override + public boolean onMenuItemClick(MenuItem menuItem) + { + if (menuItem.getItemId() == R.id.action_my_wallet) + { + viewModel.showMyAddress(getContext()); + } + if (menuItem.getItemId() == R.id.action_scan) + { + viewModel.showQRCodeScanning(getActivity()); + } + return super.onMenuItemClick(menuItem); + } + + private void initNotificationView(View view) + { + NotificationView notificationView = view.findViewById(R.id.notification); + boolean hasShownWarning = viewModel.isMarshMallowWarningShown(); + + if (!hasShownWarning && android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) + { + notificationView.setTitle(getContext().getString(R.string.title_version_support_warning)); + notificationView.setMessage(getContext().getString(R.string.message_version_support_warning)); + notificationView.setPrimaryButtonText(getContext().getString(R.string.hide_notification)); + notificationView.setPrimaryButtonListener(() -> + { + notificationView.setVisibility(View.GONE); + viewModel.setMarshMallowWarning(true); + }); + } + else + { + notificationView.setVisibility(View.GONE); + } + } + + @Override + public void onSearchClicked() + { + Intent intent = new Intent(getActivity(), SearchActivity.class); + startActivity(intent); + } + + @Override + public void onSwitchClicked() + { + Intent intent = new Intent(getActivity(), SelectNetworkFilterActivity.class); + intent.putExtra(C.EXTRA_SINGLE_ITEM, false); + networkSettingsHandler.launch(intent); + } + public class SwipeCallback extends ItemTouchHelper.SimpleCallback { private final TokensAdapter mAdapter; @@ -849,60 +912,4 @@ else if (dX < 0) icon.draw(c); } } - - public Wallet getCurrentWallet() - { - return viewModel.getWallet(); - } - - @Override - public boolean onMenuItemClick(MenuItem menuItem) - { - if (menuItem.getItemId() == R.id.action_my_wallet) - { - viewModel.showMyAddress(getContext()); - } - if (menuItem.getItemId() == R.id.action_scan) - { - viewModel.showQRCodeScanning(getActivity()); - } - return super.onMenuItemClick(menuItem); - } - - private void initNotificationView(View view) - { - NotificationView notificationView = view.findViewById(R.id.notification); - boolean hasShownWarning = viewModel.isMarshMallowWarningShown(); - - if (!hasShownWarning && android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) - { - notificationView.setTitle(getContext().getString(R.string.title_version_support_warning)); - notificationView.setMessage(getContext().getString(R.string.message_version_support_warning)); - notificationView.setPrimaryButtonText(getContext().getString(R.string.hide_notification)); - notificationView.setPrimaryButtonListener(() -> - { - notificationView.setVisibility(View.GONE); - viewModel.setMarshMallowWarning(true); - }); - } - else - { - notificationView.setVisibility(View.GONE); - } - } - - @Override - public void onSearchClicked() - { - Intent intent = new Intent(getActivity(), SearchActivity.class); - startActivity(intent); - } - - @Override - public void onSwitchClicked() - { - Intent intent = new Intent(getActivity(), SelectNetworkFilterActivity.class); - intent.putExtra(C.EXTRA_SINGLE_ITEM, false); - networkSettingsHandler.launch(intent); - } } diff --git a/app/src/main/java/com/alphawallet/app/util/CoinbasePayUtils.java b/app/src/main/java/com/alphawallet/app/util/CoinbasePayUtils.java new file mode 100644 index 0000000000..a8aff83f98 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/CoinbasePayUtils.java @@ -0,0 +1,17 @@ +package com.alphawallet.app.util; + +import com.alphawallet.app.entity.coinbasepay.DestinationWallet; +import com.google.gson.Gson; + +import java.util.ArrayList; +import java.util.List; + +public class CoinbasePayUtils +{ + public static String getDestWalletJson(DestinationWallet.Type type, String address, List value) + { + List destinationWallets = new ArrayList<>(); + destinationWallets.add(new DestinationWallet(type, address, value)); + return new Gson().toJson(destinationWallets); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/CoinbasePayViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/CoinbasePayViewModel.java new file mode 100644 index 0000000000..2094d749c9 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/CoinbasePayViewModel.java @@ -0,0 +1,68 @@ +package com.alphawallet.app.viewmodel; + + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import com.alphawallet.app.C; +import com.alphawallet.app.entity.AnalyticsProperties; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.coinbasepay.DestinationWallet; +import com.alphawallet.app.interact.GenericWalletInteract; +import com.alphawallet.app.repository.CoinbasePayRepositoryType; +import com.alphawallet.app.service.AnalyticsServiceType; + +import java.util.List; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; +import io.reactivex.disposables.Disposable; + +@HiltViewModel +public class CoinbasePayViewModel extends BaseViewModel +{ + private final GenericWalletInteract genericWalletInteract; + private final CoinbasePayRepositoryType coinbasePayRepository; + private final AnalyticsServiceType analyticsService; + private final MutableLiveData defaultWallet = new MutableLiveData<>(); + private final MutableLiveData signature = new MutableLiveData<>(); + + protected Disposable disposable; + + @Inject + public CoinbasePayViewModel(GenericWalletInteract genericWalletInteract, + CoinbasePayRepositoryType coinbasePayRepository, + AnalyticsServiceType analyticsService) + { + this.genericWalletInteract = genericWalletInteract; + this.coinbasePayRepository = coinbasePayRepository; + this.analyticsService = analyticsService; + } + + public LiveData defaultWallet() + { + return defaultWallet; + } + + public void prepare() + { + progress.postValue(false); + disposable = genericWalletInteract + .find() + .subscribe(this::onDefaultWallet, this::onError); + } + + private void onDefaultWallet(final Wallet wallet) + { + defaultWallet.setValue(wallet); + } + + public String getUri(DestinationWallet.Type type, String address, List list) + { + AnalyticsProperties analyticsProperties = new AnalyticsProperties(); + analyticsProperties.setData(type.toString() + ": " + list.get(0)); + analyticsService.track(C.AN_USE_COINBASE_PAY, analyticsProperties); + return coinbasePayRepository.getUri(type, address, list); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java index 315518adfe..cfd0aba601 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java @@ -28,9 +28,11 @@ import com.alphawallet.app.interact.ChangeTokenEnableInteract; import com.alphawallet.app.interact.FetchTokensInteract; import com.alphawallet.app.interact.GenericWalletInteract; +import com.alphawallet.app.repository.CoinbasePayRepository; import com.alphawallet.app.repository.OnRampRepositoryType; import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.repository.WalletItem; +import com.alphawallet.app.router.CoinbasePayRouter; import com.alphawallet.app.router.ManageWalletsRouter; import com.alphawallet.app.router.MyAddressRouter; import com.alphawallet.app.router.TokenDetailRouter; @@ -48,6 +50,7 @@ import org.web3j.crypto.Keys; import java.math.BigDecimal; +import java.util.ArrayList; import javax.inject.Inject; @@ -75,6 +78,7 @@ public class WalletViewModel extends BaseViewModel private final ChangeTokenEnableInteract changeTokenEnableInteract; private final PreferenceRepositoryType preferenceRepository; private final MyAddressRouter myAddressRouter; + private final CoinbasePayRouter coinbasePayRouter; private final ManageWalletsRouter manageWalletsRouter; private final RealmManager realmManager; private long lastBackupCheck = 0; @@ -90,6 +94,7 @@ public class WalletViewModel extends BaseViewModel TokensService tokensService, ChangeTokenEnableInteract changeTokenEnableInteract, MyAddressRouter myAddressRouter, + CoinbasePayRouter coinbasePayRouter, ManageWalletsRouter manageWalletsRouter, PreferenceRepositoryType preferenceRepository, RealmManager realmManager, @@ -102,6 +107,7 @@ public class WalletViewModel extends BaseViewModel this.tokensService = tokensService; this.changeTokenEnableInteract = changeTokenEnableInteract; this.myAddressRouter = myAddressRouter; + this.coinbasePayRouter = coinbasePayRouter; this.manageWalletsRouter = manageWalletsRouter; this.preferenceRepository = preferenceRepository; this.realmManager = realmManager; @@ -215,6 +221,11 @@ public void setTokenEnabled(Token token, boolean enabled) { token.tokenInfo.isEnabled = enabled; } + public void showBuyEthOptions(Activity activity) + { + coinbasePayRouter.buyFromSelectedChain(activity, CoinbasePayRepository.Blockchains.ETHEREUM); + } + public void showMyAddress(Context context) { // show bottomsheet dialog diff --git a/app/src/main/java/com/alphawallet/app/widget/BuyEthOptionsView.java b/app/src/main/java/com/alphawallet/app/widget/BuyEthOptionsView.java new file mode 100644 index 0000000000..502496bcec --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/widget/BuyEthOptionsView.java @@ -0,0 +1,64 @@ +package com.alphawallet.app.widget; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.annotation.LayoutRes; + +import com.alphawallet.app.R; + + +public class BuyEthOptionsView extends FrameLayout implements View.OnClickListener +{ + private OnClickListener onBuyWithCoinbasePayListener; + private OnClickListener onBuyWithRampListener; + + public BuyEthOptionsView(Context context) + { + this(context, R.layout.dialog_buy_eth_options); + } + + public BuyEthOptionsView(Context context, @LayoutRes int layoutId) + { + super(context); + init(layoutId); + } + + private void init(@LayoutRes int layoutId) + { + LayoutInflater.from(getContext()).inflate(layoutId, this, true); + findViewById(R.id.buy_with_coinbase_pay).setOnClickListener(this); + findViewById(R.id.buy_with_ramp).setOnClickListener(this); + } + + @Override + public void onClick(View view) + { + if (view.getId() == R.id.buy_with_coinbase_pay) + { + if (onBuyWithCoinbasePayListener != null) + { + onBuyWithCoinbasePayListener.onClick(view); + } + } + else if (view.getId() == R.id.buy_with_ramp) + { + if (onBuyWithRampListener != null) + { + onBuyWithRampListener.onClick(view); + } + } + } + + public void setOnBuyWithCoinbasePayListener(OnClickListener onClickListener) + { + this.onBuyWithCoinbasePayListener = onClickListener; + } + + public void setOnBuyWithRampListener(OnClickListener onClickListener) + { + this.onBuyWithRampListener = onClickListener; + } +} diff --git a/app/src/main/res/anim/hold.xml b/app/src/main/res/anim/hold.xml new file mode 100644 index 0000000000..3df8c1db32 --- /dev/null +++ b/app/src/main/res/anim/hold.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml new file mode 100644 index 0000000000..e5a91703ea --- /dev/null +++ b/app/src/main/res/anim/slide_in_right.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_right.xml b/app/src/main/res/anim/slide_out_right.xml new file mode 100644 index 0000000000..c0f406cb01 --- /dev/null +++ b/app/src/main/res/anim/slide_out_right.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_coinbase_pay.xml b/app/src/main/res/layout/activity_coinbase_pay.xml new file mode 100644 index 0000000000..f87d7f0655 --- /dev/null +++ b/app/src/main/res/layout/activity_coinbase_pay.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_buy_eth_options.xml b/app/src/main/res/layout/dialog_buy_eth_options.xml new file mode 100644 index 0000000000..5e084d46f1 --- /dev/null +++ b/app/src/main/res/layout/dialog_buy_eth_options.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 0327fa5267..5e5e9aeff2 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -932,6 +932,9 @@ Provider Delete Empty Delete All + Buy with Coinbase Pay + Buy with Ramp + Buy with Coinbase Pay Key Status Fix Key State Run Key Diagnostic diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 4210ddc32c..4a6dfe9af4 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -949,6 +949,9 @@ Provider Delete Empty Delete All + Buy with Coinbase Pay + Buy with Ramp + Buy with Coinbase Pay Key Status Fix Key State Run Key Diagnostic diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 40a1fd8dfc..34a3209552 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -974,6 +974,9 @@ Provider Delete Empty Delete All + Buy with Coinbase Pay + Buy with Ramp + Buy with Coinbase Pay Key Status Fix Key State Run Key Diagnostic diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index c6b78246a2..98cf6ce996 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -951,6 +951,9 @@ Provider Delete Empty Delete All + Buy with Coinbase Pay + Buy with Ramp + Buy with Coinbase Pay Key Status Fix Key State Run Key Diagnostic diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 5199c6dec6..3db506a0a9 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -932,6 +932,9 @@ Provider Delete Empty Delete All + Buy with Coinbase Pay + Buy with Ramp + Buy with Coinbase Pay Key Status Fix Key State Run Key Diagnostic diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 452ad3de51..a9dda3d53b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -973,6 +973,9 @@ Provider Delete Empty Delete All + Buy with Coinbase Pay + Buy with Ramp + Buy with Coinbase Pay Key Status Fix Key State Run Key Diagnostic diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java index 1c29aadac8..82e0ba8e57 100644 --- a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java @@ -77,4 +77,10 @@ public String getMailchimpKey() { return FAKE_KEY_FOR_TESTING; } + + @Override + public String getCoinbasePayAppId() + { + return FAKE_KEY_FOR_TESTING; + } } diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java index a8c55b4a1c..34fb5eddce 100644 --- a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java @@ -76,4 +76,10 @@ public String getMailchimpKey() { return null; } + + @Override + public String getCoinbasePayAppId() + { + return null; + } } diff --git a/app/src/test/java/com/alphawallet/app/repository/CoinbasePayRepositoryTest.java b/app/src/test/java/com/alphawallet/app/repository/CoinbasePayRepositoryTest.java new file mode 100644 index 0000000000..e84159e15b --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/repository/CoinbasePayRepositoryTest.java @@ -0,0 +1,37 @@ +package com.alphawallet.app.repository; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.app.entity.coinbasepay.DestinationWallet; +import com.alphawallet.shadows.ShadowApp; +import com.alphawallet.shadows.ShadowKeyProviderFactory; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.Collections; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowApp.class, ShadowKeyProviderFactory.class}) +public class CoinbasePayRepositoryTest +{ + @Test + public void uri_should_match() throws UnsupportedEncodingException + { + String appId = KeyProviderFactory.get().getCoinbasePayAppId(); + CoinbasePayRepository repository = new CoinbasePayRepository(); + String actualUri = repository.getUri(DestinationWallet.Type.ASSETS, "0x1234", Collections.singletonList("ETH")); + String expectedEncodedUri = "https://pay.coinbase.com/buy/select-asset?appId=" + appId + "&destinationWallets=%5B%7B%22address%22%3A%220x1234%22%2C%22assets%22%3A%5B%22ETH%22%5D%7D%5D"; + assertThat(actualUri, equalTo(expectedEncodedUri)); + + String decodedUri = URLDecoder.decode(actualUri, "UTF-8"); + String expectedDecodedUri = "https://pay.coinbase.com/buy/select-asset?appId=" + appId + "&destinationWallets=[{\"address\":\"0x1234\",\"assets\":[\"ETH\"]}]"; + assertThat(decodedUri, equalTo(expectedDecodedUri)); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/router/CoinbasePayRouterTest.java b/app/src/test/java/com/alphawallet/app/router/CoinbasePayRouterTest.java new file mode 100644 index 0000000000..38235a88a7 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/router/CoinbasePayRouterTest.java @@ -0,0 +1,62 @@ +package com.alphawallet.app.router; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.robolectric.Shadows.shadowOf; + +import android.content.Intent; + +import androidx.test.core.app.ActivityScenario; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.app.ui.CoinbasePayActivity; +import com.alphawallet.app.ui.SendActivity; +import com.alphawallet.app.ui.SplashActivity; +import com.alphawallet.shadows.ShadowApp; +import com.alphawallet.shadows.ShadowKeyProviderFactory; +import com.alphawallet.shadows.ShadowKeyService; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.android.controller.ActivityController; +import org.robolectric.annotation.Config; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowApp.class, ShadowKeyProviderFactory.class, ShadowKeyService.class}) +public class CoinbasePayRouterTest +{ + private CoinbasePayRouter coinbasePayRouter; + private SplashActivity activity; + + @Before + public void setUp() + { + ActivityController activityController = Robolectric.buildActivity(SplashActivity.class); + activity = activityController.get(); + coinbasePayRouter = new CoinbasePayRouter(); + } + + @Test + public void testOpen() + { + coinbasePayRouter.open(activity); + + Intent expectedIntent = new Intent(activity, CoinbasePayActivity.class); + Intent actual = shadowOf(RuntimeEnvironment.getApplication()).getNextStartedActivity(); + assertThat(expectedIntent.getComponent(), equalTo(actual.getComponent())); + } + + @Test + public void testBuyFromSelectedChain() + { + coinbasePayRouter.buyFromSelectedChain(activity, "ETH"); + + Intent expectedIntent = new Intent(activity, CoinbasePayActivity.class); + Intent actual = shadowOf(RuntimeEnvironment.getApplication()).getNextStartedActivity(); + assertThat(actual.getComponent(), equalTo(expectedIntent.getComponent())); + assertThat(actual.getStringExtra("blockchain"), equalTo("ETH")); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/util/CoinbasePayUtilsTest.java b/app/src/test/java/com/alphawallet/app/util/CoinbasePayUtilsTest.java new file mode 100644 index 0000000000..3a507da337 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/util/CoinbasePayUtilsTest.java @@ -0,0 +1,23 @@ +package com.alphawallet.app.util; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import com.alphawallet.app.entity.coinbasepay.DestinationWallet; + +import org.junit.Test; + +import java.util.Collections; +import java.util.List; + +public class CoinbasePayUtilsTest +{ + @Test + public void dest_wallet_json_should_match() + { + List assetList = Collections.singletonList("USDC"); + String json = CoinbasePayUtils.getDestWalletJson(DestinationWallet.Type.ASSETS, "0x1234", assetList); + String expectedResult = "[{\"address\":\"0x1234\",\"assets\":[\"USDC\"]}]"; + assertThat(json, equalTo(expectedResult)); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/widget/BuyEthOptionsViewTest.java b/app/src/test/java/com/alphawallet/app/widget/BuyEthOptionsViewTest.java new file mode 100644 index 0000000000..47f6cfa5b4 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/widget/BuyEthOptionsViewTest.java @@ -0,0 +1,48 @@ +package com.alphawallet.app.widget; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.view.View; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.alphawallet.app.R; +import com.alphawallet.shadows.ShadowRealm; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = {ShadowRealm.class}) +public class BuyEthOptionsViewTest +{ + private BuyEthOptionsView buyEthOptionsView; + private View buyWithCoinbaseButton; + + @Before + public void setUp() + { + buyEthOptionsView = new BuyEthOptionsView(ApplicationProvider.getApplicationContext()); + initView(); + } + + private void initView() + { + buyWithCoinbaseButton = buyEthOptionsView.findViewById(R.id.buy_with_coinbase_pay); + } + + @Test + public void testBuyWithCoinbasePay() + { + View.OnClickListener listener = mock(View.OnClickListener.class); + buyEthOptionsView.setOnBuyWithCoinbasePayListener(listener); + + buyWithCoinbaseButton.performClick(); + + verify(listener).onClick(buyWithCoinbaseButton); + } +} \ No newline at end of file From a14cb14abaf48651f0e9d99f274875736fb8f99c Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 31 Aug 2022 13:59:50 +0800 Subject: [PATCH 079/183] Add setup guide (#2773) * Update doc * Revert dependencies modification * Add env * Add Gradle task to check PAT * Fix build script * Fix name confliction * Refactor unit test * Increase e2e test timeout period * Update doc with missing permission * Update build token --- .github/workflows/ci.yml | 2 ++ .github/workflows/e2e.yml | 3 +-- .github/workflows/lint-pr.yml | 10 ++-------- .github/workflows/lint.yml | 8 ++------ README.md | 8 +++++++- app/build.gradle | 31 ++++++++++++++++++++++++++----- gradle.properties | 6 +++++- 7 files changed, 45 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0aab75e294..81b1631727 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,8 @@ jobs: architecture: arm64 - name: Run unit tests + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: sh ./build.sh - name: Upload Test Reports Folder diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 083c07df1f..e06f5892b5 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -25,8 +25,7 @@ jobs: - name: Run tests uses: reactivecircus/android-emulator-runner@v2 env: - USERNAME: ${{ env.GITHUB_ACTOR }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index ddcf22ac7a..57fe4af172 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -4,6 +4,8 @@ jobs: lint: name: Comments lint result on PR runs-on: macos-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v3 @@ -14,20 +16,12 @@ jobs: java-version: 11 cache: gradle - name: Run detekt - env: - USERNAME: ${{ env.GITHUB_ACTOR }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:detekt continue-on-error: true - name: Run Android Lint - env: - USERNAME: ${{ env.GITHUB_ACTOR }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:lintAnalyticsDebug - name: Run Android Lint Reporter to report Lint and Detekt result to PR env: - USERNAME: ${{ env.GITHUB_ACTOR }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a503745754..6f717d653f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,6 +8,8 @@ jobs: lint: name: Run Lint runs-on: macos-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v3 @@ -18,12 +20,6 @@ jobs: java-version: 11 cache: gradle - name: Run Kotlin lint - env: - USERNAME: ${{ env.GITHUB_ACTOR }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:detekt - name: Run Android Lint - env: - USERNAME: ${{ env.GITHUB_ACTOR }} - TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew :app:lintAnalyticsDebug \ No newline at end of file diff --git a/README.md b/README.md index 940ca051e7..d2f5a3fc07 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,13 @@ We want to give businesses the whitelabel tools they need to develop their ether 1. [Download](https://developer.android.com/studio/) Android Studio. 2. Clone this repository 3. Obtain a free Infura API key and replace the one in build.gradle -4. Build the project in AndroidStudio or Run `./gradlew build` to install tools and dependencies. See [BUILD.md](BUILD.md) for more details. +4. Generate a GitHub [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `read:packages, read:user` permission +5. Edit `~/.gradle/gradle.properties` add blow properties: +```properties +gpr.user=Your GitHub Email +gpr.key=The GitHub Personal Access Token you created in previous step +``` +6. Build the project in AndroidStudio or Run `./gradlew build` to install tools and dependencies. See [BUILD.md](BUILD.md) for more details. You can also build it from the commandline just like other Android apps. Note that JDK 8 and 11 are the versions supported by Android. diff --git a/app/build.gradle b/app/build.gradle index 8ac165b989..6884a88165 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,7 +68,11 @@ android_lint_reporter { repositories { maven { - url 'https://maven.google.com' + url = uri("https://maven.pkg.github.com/trustwallet/wallet-core") + credentials { + username = getGitHubUsername() + password = getPAT() + } } } @@ -210,6 +214,24 @@ task printVersionCode { } } +gradle.projectsEvaluated({ + def username = getGitHubUsername() + def password = getPAT() + def isOnCI = System.getenv("GITHUB_TOKEN") + if (!isOnCI && (!username || !password)) { + throw new GradleException('Please provide GitHub username and Personal Access Token. Find more here https://github.com/alphaWallet/alpha-wallet-android#getting-started') + } +}) + +// GitHub Personal Access Token +private String getPAT() { + project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") +} + +private String getGitHubUsername() { + project.findProperty("gpr.user") +} + dependencies { implementation project(":lib") @@ -308,13 +330,12 @@ dependencies { androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0' - implementation group: 'com.trustwallet', name: 'wallet-core', version: '2.6.3' - //implementation "com.trustwallet:wallet-core:0.12.31" + implementation 'com.trustwallet:wallet-core:2.6.4' - implementation 'com.github.florent37:tutoshowcase:1.0.1' + implementation 'com.github.florent37:TutoShowcase:d8b91be8a2' // Do not upgrade unless we have migrated to AndroidX - implementation 'com.google.android:flexbox:2.0.1' + implementation 'com.github.google:flexbox-layout:2.0.1' implementation 'com.github.salomonbrys.kotson:kotson:2.5.0' diff --git a/gradle.properties b/gradle.properties index b6b58e06e1..06439cc4c8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,8 @@ android.enableJetifier=true android.useAndroidX=true org.gradle.jvmargs=-Xms2048m -Xmx4096m -android.suppressUnsupportedCompileSdk=32 \ No newline at end of file +android.suppressUnsupportedCompileSdk=32 + +# You should replace these with your own generated PAT, please see the Readme.md +gpr.user=smarttokenlabs@hotmail.com +gpr.key=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 \ No newline at end of file From 5746c1e1dc2105fc3e3d5c852d54af193518b515 Mon Sep 17 00:00:00 2001 From: James Brown Date: Wed, 31 Aug 2022 23:43:17 +1000 Subject: [PATCH 080/183] EIP5169 files from IPFS are intrinsically signed (#2792) --- .../app/service/AssetDefinitionService.java | 67 ++++++++++++++----- 1 file changed, 50 insertions(+), 17 deletions(-) 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 0692453e25..382ebc6893 100644 --- a/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java +++ b/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java @@ -130,6 +130,9 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface private static final String ASSET_DEFINITION_DB = "ASSET-db.realm"; private static final String BUNDLED_SCRIPT = "bundled"; private static final long CHECK_TX_LOGS_INTERVAL = 20; + private static final String EIP5169_ISSUER = "EIP5169-IPFS"; + private static final String EIP5169_CERTIFIER = "Smart Token Labs"; + private static final String EIP5169_KEY_OWNER = "Contract Owner"; //TODO Source this from the contract via owner() private final Context context; private final OkHttpClient okHttpClient; @@ -928,7 +931,7 @@ private Single handleNewTSFile(File newFile) final TokenDefinition td = parseFile(tsf.getInputStream()); List originContracts = getOriginContracts(td); //remove all old definitions & certificates - deleteScriptEntriesFromRealm(originContracts, isDebugOverride); + deleteScriptEntriesFromRealm(originContracts, isDebugOverride, tsf.calcMD5()); cachedDefinition = null; return cacheSignature(tsf) .map(contracts -> fileLoadComplete(originContracts, tsf, td)); @@ -941,7 +944,7 @@ private Single handleNewTSFile(File newFile) return Single.fromCallable(TokenDefinition::new); } - private void deleteScriptEntriesFromRealm(List origins, boolean isDebug) + private void deleteScriptEntriesFromRealm(List origins, boolean isDebug, String newFileHash) { try (Realm realm = realmManager.getRealmInstance(ASSET_DEFINITION_DB)) { @@ -958,7 +961,7 @@ private void deleteScriptEntriesFromRealm(List origins, boolean RealmCertificateData realmCert = r.where(RealmCertificateData.class) .equalTo("instanceKey", realmData.getFileHash()) .findFirst(); - if (realmCert != null) realmCert.deleteFromRealm(); + if (realmCert != null && !realmData.getFileHash().equals(newFileHash)) realmCert.deleteFromRealm(); //don't delete cert if new cert will overwrite it deleteEventDataForScript(realmData); realmData.deleteFromRealm(); } @@ -975,7 +978,7 @@ public Single fetchTokenScriptFromContract(Token token, MutableLiveData downloadScript(uri, 0)) - .map(xmlBody -> storeFile(token.tokenInfo.address, xmlBody)); + .map(dlResponse -> storeFile(token.tokenInfo.address, dlResponse)); } private Single tryServerIfRequired(File contractScript, String address) @@ -1025,10 +1028,10 @@ private Single fetchXMLFromServer(String address) "/" + address; - String xmlBody = downloadScript(sb, fileTime); - if (!TextUtils.isEmpty(xmlBody)) + Pair downloadResponse = downloadScript(sb, fileTime); + if (!TextUtils.isEmpty(downloadResponse.first)) { - result = storeFile(address, xmlBody); + result = storeFile(address, downloadResponse); } assetChecked.put(address, System.currentTimeMillis()); @@ -1037,9 +1040,10 @@ private Single fetchXMLFromServer(String address) }); } - private String downloadScript(String Uri, long currentFileTime) throws PackageManager.NameNotFoundException + private Pair downloadScript(String Uri, long currentFileTime) throws PackageManager.NameNotFoundException { - if (TextUtils.isEmpty(Uri)) return ""; + boolean isIPFS = false; + if (TextUtils.isEmpty(Uri)) return new Pair<>("", false); SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH); format.setTimeZone(TimeZone.getTimeZone("UTC")); String dateFormat = format.format(new Date(currentFileTime)); @@ -1058,7 +1062,7 @@ private String downloadScript(String Uri, long currentFileTime) throws PackageMa .url(Uri) .get(); - if (!Uri.toLowerCase().contains("ipfs")) + if (!Uri.toLowerCase().contains("ipfs.io")) { bld.addHeader("Accept", "text/xml; charset=UTF-8") .addHeader("X-Client-Name", "AlphaWallet") @@ -1067,6 +1071,10 @@ private String downloadScript(String Uri, long currentFileTime) throws PackageMa .addHeader("X-Platform-Version", OSVersion) .addHeader("If-Modified-Since", dateFormat); } + else + { + isIPFS = true; + } Request request = bld.build(); @@ -1079,7 +1087,7 @@ private String downloadScript(String Uri, long currentFileTime) throws PackageMa case HttpURLConnection.HTTP_NOT_MODIFIED: break; case HttpURLConnection.HTTP_OK: - return response.body().string(); + return new Pair<>(response.body().string(), isIPFS); } } catch (Exception e) @@ -1087,7 +1095,7 @@ private String downloadScript(String Uri, long currentFileTime) throws PackageMa Timber.e(e); } - return ""; + return new Pair<>("", false); } private boolean definitionIsOutOfDate(TokenDefinition td) @@ -1586,15 +1594,18 @@ private void storeCertificateData(String hash, XMLDsigDescriptor sig) throws Rea { try (Realm realm = realmManager.getRealmInstance(ASSET_DEFINITION_DB)) { - realm.executeTransactionAsync(r -> { + realm.executeTransaction(r -> { //if signature present, then just update RealmCertificateData realmData = r.where(RealmCertificateData.class) .equalTo("instanceKey", hash) .findFirst(); if (realmData == null) + { realmData = r.createObject(RealmCertificateData.class, hash); + } realmData.setFromSig(sig); + r.insertOrUpdate(realmData); }); } } @@ -1628,6 +1639,19 @@ private XMLDsigDescriptor getCertificateFromRealm(String hash) return sig; } + private XMLDsigDescriptor IPFSSigDescriptor() + { + XMLDsigDescriptor sig = new XMLDsigDescriptor(); + sig.issuer = EIP5169_ISSUER; + sig.certificateName = EIP5169_CERTIFIER; + sig.keyName = EIP5169_KEY_OWNER; + sig.keyType = "ECDSA"; + sig.result = "Pass"; + sig.subject = ""; + sig.type = SigReturnType.SIGNATURE_PASS; + return sig; + } + /** * Use internal directory to store contracts fetched from the server * @param address @@ -1635,9 +1659,9 @@ private XMLDsigDescriptor getCertificateFromRealm(String hash) * @return * @throws */ - private File storeFile(String address, String result) throws IOException + private File storeFile(String address, Pair result) throws IOException { - if (result == null || result.length() < 10) return new File(""); + if (result.first == null || result.first.length() < 10) return new File(""); String fName = address + ".xml"; @@ -1646,10 +1670,19 @@ private File storeFile(String address, String result) throws IOException FileOutputStream fos = new FileOutputStream(file); OutputStream os = new BufferedOutputStream(fos); - os.write(result.getBytes()); + os.write(result.first.getBytes()); fos.flush(); os.close(); fos.close(); + + //handle signature for IPFS + if (result.second) + { + TokenScriptFile tsf = new TokenScriptFile(context, file.getAbsolutePath()); + String hash = tsf.calcMD5(); + storeCertificateData(hash, IPFSSigDescriptor()); + } + return file; } @@ -1990,7 +2023,7 @@ public Single getSignatureData(long chainId, String contractA { String hash = tsf.calcMD5(); XMLDsigDescriptor sig = getCertificateFromRealm(hash); - if (sig == null || (sig.result != null && sig.result.equals("fail"))) + if (sig == null || (sig.result != null && sig.result.equalsIgnoreCase("fail"))) { sig = alphaWalletService.checkTokenScriptSignature(tsf); tsf.determineSignatureType(sig); From d04e1ed207be17689fc844409820e34d88b072bc Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 1 Sep 2022 13:08:20 +0800 Subject: [PATCH 081/183] Remove GITHUB_TOKEN, build with Gradle configuration (#2796) * Remove GITHUB_TOKEN, build with gradle configuration * Encode PAT --- .github/workflows/ci.yml | 2 -- .github/workflows/e2e.yml | 2 -- .github/workflows/lint-pr.yml | 3 --- .github/workflows/lint.yml | 3 --- app/build.gradle | 6 +++--- gradle.properties | 6 ++++-- 6 files changed, 7 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81b1631727..0aab75e294 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,8 +18,6 @@ jobs: architecture: arm64 - name: Run unit tests - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: sh ./build.sh - name: Upload Test Reports Folder diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index e06f5892b5..d3ec0e5500 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -24,8 +24,6 @@ jobs: - name: Run tests uses: reactivecircus/android-emulator-runner@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: api-level: ${{ matrix.api-level }} target: ${{ matrix.target }} diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index 57fe4af172..11a6b1b8a6 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -4,9 +4,6 @@ jobs: lint: name: Comments lint result on PR runs-on: macos-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - uses: actions/checkout@v3 - name: set up JDK diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6f717d653f..1d79fa0a64 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,9 +8,6 @@ jobs: lint: name: Run Lint runs-on: macos-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - uses: actions/checkout@v3 - name: Set up JDK diff --git a/app/build.gradle b/app/build.gradle index 6884a88165..4a24eb8309 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -217,15 +217,15 @@ task printVersionCode { gradle.projectsEvaluated({ def username = getGitHubUsername() def password = getPAT() - def isOnCI = System.getenv("GITHUB_TOKEN") - if (!isOnCI && (!username || !password)) { + if (!username || !password) { throw new GradleException('Please provide GitHub username and Personal Access Token. Find more here https://github.com/alphaWallet/alpha-wallet-android#getting-started') } }) // GitHub Personal Access Token private String getPAT() { - project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + def encodedToken = project.findProperty("gpr.key") + new String(encodedToken.decodeBase64()) } private String getGitHubUsername() { diff --git a/gradle.properties b/gradle.properties index 06439cc4c8..6030110a80 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,6 +9,8 @@ android.useAndroidX=true org.gradle.jvmargs=-Xms2048m -Xmx4096m android.suppressUnsupportedCompileSdk=32 -# You should replace these with your own generated PAT, please see the Readme.md +# Base64 Encoded GitHub PAT, +# Make sure only check read:packages and read:user permissions if you want to create your own PAT, +# and encode it with Base64 encoder https://www.base64encoder.io/ gpr.user=smarttokenlabs@hotmail.com -gpr.key=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 \ No newline at end of file +gpr.key=Z2hwX3NFR09PbXRkOFQ2M09RcEdmY0xvR1VXTVJ6ODJBSDAxWWQ4OA== \ No newline at end of file From fe5afcdccc52c0303cdc2d9bf99ac4e0cad2939b Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 2 Sep 2022 11:05:05 +1000 Subject: [PATCH 082/183] Change order of main tokens, update names (#2798) --- app/src/main/java/com/alphawallet/app/C.java | 6 +-- .../app/repository/EthereumNetworkBase.java | 52 +++++++++---------- .../repository/EthereumNetworkRepository.java | 8 ++- .../app/service/OpenSeaService.java | 5 +- .../app/service/TickerService.java | 14 ++--- .../service/TransactionsNetworkClient.java | 6 +-- .../app/ui/ImportTokenActivity.java | 7 +-- .../app/util/DappBrowserUtils.java | 6 +-- .../java/com/alphawallet/app/util/Utils.java | 8 +-- .../app/widget/FunctionButtonBar.java | 10 ++-- .../token/web/Service/EthRPCNodes.java | 2 +- .../ethereum/EthereumNetworkBase.java | 18 +++---- .../token/entity/MagicLinkInfo.java | 24 ++------- 13 files changed, 72 insertions(+), 94 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 456c00069d..1961f6c311 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -39,8 +39,8 @@ public abstract class C { public static final String FANTOM_TEST_NETWORK = "Fantom (Test)"; public static final String AVALANCHE_NETWORK = "Avalanche"; public static final String FUJI_TEST_NETWORK = "Avalanche FUJI (Test)"; - public static final String MATIC_NETWORK = "Polygon"; - public static final String MATIC_TEST_NETWORK = "Mumbai (Test)"; + public static final String POLYGON_NETWORK = "Polygon"; + public static final String POLYGON_TEST_NETWORK = "Mumbai (Test)"; public static final String OPTIMISTIC_NETWORK = "Optimistic"; public static final String OPTIMISTIC_TEST_NETWORK = "Optimistic (Test)"; public static final String CRONOS_MAIN_NETWORK = "Cronos"; @@ -80,7 +80,7 @@ public abstract class C { public static final String HECO_SYMBOL = "HT"; public static final String FANTOM_SYMBOL = "FTM"; public static final String AVALANCHE_SYMBOL = "AVAX"; - public static final String MATIC_SYMBOL = "MATIC"; + public static final String POLYGON_SYMBOL = "MATIC"; public static final String CRONOS_SYMBOL = "CRO"; public static final String CRONOS_TEST_SYMBOL = "tCRO"; public static final String ARBITRUM_SYMBOL = "AETH"; diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 2baf9a4cdd..1d92f0add0 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -33,8 +33,8 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_TEST_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_TEST_ID; @@ -48,7 +48,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.SOKOL_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import android.text.TextUtils; import android.util.LongSparseArray; @@ -123,7 +123,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy : FREE_KOVAN_RPC_URL; public static final String GOERLI_RPC_URL = usesProductionKey ? "https://goerli.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_GOERLI_RPC_URL; - public static final String MATIC_RPC_URL = usesProductionKey ? "https://polygon-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() + public static final String POLYGON_RPC_URL = usesProductionKey ? "https://polygon-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_POLYGON_RPC_URL; public static final String ARBITRUM_MAINNET_RPC = usesProductionKey ? "https://arbitrum-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_ARBITRUM_RPC_URL; @@ -172,7 +172,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String BINANCE_MAIN_FALLBACK_RPC_URL = "https://bsc-dataseed2.ninicoin.io:443"; public static final String HECO_RPC_URL = "https://http-mainnet.hecochain.com"; public static final String HECO_TEST_RPC_URL = "https://http-testnet.hecochain.com"; - public static final String MATIC_FALLBACK_RPC_URL = "https://matic-mainnet.chainstacklabs.com"; + public static final String POLYGON_FALLBACK_RPC_URL = "https://matic-mainnet.chainstacklabs.com"; public static final String MUMBAI_FALLBACK_RPC_URL = "https://matic-mumbai.chainstacklabs.com"; public static final String OPTIMISTIC_MAIN_FALLBACK_URL = "https://mainnet.optimism.io"; public static final String OPTIMISTIC_TEST_FALLBACK_URL = "https://kovan.optimism.io"; @@ -191,8 +191,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy //If your wallet prioritises xDai for example, you may want to move the XDAI_ID to the front of this list, //Then xDai would appear as the first token at the top of the wallet private static final List hasValue = new ArrayList<>(Arrays.asList( - MAINNET_ID, CLASSIC_ID, XDAI_ID, POA_ID, ARTIS_SIGMA1_ID, BINANCE_MAIN_ID, HECO_ID, AVALANCHE_ID, - FANTOM_ID, MATIC_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID, + MAINNET_ID, GNOSIS_ID, POLYGON_ID, CLASSIC_ID, POA_ID, ARTIS_SIGMA1_ID, BINANCE_MAIN_ID, HECO_ID, AVALANCHE_ID, + FANTOM_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID, PHI_NETWORK_MAIN_ID)); // for reset built-in network @@ -206,9 +206,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy CLASSIC_RPC_URL, "https://blockscout.com/etc/mainnet/tx/", CLASSIC_ID, CLASSIC_RPC_URL, "https://blockscout.com/etc/mainnet/api?")); - put(XDAI_ID, new NetworkInfo(C.XDAI_NETWORK_NAME, C.xDAI_SYMBOL, + put(GNOSIS_ID, new NetworkInfo(C.XDAI_NETWORK_NAME, C.xDAI_SYMBOL, XDAI_RPC_URL, - "https://blockscout.com/xdai/mainnet/tx/", XDAI_ID, + "https://blockscout.com/xdai/mainnet/tx/", GNOSIS_ID, "https://gnosis.public-rpc.com", "https://blockscout.com/xdai/mainnet/api?")); put(POA_ID, new NetworkInfo(C.POA_NETWORK_NAME, C.POA_SYMBOL, POA_RPC_URL, @@ -274,12 +274,12 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy FANTOM_TEST_RPC_URL, "https://explorer.testnet.fantom.network/tx/", FANTOM_TEST_ID, FANTOM_TEST_RPC_URL, "https://api.covalenthq.com/v1/" + COVALENT)); //NB: Fantom testnet not yet supported by Covalent - put(MATIC_ID, new NetworkInfo(C.MATIC_NETWORK, C.MATIC_SYMBOL, MATIC_RPC_URL, - "https://polygonscan.com/tx/", MATIC_ID, - MATIC_FALLBACK_RPC_URL, "https://api.polygonscan.com/api?")); - put(MATIC_TEST_ID, new NetworkInfo(C.MATIC_TEST_NETWORK, C.MATIC_SYMBOL, + put(POLYGON_ID, new NetworkInfo(C.POLYGON_NETWORK, C.POLYGON_SYMBOL, POLYGON_RPC_URL, + "https://polygonscan.com/tx/", POLYGON_ID, + POLYGON_FALLBACK_RPC_URL, "https://api.polygonscan.com/api?")); + put(POLYGON_TEST_ID, new NetworkInfo(C.POLYGON_TEST_NETWORK, C.POLYGON_SYMBOL, MUMBAI_TEST_RPC_URL, - "https://mumbai.polygonscan.com/tx/", MATIC_TEST_ID, + "https://mumbai.polygonscan.com/tx/", POLYGON_TEST_ID, MUMBAI_FALLBACK_RPC_URL, " https://api-testnet.polygonscan.com/api?")); put(OPTIMISTIC_MAIN_ID, new NetworkInfo(C.OPTIMISTIC_NETWORK, C.ETH_SYMBOL, OPTIMISTIC_MAIN_URL, @@ -365,7 +365,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(CLASSIC_ID, R.drawable.ic_icons_network_etc); //classic_logo put(POA_ID, R.drawable.ic_poa_logo); put(SOKOL_ID, R.drawable.ic_icons_tokens_sokol); - put(XDAI_ID, R.drawable.ic_icons_network_gnosis); + put(GNOSIS_ID, R.drawable.ic_icons_network_gnosis); put(GOERLI_ID, R.drawable.ic_goerli); put(ARTIS_SIGMA1_ID, R.drawable.ic_artis_sigma_logo); put(ARTIS_TAU1_ID, R.drawable.ic_artis_tau_logo); @@ -377,8 +377,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(FANTOM_TEST_ID, R.drawable.ic_icons_fantom_test); put(AVALANCHE_ID, R.drawable.ic_icons_tokens_avalanche); put(FUJI_TEST_ID, R.drawable.ic_icons_tokens_avalanche_testnet); - put(MATIC_ID, R.drawable.ic_icons_polygon); - put(MATIC_TEST_ID, R.drawable.ic_icons_tokens_mumbai); + put(POLYGON_ID, R.drawable.ic_icons_polygon); + put(POLYGON_TEST_ID, R.drawable.ic_icons_tokens_mumbai); put(OPTIMISTIC_MAIN_ID, R.drawable.ic_optimism_logo); put(OPTIMISTIC_TEST_ID, R.drawable.ic_optimism_testnet_logo); put(CRONOS_MAIN_ID, R.drawable.ic_cronos_mainnet); @@ -408,7 +408,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(CLASSIC_ID, R.drawable.ic_icons_network_etc); put(POA_ID, R.drawable.ic_icons_network_poa); put(SOKOL_ID, R.drawable.ic_icons_tokens_sokol); - put(XDAI_ID, R.drawable.ic_icons_network_gnosis); + put(GNOSIS_ID, R.drawable.ic_icons_network_gnosis); put(GOERLI_ID, R.drawable.ic_goerli); put(ARTIS_SIGMA1_ID, R.drawable.ic_icons_network_artis); put(ARTIS_TAU1_ID, R.drawable.ic_artis_tau_logo); @@ -420,8 +420,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(FANTOM_TEST_ID, R.drawable.ic_icons_fantom_test); put(AVALANCHE_ID, R.drawable.ic_icons_network_avalanche); put(FUJI_TEST_ID, R.drawable.ic_icons_tokens_avalanche_testnet); - put(MATIC_ID, R.drawable.ic_icons_network_polygon); - put(MATIC_TEST_ID, R.drawable.ic_icons_tokens_mumbai); + put(POLYGON_ID, R.drawable.ic_icons_network_polygon); + put(POLYGON_TEST_ID, R.drawable.ic_icons_tokens_mumbai); put(OPTIMISTIC_MAIN_ID, R.drawable.ic_icons_network_optimism); put(OPTIMISTIC_TEST_ID, R.drawable.ic_optimism_testnet_logo); put(CRONOS_MAIN_ID, R.drawable.ic_cronos_mainnet); @@ -451,7 +451,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(CLASSIC_ID, R.color.classic); put(POA_ID, R.color.poa); put(SOKOL_ID, R.color.sokol); - put(XDAI_ID, R.color.xdai); + put(GNOSIS_ID, R.color.xdai); put(GOERLI_ID, R.color.goerli); put(ARTIS_SIGMA1_ID, R.color.artis_sigma1); put(ARTIS_TAU1_ID, R.color.artis_tau1); @@ -463,8 +463,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(FANTOM_TEST_ID, R.color.fantom_test); put(AVALANCHE_ID, R.color.avalanche_main); put(FUJI_TEST_ID, R.color.avalanche_test); - put(MATIC_ID, R.color.polygon_main); - put(MATIC_TEST_ID, R.color.polygon_test); + put(POLYGON_ID, R.color.polygon_main); + put(POLYGON_TEST_ID, R.color.polygon_test); put(OPTIMISTIC_MAIN_ID, R.color.optimistic_main); put(OPTIMISTIC_TEST_ID, R.color.optimistic_test); put(CRONOS_MAIN_ID, R.color.cronos_main); @@ -489,12 +489,12 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy //Add it to this list here if so. Note that so far, all gas oracles follow the same format: // + GAS_API //If the gas oracle you're adding doesn't follow this spec then you'll have to change the getGasOracle method - private static final List hasGasOracleAPI = Arrays.asList(MAINNET_ID, HECO_ID, BINANCE_MAIN_ID, MATIC_ID); + private static final List hasGasOracleAPI = Arrays.asList(MAINNET_ID, HECO_ID, BINANCE_MAIN_ID, POLYGON_ID); //These chains don't allow custom gas private static final List hasLockedGas = Arrays.asList(OPTIMISTIC_MAIN_ID, OPTIMISTIC_TEST_ID, ARBITRUM_MAIN_ID, ARBITRUM_TEST_ID, KLAYTN_ID, KLAYTN_BAOBAB_ID); - private static final List hasOpenSeaAPI = Arrays.asList(MAINNET_ID, MATIC_ID, RINKEBY_ID); + private static final List hasOpenSeaAPI = Arrays.asList(MAINNET_ID, POLYGON_ID, RINKEBY_ID); private static final LongSparseArray blockGasLimit = new LongSparseArray() { @@ -1093,7 +1093,7 @@ public static String getChainSymbol(long chainId) public static BigInteger getMaxEventFetch(long chainId) { - if (chainId == MATIC_ID || chainId == MATIC_TEST_ID) + if (chainId == POLYGON_ID || chainId == POLYGON_TEST_ID) { return BigInteger.valueOf(3500L); } diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkRepository.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkRepository.java index 8d219bcf42..2c2be94338 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkRepository.java @@ -12,13 +12,11 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; public class EthereumNetworkRepository extends EthereumNetworkBase { @@ -68,11 +66,11 @@ private void buildPopularTokenMap(List networkFilters) popularTokens.put(unknownToken.address.toLowerCase(), new ContractLocator(unknownToken.address, MAINNET_ID)); } } - if (networkFilters == null || networkFilters.contains(XDAI_ID)) + if (networkFilters == null || networkFilters.contains(GNOSIS_ID)) { for (UnknownToken unknownToken: knownContract.getXDAI()) { - popularTokens.put(unknownToken.address.toLowerCase(), new ContractLocator(unknownToken.address, XDAI_ID)); + popularTokens.put(unknownToken.address.toLowerCase(), new ContractLocator(unknownToken.address, GNOSIS_ID)); } } } diff --git a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java index 0b1b7227b0..9b11004fa8 100644 --- a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java +++ b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java @@ -13,7 +13,6 @@ import com.alphawallet.app.entity.tokens.TokenFactory; import com.alphawallet.app.entity.tokens.TokenInfo; import com.alphawallet.app.repository.KeyProviderFactory; -import com.alphawallet.app.repository.KeyProviderJNIImpl; import com.alphawallet.app.util.JsonUtils; import com.alphawallet.ethereum.EthereumNetworkBase; import com.google.gson.Gson; @@ -357,7 +356,7 @@ else if (networkId == EthereumNetworkBase.RINKEBY_ID) { api = C.OPENSEA_ASSETS_API_RINKEBY; } - else if (networkId == EthereumNetworkBase.MATIC_ID) + else if (networkId == EthereumNetworkBase.POLYGON_ID) { api = C.OPENSEA_ASSETS_API_MATIC; ownerOption = "owner_address"; @@ -383,7 +382,7 @@ else if (networkId == EthereumNetworkBase.RINKEBY_ID) { api = C.OPENSEA_SINGLE_ASSET_API_RINKEBY + contractAddress + "/" + tokenId; } - else if (networkId == EthereumNetworkBase.MATIC_ID) + else if (networkId == EthereumNetworkBase.POLYGON_ID) { api = C.OPENSEA_SINGLE_ASSET_API_MATIC + contractAddress + "/" + tokenId; } diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index 8526533e97..c134f9b83b 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -13,12 +13,12 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; import android.text.TextUtils; @@ -694,9 +694,9 @@ private void resetTickerUpdate() // Update this list from here: https://api.coingecko.com/api/v3/asset_platforms public static final Map coinGeckoChainIdToAPIName = new HashMap(){{ put(MAINNET_ID, "ethereum"); - put(XDAI_ID, "xdai"); + put(GNOSIS_ID, "xdai"); put(BINANCE_MAIN_ID, "binance-smart-chain"); - put(MATIC_ID, "polygon-pos"); + put(POLYGON_ID, "polygon-pos"); put(CLASSIC_ID, "ethereum-classic"); put(FANTOM_ID, "fantom"); put(AVALANCHE_ID, "avalanche"); @@ -717,7 +717,7 @@ private void resetTickerUpdate() private static final Map dexGuruChainIdToAPISymbol = new HashMap(){{ put(MAINNET_ID, "eth"); put(BINANCE_MAIN_ID, "bsc"); - put(MATIC_ID, "polygon"); + put(POLYGON_ID, "polygon"); put(AVALANCHE_ID, "avalanche"); }}; @@ -731,12 +731,12 @@ public void deleteTickers() put(MAINNET_ID, "ethereum"); put(CLASSIC_ID, "ethereum-classic"); put(POA_ID, "poa-network"); - put(XDAI_ID, "xdai"); + put(GNOSIS_ID, "xdai"); put(BINANCE_MAIN_ID, "binancecoin"); put(HECO_ID, "huobi-token"); put(AVALANCHE_ID, "avalanche-2"); put(FANTOM_ID, "fantom"); - put(MATIC_ID, "matic-network"); + put(POLYGON_ID, "matic-network"); put(ARBITRUM_MAIN_ID, "ethereum"); put(OPTIMISTIC_MAIN_ID, "ethereum"); put(KLAYTN_ID, "klay-token"); diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java index bda363f1af..9e3a9ad810 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java @@ -8,8 +8,8 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_TESTNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_TEST_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; import android.text.TextUtils; @@ -697,7 +697,7 @@ else if (networkInfo.chainId == BINANCE_TEST_ID || networkInfo.chainId == BINANC { return BSC_EXPLORER_API_KEY; } - else if (networkInfo.chainId == MATIC_ID || networkInfo.chainId == MATIC_TEST_ID) + else if (networkInfo.chainId == POLYGON_ID || networkInfo.chainId == POLYGON_TEST_ID) { return POLYGONSCAN_API_KEY; diff --git a/app/src/main/java/com/alphawallet/app/ui/ImportTokenActivity.java b/app/src/main/java/com/alphawallet/app/ui/ImportTokenActivity.java index e748601473..de73fdb307 100644 --- a/app/src/main/java/com/alphawallet/app/ui/ImportTokenActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/ImportTokenActivity.java @@ -5,7 +5,6 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.util.Log; import android.view.MenuItem; import android.view.View; import android.webkit.WebView; @@ -43,13 +42,11 @@ import java.math.BigDecimal; -import javax.inject.Inject; - import timber.log.Timber; import static com.alphawallet.app.C.IMPORT_STRING; import static com.alphawallet.app.entity.Operation.SIGN_DATA; -import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import static com.alphawallet.token.tools.Convert.getEthString; import static com.alphawallet.token.tools.ParseMagicLink.currencyLink; import static com.alphawallet.token.tools.ParseMagicLink.spawnable; @@ -157,7 +154,7 @@ private void checkContractNetwork(String contractAddress) { case currencyLink: //for currency drop link, check xDai first, then other networks - viewModel.switchNetwork(XDAI_ID); + viewModel.switchNetwork(GNOSIS_ID); viewModel.checkTokenNetwork(contractAddress, "requiredPrefix"); break; default: diff --git a/app/src/main/java/com/alphawallet/app/util/DappBrowserUtils.java b/app/src/main/java/com/alphawallet/app/util/DappBrowserUtils.java index 0ddfd35f75..ee0901df3a 100644 --- a/app/src/main/java/com/alphawallet/app/util/DappBrowserUtils.java +++ b/app/src/main/java/com/alphawallet/app/util/DappBrowserUtils.java @@ -1,8 +1,8 @@ package com.alphawallet.app.util; import static com.alphawallet.app.util.Utils.isValidUrl; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_TEST_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; import android.content.Context; import android.content.SharedPreferences; @@ -259,7 +259,7 @@ private static void blankPrefEntry(Context context, String key) public static String defaultDapp(long chainId) { - return (chainId == MATIC_ID || chainId == MATIC_TEST_ID) ? POLYGON_HOMEPAGE : DEFAULT_HOMEPAGE; + return (chainId == POLYGON_ID || chainId == POLYGON_TEST_ID) ? POLYGON_HOMEPAGE : DEFAULT_HOMEPAGE; } public static boolean isWithinHomePage(String url) diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index ef70103546..1575f91cf1 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -4,10 +4,10 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.CLASSIC_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import android.app.Activity; import android.content.Context; @@ -773,12 +773,12 @@ public static String getTokenAddrFromAWUrl(String url) private static final Map twChainNames = new HashMap() { { put(CLASSIC_ID, "classic"); - put(XDAI_ID, "xdai"); + put(GNOSIS_ID, "xdai"); put(POA_ID, "poa"); put(BINANCE_MAIN_ID, "smartchain"); put(AVALANCHE_ID, "avalanche"); put(OPTIMISTIC_MAIN_ID, "optimism"); - put(MATIC_ID, "polygon"); + put(POLYGON_ID, "polygon"); put(MAINNET_ID, "ethereum"); } }; 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 cc806e680e..de64555baf 100644 --- a/app/src/main/java/com/alphawallet/app/widget/FunctionButtonBar.java +++ b/app/src/main/java/com/alphawallet/app/widget/FunctionButtonBar.java @@ -4,9 +4,9 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import android.annotation.SuppressLint; import android.content.Context; @@ -621,7 +621,7 @@ private void addTokenScriptFunctions(Map availableFunctions, T */ private boolean setupCustomTokenActions() { - if (token.tokenInfo.chainId == MATIC_ID && token.isNonFungible()) + if (token.tokenInfo.chainId == POLYGON_ID && token.isNonFungible()) { return false; } @@ -652,7 +652,7 @@ else if (token.tokenInfo.chainId == BINANCE_MAIN_ID return true; } } - else if (token.tokenInfo.chainId == MATIC_ID) + else if (token.tokenInfo.chainId == POLYGON_ID) { addFunction(R.string.swap_with_quickswap); return true; @@ -728,7 +728,7 @@ public void setupBuyFunction(BuyCryptoInterface buyCryptoInterface, OnRampReposi private void addBuyFunction() { if (token.tokenInfo.chainId == MAINNET_ID - || token.tokenInfo.chainId == XDAI_ID) + || token.tokenInfo.chainId == GNOSIS_ID) { addPurchaseVerb(token, onRampRepository); } diff --git a/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java b/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java index 1e1782cf89..e1fee2e176 100644 --- a/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java +++ b/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java @@ -35,7 +35,7 @@ public static String getNodeURLByNetworkId(long networkId) { return SOKOL_RPC_URL; case (int)EthereumNetworkBase.CLASSIC_ID: return CLASSIC_RPC_URL; - case (int)EthereumNetworkBase.XDAI_ID: + case (int)EthereumNetworkBase.GNOSIS_ID: return XDAI_RPC_URL; case (int)EthereumNetworkBase.GOERLI_ID: return GOERLI_RPC_URL; diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 7c0ee5f6bd..dadfb333ca 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -15,7 +15,7 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final long ROPSTEN_ID = 3; public static final long SOKOL_ID = 77; public static final long RINKEBY_ID = 4; - public static final long XDAI_ID = 100; + public static final long GNOSIS_ID = 100; public static final long GOERLI_ID = 5; public static final long ARTIS_SIGMA1_ID = 246529; public static final long ARTIS_TAU1_ID = 246785; @@ -27,8 +27,8 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final long FANTOM_TEST_ID = 4002; public static final long AVALANCHE_ID = 43114; public static final long FUJI_TEST_ID = 43113; - public static final long MATIC_ID = 137; - public static final long MATIC_TEST_ID = 80001; + public static final long POLYGON_ID = 137; + public static final long POLYGON_TEST_ID = 80001; public static final long OPTIMISTIC_MAIN_ID = 10; public static final long OPTIMISTIC_TEST_ID = 69; public static final long CRONOS_MAIN_ID = 25; @@ -92,8 +92,8 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit MAINNET_ID, false)); put(CLASSIC_ID, new NetworkInfo("Ethereum Classic", "ETC", CLASSIC_RPC_URL, "https://blockscout.com/etc/mainnet/tx/", CLASSIC_ID, false)); - put(XDAI_ID, new NetworkInfo("Gnosis", "xDAi", XDAI_RPC_URL, "https://blockscout.com/xdai/mainnet/tx/", - XDAI_ID, false)); + put(GNOSIS_ID, new NetworkInfo("Gnosis", "xDAi", XDAI_RPC_URL, "https://blockscout.com/xdai/mainnet/tx/", + GNOSIS_ID, false)); put(POA_ID, new NetworkInfo("POA", "POA", POA_RPC_URL, "https://blockscout.com/poa/core/tx/", POA_ID, false)); put(ARTIS_SIGMA1_ID, new NetworkInfo("ARTIS sigma1", "ATS", ARTIS_SIGMA1_RPC_URL, "https://explorer.sigma1.artis.network/tx/", @@ -129,10 +129,10 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit put(FANTOM_TEST_ID, new NetworkInfo("Fantom (Test)", "FTM", FANTOM_TEST_RPC_URL, "https://explorer.testnet.fantom.network/tx/", FANTOM_TEST_ID, false)); - put(MATIC_ID, new NetworkInfo("Polygon", "POLY", MATIC_RPC_URL, "https://polygonscan.com/tx/", - MATIC_ID, false)); - put(MATIC_TEST_ID, new NetworkInfo("Mumbai (Test)", "POLY", MUMBAI_TEST_RPC_URL, "https://mumbai.polygonscan.com/tx/", - MATIC_TEST_ID, false)); + put(POLYGON_ID, new NetworkInfo("Polygon", "POLY", MATIC_RPC_URL, "https://polygonscan.com/tx/", + POLYGON_ID, false)); + put(POLYGON_TEST_ID, new NetworkInfo("Mumbai (Test)", "POLY", MUMBAI_TEST_RPC_URL, "https://mumbai.polygonscan.com/tx/", + POLYGON_TEST_ID, false)); put(OPTIMISTIC_MAIN_ID, new NetworkInfo("Optimistic","ETH", OPTIMISTIC_MAIN_URL, "https://optimistic.etherscan.io/tx/", OPTIMISTIC_MAIN_ID, false)); diff --git a/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java b/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java index b613d885de..86f932f30f 100644 --- a/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java +++ b/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java @@ -5,31 +5,15 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_SIGMA1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_TAU1_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.AVALANCHE_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.AVALANCHE_RPC_URL; -import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.CLASSIC_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.FANTOM_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.FANTOM_RPC_URL; -import static com.alphawallet.ethereum.EthereumNetworkBase.FANTOM_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.FANTOM_TEST_RPC_URL; -import static com.alphawallet.ethereum.EthereumNetworkBase.FUJI_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.FUJI_TEST_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_RPC_URL; -import static com.alphawallet.ethereum.EthereumNetworkBase.MATIC_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MUMBAI_TEST_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.SOKOL_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; /** * Created by James on 2/03/2019. @@ -98,7 +82,7 @@ public static String getMagicLinkDomainFromNetworkId(long networkId) { return sokolMagicLinkDomain; case (int)CLASSIC_ID: return classicMagicLinkDomain; - case (int)XDAI_ID: + case (int) GNOSIS_ID: return xDaiMagicLinkDomain; case (int)GOERLI_ID: return goerliMagicLinkDomain; @@ -131,7 +115,7 @@ public static long getNetworkIdFromDomain(String domain) { case sokolMagicLinkDomain: return SOKOL_ID; case xDaiMagicLinkDomain: - return XDAI_ID; + return GNOSIS_ID; case goerliMagicLinkDomain: return GOERLI_ID; case artisSigma1MagicLinkDomain: @@ -159,7 +143,7 @@ public static String getEtherscanURLbyNetwork(long networkId) { return sokolEtherscan; case (int)CLASSIC_ID: return classicEtherscan; - case (int)XDAI_ID: + case (int) GNOSIS_ID: return xDaiEtherscan; case (int)GOERLI_ID: return goerliEtherscan; From b00f6551bd2de25da736835c5034f80713505115 Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 2 Sep 2022 22:20:30 +1000 Subject: [PATCH 083/183] Add unit test for EIP5169 Certificate (#2797) * small refactor and add unit test * Wait for token * Change timeout --- .../app/TokenScriptCertificateTest.java | 56 ++++++ .../app/service/AssetDefinitionService.java | 178 +++++++++++------- .../java/com/alphawallet/app/util/Utils.java | 4 +- 3 files changed, 165 insertions(+), 73 deletions(-) create mode 100644 app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java diff --git a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java new file mode 100644 index 0000000000..4ae079d56a --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java @@ -0,0 +1,56 @@ +package com.alphawallet.app; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; +import static com.alphawallet.app.assertions.Should.shouldSee; +import static com.alphawallet.app.steps.Steps.importKSWalletFromFrontPage; +import static com.alphawallet.app.steps.Steps.selectTestNet; +import static com.alphawallet.app.steps.Steps.switchToWallet; +import static com.alphawallet.app.util.Helper.click; +import static com.alphawallet.app.util.Helper.waitUntil; + +import androidx.test.espresso.action.ViewActions; + +import com.alphawallet.app.util.Helper; + +import org.junit.Test; + +/** + * Created by JB on 1/09/2022. + */ +public class TokenScriptCertificateTest extends BaseE2ETest { + private static final String keystore = "{\"address\":\"f9c883c8dca140ebbdc87a225fe6e330be5d25ef\",\"id\":\"5648908b-1862-4f3e-b425-d1ba0790a601\",\"version\":3,\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"bcbfcffb52f42e9d149b97a8512d4c49\"},\"ciphertext\":\"967d3cd0db82445e4e74a6d5e537c799632e91cf0ca6f9fec17c769812e9454f\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"084c44b6e76e2b879257520ac00bb59c93e17321ce4a029f9b8294e304defc7a\"},\"mac\":\"0e4a74746d0c3e2739653200bcffb92716e77677d41f84c1184a4eb2054963c6\"}}\n"; + private static final String password = "hellohello"; + + @Test + public void cipher_integrity_test_keystore() { + importKSWalletFromFrontPage(keystore, password); + + selectTestNet("Kovan"); + + //Ensure we're on the wallet page + switchToWallet("0xF9c883c8DcA140EBbdC87a225Fe6E330BE5D25ef"); + + //Wait for TokensService engine to resolve the STL token + Helper.wait(8); + + //Swipe up + onView(withId(R.id.coordinator)).perform(ViewActions.swipeUp()); + + waitUntil(withSubstring("OFFIC"), 600); + + //Select token + click(withSubstring("OFFIC")); + + //Wait for cert to resolve + Helper.wait(8); + + //click certificate + click(withId(R.id.image_lock)); + + shouldSee("Smart Token Labs"); + shouldSee("ECDSA"); + shouldSee("Contract Owner"); // Note this may fail once we pull owner() from contract, test will need to be changed to contract owner, which for this test is: 0xA20efc4B9537d27acfD052003e311f762620642D + } +} 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 382ebc6893..88e6099de9 100644 --- a/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java +++ b/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java @@ -159,9 +159,9 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface private Disposable checkEventDisposable; /* Designed with the assmuption that only a single instance of this class at any given time - * ^^ The "service" part of AssetDefinitionService is the keyword here. - * This is shorthand in the project to indicate this is a singleton that other classes inject. - * This is the design pattern of the app. See class RepositoriesModule for constructors which are called at App init only */ + * ^^ The "service" part of AssetDefinitionService is the keyword here. + * This is shorthand in the project to indicate this is a singleton that other classes inject. + * This is the design pattern of the app. See class RepositoriesModule for constructors which are called at App init only */ public AssetDefinitionService(OkHttpClient client, Context ctx, NotificationService svs, RealmManager rm, TokensService tokensService, TokenLocalSource trs, TransactionRepositoryType trt, @@ -174,7 +174,9 @@ public AssetDefinitionService(OkHttpClient client, Context ctx, NotificationServ realmManager = rm; alphaWalletService = alphaService; this.tokensService = tokensService; - tokenscriptUtility = new TokenscriptFunction() { }; //no overridden functions + tokenscriptUtility = new TokenscriptFunction() + { + }; //no overridden functions tokenLocalSource = trs; transactionRepository = trt; assetLoadingLock = new Semaphore(1); @@ -183,13 +185,14 @@ public AssetDefinitionService(OkHttpClient client, Context ctx, NotificationServ loadAssetScripts(); } - public TokenLocalSource getTokenLocalSource() { + public TokenLocalSource getTokenLocalSource() + { return tokenLocalSource; } /** * Load all TokenScripts - * + *

* This order has to be observed because it's an expected developer override order. If a script is placed in the /AlphaWallet directory * it is expected to override the one fetched from the repo server. * If a developer clicks on a script intent this script is expected to override the one fetched from the server. @@ -232,7 +235,8 @@ private List checkRealmScriptsForChanges() for (RealmTokenScriptData entry : realmData) { - if (handledHashes.contains(entry.getFileHash())) continue; //already checked - note that if a contract has multiple origins it could have more than one entry + if (handledHashes.contains(entry.getFileHash())) + continue; //already checked - note that if a contract has multiple origins it could have more than one entry //get file TokenScriptFile tsf = new TokenScriptFile(context, entry.getFilePath()); handledHashes.add(entry.getFileHash()); @@ -245,7 +249,7 @@ private List checkRealmScriptsForChanges() handledHashes.add(tsf.calcMD5()); //add the hash of the new file //re-parse script, file hash has changed final TokenDefinition td = parseFile(tsf.getInputStream()); - cacheSignature(tsf) + cacheSignature(tsf) .map(definition -> getOriginContracts(td)) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) @@ -299,7 +303,7 @@ private void loadNewFiles(List handledHashes) handledHashes.add(new TokenScriptFile(context, file.getAbsolutePath()).calcMD5()); handleFileLoadError(e, file); } - } ); + }); } private void deleteTokenScriptFromRealm(Realm realm, String fileHash) throws RealmException @@ -399,22 +403,22 @@ private TokenDefinition fileLoadComplete(List originContracts, final String hash = file.calcMD5(); - realm.beginTransaction(); - for (ContractLocator cl : originContracts) - { - String entryKey = getTSDataKey(cl.chainId, cl.address); - RealmTokenScriptData entry = realm.where(RealmTokenScriptData.class) - .equalTo("instanceKey", entryKey) - .findFirst(); - if (entry != null) continue; // at this point, don't override any existing entry - entry = realm.createObject(RealmTokenScriptData.class, entryKey); - entry.setFileHash(hash); - entry.setFilePath(file.getAbsolutePath()); - entry.setNames(td.getTokenNameList()); - entry.setViewList(td.getViews()); - entry.setHasEvents(hasEvents); - } - realm.commitTransaction(); + realm.executeTransaction(r -> { + for (ContractLocator cl : originContracts) + { + String entryKey = getTSDataKey(cl.chainId, cl.address); + RealmTokenScriptData entry = realm.where(RealmTokenScriptData.class) + .equalTo("instanceKey", entryKey) + .findFirst(); + if (entry != null) continue; // at this point, don't override any existing entry + entry = realm.createObject(RealmTokenScriptData.class, entryKey); + entry.setFileHash(hash); + entry.setFilePath(file.getAbsolutePath()); + entry.setNames(td.getTokenNameList()); + entry.setViewList(td.getViews()); + entry.setHasEvents(hasEvents); + } + }); } catch (Exception e) { @@ -488,11 +492,13 @@ private List buildFileList() //then include the files in the app external directory - these are placed here when there's no file permission files = context.getExternalFilesDir("").listFiles(); - if (files != null) fileList.addAll(Arrays.asList(files)); //now add files in the app's external directory; /Android/data/[app-name]/files. These override internal + if (files != null) + fileList.addAll(Arrays.asList(files)); //now add files in the app's external directory; /Android/data/[app-name]/files. These override internal //finally the files downloaded from the server files = context.getFilesDir().listFiles(); - if (files != null) fileList.addAll(Arrays.asList(files)); //first add files in app internal area - these are downloaded from the server + if (files != null) + fileList.addAll(Arrays.asList(files)); //first add files in app internal area - these are downloaded from the server } catch (Exception e) { @@ -690,7 +696,8 @@ public TokenScriptResult.Attribute getAttribute(Token token, BigInteger tokenId, } } - private boolean checkReadPermission() { + private boolean checkReadPermission() + { return context.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; } @@ -789,7 +796,8 @@ public Single getAssetDefinitionASync(long chainId, final Strin { if (address == null) return Single.fromCallable(TokenDefinition::new); String contractName = address; - if (contractName.equalsIgnoreCase(tokensService.getCurrentAddress())) contractName = "ethereum"; + if (contractName.equalsIgnoreCase(tokensService.getCurrentAddress())) + contractName = "ethereum"; // hold until asset definitions have finished loading waitForAssets(); @@ -882,7 +890,7 @@ public String getIssuerName(Token token) private void loadScriptFromServer(String correctedAddress) { //first check the last time we tried this session - if (assetChecked.get(correctedAddress) == null || (System.currentTimeMillis() > (assetChecked.get(correctedAddress) + 1000L*60L*60L))) + if (assetChecked.get(correctedAddress) == null || (System.currentTimeMillis() > (assetChecked.get(correctedAddress) + 1000L * 60L * 60L))) { fetchXMLFromServer(correctedAddress) .flatMap(this::cacheSignature) @@ -906,7 +914,8 @@ private void onError(Throwable throwable) private TokenDefinition parseFile(InputStream xmlInputStream) throws Exception { Locale locale; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + { locale = context.getResources().getConfiguration().getLocales().get(0); } else @@ -961,7 +970,8 @@ private void deleteScriptEntriesFromRealm(List origins, boolean RealmCertificateData realmCert = r.where(RealmCertificateData.class) .equalTo("instanceKey", realmData.getFileHash()) .findFirst(); - if (realmCert != null && !realmData.getFileHash().equals(newFileHash)) realmCert.deleteFromRealm(); //don't delete cert if new cert will overwrite it + if (realmCert != null && !realmData.getFileHash().equals(newFileHash)) + realmCert.deleteFromRealm(); //don't delete cert if new cert will overwrite it deleteEventDataForScript(realmData); realmData.deleteFromRealm(); } @@ -976,7 +986,8 @@ public Single fetchTokenScriptFromContract(Token token, MutableLiveData { if (!TextUtils.isEmpty(uri)) updateFlag.postValue(true); - return uri; }) + return uri; + }) .map(uri -> downloadScript(uri, 0)) .map(dlResponse -> storeFile(token.tokenInfo.address, dlResponse)); } @@ -1021,7 +1032,8 @@ private Single fetchXMLFromServer(String address) result = defaultReturn; } - if (assetChecked.get(address) != null && (System.currentTimeMillis() > (assetChecked.get(address) + 1000L*60L*60L))) return result; + if (assetChecked.get(address) != null && (System.currentTimeMillis() > (assetChecked.get(address) + 1000L * 60L * 60L))) + return result; String sb = TOKENSCRIPT_REPO_SERVER + TOKENSCRIPT_CURRENT_SCHEMA + @@ -1065,11 +1077,11 @@ private Pair downloadScript(String Uri, long currentFileTime) t if (!Uri.toLowerCase().contains("ipfs.io")) { bld.addHeader("Accept", "text/xml; charset=UTF-8") - .addHeader("X-Client-Name", "AlphaWallet") - .addHeader("X-Client-Version", appVersion) - .addHeader("X-Platform-Name", "Android") - .addHeader("X-Platform-Version", OSVersion) - .addHeader("If-Modified-Since", dateFormat); + .addHeader("X-Client-Name", "AlphaWallet") + .addHeader("X-Client-Version", appVersion) + .addHeader("X-Platform-Name", "Android") + .addHeader("X-Platform-Version", OSVersion) + .addHeader("If-Modified-Since", dateFormat); } else { @@ -1128,12 +1140,14 @@ private void removeFile(String filename) /** * Only used for loading bundled TokenScripts + * * @param asset * @return */ private boolean addContractAssets(String asset) { - try (InputStream input = context.getResources().getAssets().open(asset)) { + try (InputStream input = context.getResources().getAssets().open(asset)) + { TokenDefinition token = parseFile(input); TokenScriptFile tsf = new TokenScriptFile(context, asset); ContractInfo holdingContracts = token.contracts.get(token.holdingToken); @@ -1157,7 +1171,9 @@ private boolean addContractAssets(String asset) } return true; } - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } return false; @@ -1182,7 +1198,7 @@ private void updateRealmForBundledScript(long chainId, String address, String as { try (Realm realm = realmManager.getRealmInstance(ASSET_DEFINITION_DB)) { - realm.executeTransactionAsync(r -> { + realm.executeTransaction(r -> { String entryKey = getTSDataKey(chainId, address); RealmTokenScriptData entry = r.where(RealmTokenScriptData.class) .equalTo("instanceKey", entryKey) @@ -1201,7 +1217,8 @@ private void updateRealmForBundledScript(long chainId, String address, String as public TokenDefinition getTokenDefinition(File file) { - try (FileInputStream input = new FileInputStream(file)) { + try (FileInputStream input = new FileInputStream(file)) + { return parseFile(input); } catch (Exception e) @@ -1255,7 +1272,8 @@ private void checkAddToEventList(EventDefinition ev) public void stopEventListener() { if (eventListener != null && !eventListener.isDisposed()) eventListener.dispose(); - if (checkEventDisposable != null && !checkEventDisposable.isDisposed()) checkEventDisposable.dispose(); + if (checkEventDisposable != null && !checkEventDisposable.isDisposed()) + checkEventDisposable.dispose(); } public void startEventListener() @@ -1263,7 +1281,7 @@ public void startEventListener() if (assetLoadingLock.availablePermits() == 0) return; if (eventListener != null && !eventListener.isDisposed()) eventListener.dispose(); - eventListener = Observable.interval(0, CHECK_TX_LOGS_INTERVAL, TimeUnit.SECONDS) + eventListener = Observable.interval(0, CHECK_TX_LOGS_INTERVAL, TimeUnit.SECONDS) .doOnNext(l -> { checkEvents() .subscribeOn(Schedulers.io()) @@ -1290,7 +1308,8 @@ private void getEvent(EventDefinition ev) { EthFilter filter = getEventFilter(ev); if (filter == null) return; - if (BuildConfig.DEBUG) eventConnection.acquire(); //prevent overlapping event calls while debugging + if (BuildConfig.DEBUG) + eventConnection.acquire(); //prevent overlapping event calls while debugging final String walletAddress = tokensService.getCurrentAddress(); Web3j web3j = getWeb3jService(ev.getEventChainId()); @@ -1359,10 +1378,10 @@ private String processLogs(EventDefinition ev, List logs, Stri for (int i = index; i >= 0; i--) { EthLog.LogResult ethLog = logs.get(i); - String txHash = ((Log)ethLog.get()).getTransactionHash(); + String txHash = ((Log) ethLog.get()).getTransactionHash(); if (TextUtils.isEmpty(firstTxHash)) firstTxHash = txHash; String selectVal = EventUtils.getSelectVal(ev, ethLog); - BigInteger blockNumber = ((Log)ethLog.get()).getBlockNumber(); + BigInteger blockNumber = ((Log) ethLog.get()).getBlockNumber(); if (blockNumber.compareTo(ev.readBlock) > 0) { @@ -1376,7 +1395,7 @@ private String processLogs(EventDefinition ev, List logs, Stri } else { - EthBlock txBlock = EventUtils.getBlockDetails(((Log)ethLog.get()).getBlockHash(), web3j).blockingGet(); + EthBlock txBlock = EventUtils.getBlockDetails(((Log) ethLog.get()).getBlockHash(), web3j).blockingGet(); long blockTime = txBlock.getBlock().getTimestamp().longValue(); storeActivityValue(walletAddress, ev, ethLog, blockTime, ev.activityName); @@ -1401,7 +1420,8 @@ private void storeLatestEventBlockTime(String walletAddress, EventDefinition ev, RealmAuxData realmToken = r.where(RealmAuxData.class) .equalTo("instanceKey", databaseKey) .findFirst(); - if (realmToken == null) realmToken = r.createObject(RealmAuxData.class, databaseKey); + if (realmToken == null) + realmToken = r.createObject(RealmAuxData.class, databaseKey); realmToken.setResultTime(System.currentTimeMillis()); realmToken.setResult(ev.readBlock.toString(16)); realmToken.setFunctionId(eventName); @@ -1440,7 +1460,8 @@ private void storeAuxData(String walletAddress, String databaseKey, BigInteger t RealmAuxData realmToken = r.where(RealmAuxData.class) .equalTo("instanceKey", databaseKey) .findFirst(); - if (realmToken == null) realmToken = r.createObject(RealmAuxData.class, databaseKey); + if (realmToken == null) + realmToken = r.createObject(RealmAuxData.class, databaseKey); realmToken.setResultTime(blockTime); realmToken.setResult(eventData); realmToken.setFunctionId(activityName); @@ -1467,7 +1488,7 @@ private void storeEventValue(String walletAddress, EventDefinition ev, EthLog.Lo TransactionResult txResult = getFunctionResult(eventContractAddress, attr, tokenId); txResult.result = attr.getSyntaxVal(selectVal); - long blockNumber = ((Log)log.get()).getBlockNumber().longValue(); + long blockNumber = ((Log) log.get()).getBlockNumber().longValue(); //Update the entry for the attribute if required if (txResult.resultTime == 0 || blockNumber >= txResult.resultTime) @@ -1482,7 +1503,7 @@ private boolean allowableExtension(File file) int index = file.getName().lastIndexOf("."); if (index >= 0) { - String extension = file.getName().substring(index+1); + String extension = file.getName().substring(index + 1); switch (extension) { case "xml": @@ -1520,6 +1541,7 @@ private boolean isAddress(File file) /** * This is used to retrieve the file from the secure area in order to check the date. * Note: it only finds files previously downloaded from the server + * * @param contractAddress * @return */ @@ -1551,7 +1573,7 @@ private List getScriptsInSecureZone() .filter(this::allowableExtension) .filter(File::canRead) .filter(this::isAddress) - .forEach(file -> checkScripts.add(getFileName(file)) ).isDisposed(); + .forEach(file -> checkScripts.add(getFileName(file))).isDisposed(); return checkScripts; } @@ -1654,6 +1676,7 @@ private XMLDsigDescriptor IPFSSigDescriptor() /** * Use internal directory to store contracts fetched from the server + * * @param address * @param result * @return @@ -1799,7 +1822,8 @@ public Single>> fetchFunctionMap(Token token) TSSelection selection = action.exclude != null ? td.getSelection(action.exclude) : null; if (selection == null) { - if (!validActions.containsKey(tokenId)) validActions.put(tokenId, new ArrayList<>()); + if (!validActions.containsKey(tokenId)) + validActions.put(tokenId, new ArrayList<>()); validActions.get(tokenId).add(actionName); } else @@ -1813,7 +1837,8 @@ public Single>> fetchFunctionMap(Token token) boolean exclude = EvaluateSelection.evaluate(selection.head, idAttrResults); if (!exclude || selection.denialMessage != null) { - if (!validActions.containsKey(tokenId)) validActions.put(tokenId, new ArrayList<>()); + if (!validActions.containsKey(tokenId)) + validActions.put(tokenId, new ArrayList<>()); validActions.get(tokenId).add(actionName); } } @@ -1950,6 +1975,7 @@ private FileObserver startFileListener(String path) FileObserver observer = new FileObserver(path) { private final String listenerPath = path; + @Override public void onEvent(int event, @Nullable String file) { @@ -1978,7 +2004,8 @@ public void onEvent(int event, @Nullable String file) } catch (Exception e) { - if (homeMessenger != null) homeMessenger.tokenScriptError(e.getMessage()); + if (homeMessenger != null) + homeMessenger.tokenScriptError(e.getMessage()); } break; default: @@ -2124,7 +2151,8 @@ public TransactionResult getFunctionResult(ContractAddress contract, Attribute a @Override public TransactionResult storeAuxData(String walletAddress, TransactionResult tResult) { - if (tokensService.getCurrentAddress() == null || !Utils.isAddressValid(tokensService.getCurrentAddress())) return tResult; + if (tokensService.getCurrentAddress() == null || !Utils.isAddressValid(tokensService.getCurrentAddress())) + return tResult; if (tResult.result == null || tResult.resultTime < 0) return tResult; try (Realm realm = realmManager.getRealmInstance(walletAddress)) { @@ -2257,17 +2285,22 @@ private void createAuxData(Realm realm, TransactionResult tResult, String dataBa private void addOpenSeaAttributes(StringBuilder attrs, Token erc721Token, BigInteger tokenId) { NFTAsset tokenAsset = erc721Token.getAssetForToken(tokenId.toString()); - if(tokenAsset == null) return; + if (tokenAsset == null) return; try { //add all asset IDs - if (tokenAsset.getBackgroundColor() != null) TokenScriptResult.addPair(attrs, "background_colour", URLEncoder.encode(tokenAsset.getBackgroundColor(), "utf-8")); - if (tokenAsset.getThumbnail() != null) TokenScriptResult.addPair(attrs, "image_preview_url", URLEncoder.encode(tokenAsset.getThumbnail(), "utf-8")); - if (tokenAsset.getDescription() != null) TokenScriptResult.addPair(attrs, "description", URLEncoder.encode(tokenAsset.getDescription(), "utf-8")); - if (tokenAsset.getExternalLink() != null) TokenScriptResult.addPair(attrs, "external_link", URLEncoder.encode(tokenAsset.getExternalLink(), "utf-8")); + if (tokenAsset.getBackgroundColor() != null) + TokenScriptResult.addPair(attrs, "background_colour", URLEncoder.encode(tokenAsset.getBackgroundColor(), "utf-8")); + if (tokenAsset.getThumbnail() != null) + TokenScriptResult.addPair(attrs, "image_preview_url", URLEncoder.encode(tokenAsset.getThumbnail(), "utf-8")); + if (tokenAsset.getDescription() != null) + TokenScriptResult.addPair(attrs, "description", URLEncoder.encode(tokenAsset.getDescription(), "utf-8")); + if (tokenAsset.getExternalLink() != null) + TokenScriptResult.addPair(attrs, "external_link", URLEncoder.encode(tokenAsset.getExternalLink(), "utf-8")); //if (tokenAsset.getTraits() != null) TokenScriptResult.addPair(attrs, "traits", tokenAsset.getTraits()); - if (tokenAsset.getName() != null) TokenScriptResult.addPair(attrs, "name", URLEncoder.encode(tokenAsset.getName(), "utf-8")); + if (tokenAsset.getName() != null) + TokenScriptResult.addPair(attrs, "name", URLEncoder.encode(tokenAsset.getName(), "utf-8")); } catch (UnsupportedEncodingException e) { @@ -2294,7 +2327,7 @@ public StringBuilder getTokenAttrs(Token token, BigInteger tokenId, int count) TokenScriptResult.addPair(attrs, "tokenId", tokenId); TokenScriptResult.addPair(attrs, "ownerAddress", token.getWallet()); - if(token instanceof ERC721Token) + if (token instanceof ERC721Token) { addOpenSeaAttributes(attrs, token, tokenId); } @@ -2309,6 +2342,7 @@ public StringBuilder getTokenAttrs(Token token, BigInteger tokenId, int count) /** * Get all the magic values - eg native crypto balances for all chains + * * @return */ public String getMagicValuesForInjection(long chainId) throws Exception @@ -2340,7 +2374,8 @@ public Observable resolveAttrs(Token token, BigInte { TokenDefinition definition = getAssetDefinition(token.tokenInfo.chainId, token.tokenInfo.address); ContractAddress cAddr = new ContractAddress(token.tokenInfo.chainId, token.tokenInfo.address); - if (definition == null) return Observable.fromCallable(() -> new TokenScriptResult.Attribute("RAttrs", "", BigInteger.ZERO, "")); + if (definition == null) + return Observable.fromCallable(() -> new TokenScriptResult.Attribute("RAttrs", "", BigInteger.ZERO, "")); definition.context = new TokenscriptContext(); definition.context.cAddr = cAddr; @@ -2353,7 +2388,7 @@ public Observable resolveAttrs(Token token, BigInte return Observable.fromIterable(attrList) .flatMap(attr -> tokenscriptUtility.fetchAttrResult(token, attr, tokenId, - definition, this, itemView)); + definition, this, itemView)); } public Observable resolveAttrs(Token token, List tokenIds, List extraAttrs) @@ -2508,7 +2543,7 @@ public Single> getAllTokenDefinitions(boolean refresh) catch (Exception e) { TokenScriptFile tsf = new TokenScriptFile(context, file.getAbsolutePath()); - ContractInfo contractInfo = new ContractInfo("Contract Type",new HashMap<>()); + ContractInfo contractInfo = new ContractInfo("Contract Type", new HashMap<>()); StringWriter stackTrace = new StringWriter(); e.printStackTrace(new PrintWriter(stackTrace)); @@ -2523,7 +2558,8 @@ public Single> getAllTokenDefinitions(boolean refresh) public Single checkServerForScript(Token token, MutableLiveData updateFlag) { TokenScriptFile tf = getTokenScriptFile(token.tokenInfo.chainId, token.getAddress()); - if ((tf != null && !TextUtils.isEmpty(tf.getName())) && !isInSecureZone(tf)) return Single.fromCallable(TokenDefinition::new); //early return for debug script check + if ((tf != null && !TextUtils.isEmpty(tf.getName())) && !isInSecureZone(tf)) + return Single.fromCallable(TokenDefinition::new); //early return for debug script check //try the contractURI, then server return fetchTokenScriptFromContract(token, updateFlag) @@ -2634,7 +2670,7 @@ public Single fetchViewHeight(long chainId, String address) if (hash.equals(realmToken.getResult())) { //can use this height - return (int)realmToken.getResultTime(); + return (int) realmToken.getResultTime(); } } catch (Exception e) @@ -2672,4 +2708,4 @@ private void deleteAWRealm() }); } } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index 1575f91cf1..ced009f77d 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -813,11 +813,11 @@ public static String parseIPFS(String URL) int ipfsIndex = URL.lastIndexOf("/ipfs/"); if (ipfsIndex >= 0) { - parsed = "https://gateway.ipfs.io" + URL.substring(ipfsIndex); + parsed = "https://alphawallet.infura-ipfs.io" + URL.substring(ipfsIndex); } else if (URL.startsWith(IPFS_PREFIX)) { - parsed = "https://gateway.ipfs.io/ipfs/" + URL.substring(IPFS_PREFIX.length()); + parsed = "https://alphawallet.infura-ipfs.io/ipfs/" + URL.substring(IPFS_PREFIX.length()); } return parsed; From 5dc2c1a706d9447c9329cc6793edb12f1eebc36d Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 2 Sep 2022 22:27:49 +1000 Subject: [PATCH 084/183] Refactor Covalent Handling (#2801) * refactor covalent handling and add unit test * update test * Get resource from resource folder * Remove unused code Co-authored-by: Seaborn Lee --- app/build.gradle | 1 + .../app/entity/CovalentTransaction.java | 39 ++-------- .../service/TransactionsNetworkClient.java | 3 +- .../app/CovalentProcessingTest.java | 76 +++++++++++++++++++ app/src/test/resources/covalenttxs.json | 1 + 5 files changed, 87 insertions(+), 33 deletions(-) create mode 100644 app/src/test/java/com/alphawallet/app/CovalentProcessingTest.java create mode 100644 app/src/test/resources/covalenttxs.json diff --git a/app/build.gradle b/app/build.gradle index 4a24eb8309..d30edd4cfb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -309,6 +309,7 @@ dependencies { testImplementation group: 'org.powermock', name: 'powermock-module-junit4-rule-agent', version: '2.0.9' testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.9' testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9' + testImplementation group: 'org.json', name: 'json', version: '20220320' // Component tests testImplementation 'org.robolectric:robolectric:4.8.2' diff --git a/app/src/main/java/com/alphawallet/app/entity/CovalentTransaction.java b/app/src/main/java/com/alphawallet/app/entity/CovalentTransaction.java index 4b62d4cdd9..566f5d0d74 100644 --- a/app/src/main/java/com/alphawallet/app/entity/CovalentTransaction.java +++ b/app/src/main/java/com/alphawallet/app/entity/CovalentTransaction.java @@ -1,25 +1,17 @@ package com.alphawallet.app.entity; -import com.alphawallet.app.entity.tokenscript.EventUtils; -import com.alphawallet.app.util.Utils; -import com.alphawallet.token.tools.Numeric; +import android.text.TextUtils; -import org.web3j.protocol.Web3j; +import com.alphawallet.app.util.Utils; import java.math.BigInteger; -import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import static com.alphawallet.app.repository.TokenRepository.getWeb3jService; - -import android.text.TextUtils; - /** * Created by JB on 17/05/2021. */ @@ -65,14 +57,10 @@ public Map getParams() throws Exception Param param = new Param(); param.type = lp.type; String rawValue = TextUtils.isEmpty(lp.value) || lp.value.equals("null") ? rawLogValue : lp.value; + param.value = rawValue; if (lp.type.startsWith("uint") || lp.type.startsWith("int")) { - param.valueBI = rawValue.startsWith("0x") ? Numeric.toBigInt(rawValue) : new BigInteger(rawValue); - param.value = ""; - } - else - { - param.value = rawValue; + param.valueBI = Utils.stringToBigInteger(rawValue);// rawValue.startsWith("0x") ? Numeric.toBigInt(rawValue) : new BigInteger(rawValue); } params.put(lp.name, param); @@ -153,21 +141,10 @@ private EtherscanEvent getEtherscanTransferEvent(LogEvent logEvent) throws Excep Map logParams = logEvent.getParams(); - ev.from = logParams.get("from").value; - ev.to = logParams.get("to").value; - - logParams.remove("from"); - logParams.remove("to"); - - if (logEvent.sender_contract_decimals == 0) - { - //get TokenId - ev.tokenID = logParams.values().iterator().next().valueBI.toString(); - } - else - { - ev.value = logParams.values().iterator().next().valueBI.toString(); - } + ev.from = logParams.containsKey("from") ? logParams.get("from").value : ""; + ev.to = logParams.containsKey("to") ? logParams.get("to").value : ""; + ev.tokenID = logParams.containsKey("tokenId") ? logParams.get("tokenId").valueBI.toString() : ""; + ev.value = logParams.containsKey("value") ? logParams.get("value").valueBI.toString() : ""; ev.gasUsed = gas_spent; ev.gasPrice = gas_price; diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java index 9e3a9ad810..ce974a573f 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java @@ -167,7 +167,7 @@ public Single storeNewTransactions(TokensService svs, NetworkInfo { lastTransaction = syncDownwards(updates, instance, svs, networkInfo, tokenAddress, 9999999999L); } - else // try to sydenc upwards from the last read + else // try to sync upwards from the last read { lastTransaction = syncUpwards(updates, instance, svs, networkInfo, tokenAddress, lastBlockNumber); } @@ -699,7 +699,6 @@ else if (networkInfo.chainId == BINANCE_TEST_ID || networkInfo.chainId == BINANC } else if (networkInfo.chainId == POLYGON_ID || networkInfo.chainId == POLYGON_TEST_ID) { - return POLYGONSCAN_API_KEY; } else if (networkInfo.chainId == AURORA_MAINNET_ID || networkInfo.chainId == AURORA_TESTNET_ID) diff --git a/app/src/test/java/com/alphawallet/app/CovalentProcessingTest.java b/app/src/test/java/com/alphawallet/app/CovalentProcessingTest.java new file mode 100644 index 0000000000..adb76f7dd6 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/CovalentProcessingTest.java @@ -0,0 +1,76 @@ +package com.alphawallet.app; + +import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; +import static org.junit.Assert.assertEquals; + +import com.alphawallet.app.entity.CovalentTransaction; +import com.alphawallet.app.entity.EtherscanEvent; +import com.alphawallet.app.entity.EtherscanTransaction; +import com.alphawallet.app.entity.NetworkInfo; +import com.google.common.io.Resources; +import com.google.gson.Gson; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Test; + +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +/** + * Created by JB on 2/09/2022. + */ +public class CovalentProcessingTest +{ + private String APIReturn; + + public CovalentProcessingTest() throws IOException + { + URL url = Resources.getResource("covalenttxs.json"); + APIReturn = Resources.toString(url, StandardCharsets.UTF_8); + } + + @Test + public void testCovalentTx() throws JSONException + { + CovalentTransaction[] covalentTransactions = getCovalentTransactions(APIReturn); + + NetworkInfo info = new NetworkInfo("Klaytn", "Klaytn", "", "", KLAYTN_ID, "", ""); + EtherscanEvent[] events = CovalentTransaction.toEtherscanEvents(covalentTransactions); + EtherscanTransaction[] txs = CovalentTransaction.toRawEtherscanTransactions(covalentTransactions, info); + + assertEquals(events.length, 517); + assertEquals(txs.length, 139); + + EtherscanEvent ev = events[0]; + assertEquals(ev.value, "2700000000"); + assertEquals(ev.tokenDecimal, "6"); + + ev = events[516]; + + assertEquals(ev.value, ""); + assertEquals(ev.tokenID, "20007"); + assertEquals(ev.tokenDecimal, "0"); + assertEquals(ev.from, "0xc067a53c91258ba513059919e03b81cf93f57ac7"); + assertEquals(ev.to, "0xf9c883c8dca140ebbdc87a225fe6e330be5d25ef"); + } + + private CovalentTransaction[] getCovalentTransactions(String response) throws JSONException + { + if (response == null || response.length() < 80) + { + return new CovalentTransaction[0]; + } + JSONObject stateData = new JSONObject(response); + + JSONObject data = stateData.getJSONObject("data"); + JSONArray orders = data.getJSONArray("items"); + CovalentTransaction[] ctxs = new Gson().fromJson(orders.toString(), CovalentTransaction[].class); + + return ctxs; + } +} + + diff --git a/app/src/test/resources/covalenttxs.json b/app/src/test/resources/covalenttxs.json new file mode 100644 index 0000000000..87fb37e3e5 --- /dev/null +++ b/app/src/test/resources/covalenttxs.json @@ -0,0 +1 @@ +{"data":{"address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","updated_at":"2022-09-02T06:32:32.334301890Z","next_update_at":"2022-09-02T06:37:32.334302150Z","quote_currency":"USD","chain_id":8217,"items":[{"block_signed_at":"2021-08-23T11:47:03Z","block_height":67996465,"tx_hash":"0xaf534e19e3c85c0c4b7743ff4717106e8413ded19644535c7600967f9c7a7d0c","tx_offset":4,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"5000000000000000000","value_quote":9.084015488624573,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":9.538216263055801E-4,"gas_quote_rate":1.8168030977249146,"log_events":[]},{"block_signed_at":"2021-08-23T11:47:18Z","block_height":67996480,"tx_hash":"0x9f56287973f0c8c7309f78a91a202d0f72c715246b9b1c52c434dd954af08a7c","tx_offset":8,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":3300000,"gas_spent":50459,"gas_price":25000000000,"fees_paid":"1261475000000000","gas_quote":0.0022918516877025365,"gas_quote_rate":1.8168030977249146,"log_events":[{"block_signed_at":"2021-08-23T11:47:18Z","block_height":67996480,"tx_offset":8,"log_offset":22,"tx_hash":"0x9f56287973f0c8c7309f78a91a202d0f72c715246b9b1c52c434dd954af08a7c","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000005382cdb55d8c0f05ec619ee80fb55c18f4d7d8b"],"sender_contract_decimals":6,"sender_name":"Orbit Bridge Klaytn USD Tether","sender_contract_ticker_symbol":"KUSDT","sender_address":"0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0x05382cdb55d8c0f05ec619ee80fb55c18f4d7d8b"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564039457584007913129639935"}]}}]},{"block_signed_at":"2021-08-24T10:54:57Z","block_height":68079735,"tx_hash":"0x1b85032039a39119c3acacbd181f28d972942840b6cdd1e88e258d4f1af1fceb","tx_offset":8,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":104926,"gas_spent":57263,"gas_price":25000000000,"fees_paid":"1431575000000000","gas_quote":0.0025168779943346977,"gas_quote_rate":1.7581181526184082,"log_events":[{"block_signed_at":"2021-08-24T10:54:57Z","block_height":68079735,"tx_offset":8,"log_offset":19,"tx_hash":"0x1b85032039a39119c3acacbd181f28d972942840b6cdd1e88e258d4f1af1fceb","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ca4753ef46f847d1b8e8c20947f6e2e78bc1145e","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":6,"sender_name":"Orbit Bridge Klaytn USD Tether","sender_contract_ticker_symbol":"KUSDT","sender_address":"0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000a0eebb00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2700000000"}]}}]},{"block_signed_at":"2021-09-01T03:53:20Z","block_height":68745637,"tx_hash":"0xcddf99eb1ca2c0053de4bef907163c19437dbe7e26fec9db11f10410d4b1fa6f","tx_offset":5,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"8000000000000000000","value_quote":12.85687255859375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.437322616577148E-4,"gas_quote_rate":1.6071090698242188,"log_events":[]},{"block_signed_at":"2021-09-04T01:25:58Z","block_height":68995961,"tx_hash":"0x1345fdd1f88c49d4f617dccb72ddc4d2a7124ed0ef26df913b8b2cff856fda75","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":74926,"gas_spent":27263,"gas_price":25000000000,"fees_paid":"681575000000000","gas_quote":0.0010867547254353762,"gas_quote_rate":1.5944756269454956,"log_events":[{"block_signed_at":"2021-09-04T01:25:58Z","block_height":68995961,"tx_offset":5,"log_offset":2,"tx_hash":"0x1345fdd1f88c49d4f617dccb72ddc4d2a7124ed0ef26df913b8b2cff856fda75","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000ca4753ef46f847d1b8e8c20947f6e2e78bc1145e"],"sender_contract_decimals":6,"sender_name":"Orbit Bridge Klaytn USD Tether","sender_contract_ticker_symbol":"KUSDT","sender_address":"0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000a0eebb00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2700000000"}]}}]},{"block_signed_at":"2021-09-04T01:26:28Z","block_height":68995991,"tx_hash":"0xa89b0ce074ad976e8ba5b1ef61edddbf4519f2dede739bb2fb26a1e49dfc21e5","tx_offset":44,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3188.951253890991,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.370997041463852E-4,"gas_quote_rate":1.5944756269454956,"log_events":[]},{"block_signed_at":"2021-09-04T02:23:54Z","block_height":68999437,"tx_hash":"0xec8daeee46b17129186ccebc8f393a3c6bc1846d92c1dc0e888634c3a0d0ba02","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3188.951253890991,"gas_offered":416455,"gas_spent":284186,"gas_price":25000000000,"fees_paid":"7104650000000000","gas_quote":0.011328191262978314,"gas_quote_rate":1.5944756269454956,"log_events":[{"block_signed_at":"2021-09-04T02:23:54Z","block_height":68999437,"tx_offset":2,"log_offset":10,"tx_hash":"0xec8daeee46b17129186ccebc8f393a3c6bc1846d92c1dc0e888634c3a0d0ba02","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000e957e0a4271093cc1a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4304423610738097245210"}]}},{"block_signed_at":"2021-09-04T02:23:54Z","block_height":68999437,"tx_offset":2,"log_offset":11,"tx_hash":"0xec8daeee46b17129186ccebc8f393a3c6bc1846d92c1dc0e888634c3a0d0ba02","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000e957e0a4271093cc1a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"4304423610738097245210"}]}},{"block_signed_at":"2021-09-04T02:23:54Z","block_height":68999437,"tx_offset":2,"log_offset":12,"tx_hash":"0xec8daeee46b17129186ccebc8f393a3c6bc1846d92c1dc0e888634c3a0d0ba02","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-04T02:23:54Z","block_height":68999437,"tx_offset":2,"log_offset":13,"tx_hash":"0xec8daeee46b17129186ccebc8f393a3c6bc1846d92c1dc0e888634c3a0d0ba02","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004544da3292eb406a0000000000000000000000000000000000000000000000004544db5f3e718dbd","decoded":null},{"block_signed_at":"2021-09-04T02:23:54Z","block_height":68999437,"tx_offset":2,"log_offset":14,"tx_hash":"0xec8daeee46b17129186ccebc8f393a3c6bc1846d92c1dc0e888634c3a0d0ba02","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002466deb5bec65c0e83e7400000000000000000000000000000000000000000004e85f294c0a9f8dbccbf9","decoded":null},{"block_signed_at":"2021-09-04T02:23:54Z","block_height":68999437,"tx_offset":2,"log_offset":15,"tx_hash":"0xec8daeee46b17129186ccebc8f393a3c6bc1846d92c1dc0e888634c3a0d0ba02","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000e957e0a4271093cc1a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4304423610738097245210"}]}},{"block_signed_at":"2021-09-04T02:23:54Z","block_height":68999437,"tx_offset":2,"log_offset":16,"tx_hash":"0xec8daeee46b17129186ccebc8f393a3c6bc1846d92c1dc0e888634c3a0d0ba02","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000e957e0a4271093cc1a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"4304423610738097245210"}]}}]},{"block_signed_at":"2021-09-04T02:24:34Z","block_height":68999477,"tx_hash":"0x1b3cb274a9965bcbfac86769b2a5395692fda106d130e1da18fe9d3153b07de3","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":72290,"gas_spent":56137,"gas_price":25000000000,"fees_paid":"1403425000000000","gas_quote":0.002237726956745982,"gas_quote_rate":1.5944756269454956,"log_events":[{"block_signed_at":"2021-09-04T02:24:34Z","block_height":68999477,"tx_offset":1,"log_offset":2,"tx_hash":"0x1b3cb274a9965bcbfac86769b2a5395692fda106d130e1da18fe9d3153b07de3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000e951ffac6e41400000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4304000000000000000000"}]}}]},{"block_signed_at":"2021-09-04T02:28:46Z","block_height":68999729,"tx_hash":"0x67173ca17d439739eacdce529156fc2895c53c7959d87af07867285b31d0f1fa","tx_offset":0,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3188.951253890991,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.370997041463852E-4,"gas_quote_rate":1.5944756269454956,"log_events":[]},{"block_signed_at":"2021-09-04T02:39:46Z","block_height":69000389,"tx_hash":"0xc3cdc5916588ce1a89790d7ec8bf4a90232b8b1a447fa2299da1c003418c763f","tx_offset":0,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":54985,"gas_spent":21657,"gas_price":25000000000,"fees_paid":"541425000000000","gas_quote":8.63288966318965E-4,"gas_quote_rate":1.5944756269454956,"log_events":[{"block_signed_at":"2021-09-04T02:39:46Z","block_height":69000389,"tx_offset":0,"log_offset":0,"tx_hash":"0xc3cdc5916588ce1a89790d7ec8bf4a90232b8b1a447fa2299da1c003418c763f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ca4753ef46f847d1b8e8c20947f6e2e78bc1145e","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000068cd2afb5d21521400","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"1933245288770000000000"}]}}]},{"block_signed_at":"2021-09-04T02:57:36Z","block_height":69001459,"tx_hash":"0xdf4a32059004b4a7d835e3f08a4ee60df19bfd3e5f8e219a2392e1941b175a99","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":55081,"gas_spent":21721,"gas_price":25000000000,"fees_paid":"543025000000000","gas_quote":8.658401273220778E-4,"gas_quote_rate":1.5944756269454956,"log_events":[{"block_signed_at":"2021-09-04T02:57:36Z","block_height":69001459,"tx_offset":3,"log_offset":13,"tx_hash":"0xdf4a32059004b4a7d835e3f08a4ee60df19bfd3e5f8e219a2392e1941b175a99","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000ca4753ef46f847d1b8e8c20947f6e2e78bc1145e"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000068d30bf315f0a5e01a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"1933668899508097245210"}]}}]},{"block_signed_at":"2021-09-04T04:43:12Z","block_height":69007795,"tx_hash":"0xe68547e0d27a6ba6117e7612e5db3d298b242c77245b5da3533f37164e2ec51d","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","to_address_label":null,"value":"2000000000000000000000","value_quote":3188.951253890991,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.370997041463852E-4,"gas_quote_rate":1.5944756269454956,"log_events":[]},{"block_signed_at":"2021-09-07T07:40:56Z","block_height":69277653,"tx_hash":"0x31abaf5730b578b4384e53e249662f57390d37b0bec1e2c6b64b00bdbcaa8ab2","tx_offset":1,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T07:40:56Z","block_height":69277653,"tx_offset":1,"log_offset":2,"tx_hash":"0x31abaf5730b578b4384e53e249662f57390d37b0bec1e2c6b64b00bdbcaa8ab2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ca4753ef46f847d1b8e8c20947f6e2e78bc1145e","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8d726b7177a800000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T07:41:06Z","block_height":69277663,"tx_hash":"0xf22c68c720d588b39d24778e5a049a06d6fd18591bc7bd593d63100821adfa66","tx_offset":7,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T07:46:49Z","block_height":69278006,"tx_hash":"0x99a7b49764e9c22789104cab5709075d26ba0065deae5cd0bda64c59fee4469a","tx_offset":10,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":71046,"gas_spent":47364,"gas_price":25000000000,"fees_paid":"1184100000000000","gas_quote":0.0019513644775986671,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T07:46:49Z","block_height":69278006,"tx_offset":10,"log_offset":73,"tx_hash":"0x99a7b49764e9c22789104cab5709075d26ba0065deae5cd0bda64c59fee4469a","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564039457584007913129639935"}]}}]},{"block_signed_at":"2021-09-07T08:00:43Z","block_height":69278840,"tx_hash":"0x8c217ce730d83ebe45fef00e22be608920e4db9234f4c3bc58e3e58c909aabf6","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:00:43Z","block_height":69278840,"tx_offset":2,"log_offset":0,"tx_hash":"0x8c217ce730d83ebe45fef00e22be608920e4db9234f4c3bc58e3e58c909aabf6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008abcccc4677c4755ff","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2559255146695043274239"}]}},{"block_signed_at":"2021-09-07T08:00:43Z","block_height":69278840,"tx_offset":2,"log_offset":1,"tx_hash":"0x8c217ce730d83ebe45fef00e22be608920e4db9234f4c3bc58e3e58c909aabf6","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008abcccc4677c4755ff","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2559255146695043274239"}]}},{"block_signed_at":"2021-09-07T08:00:43Z","block_height":69278840,"tx_offset":2,"log_offset":2,"tx_hash":"0x8c217ce730d83ebe45fef00e22be608920e4db9234f4c3bc58e3e58c909aabf6","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T08:00:43Z","block_height":69278840,"tx_offset":2,"log_offset":3,"tx_hash":"0x8c217ce730d83ebe45fef00e22be608920e4db9234f4c3bc58e3e58c909aabf6","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000454fbf0ec0fed425000000000000000000000000000000000000000000000000454fc064dacff32c","decoded":null},{"block_signed_at":"2021-09-07T08:00:43Z","block_height":69278840,"tx_offset":2,"log_offset":4,"tx_hash":"0x8c217ce730d83ebe45fef00e22be608920e4db9234f4c3bc58e3e58c909aabf6","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030fe0b3a77c28d7fbe8bb00000000000000000000000000000000000000000003ed8c430c5c20be8c4cba","decoded":null},{"block_signed_at":"2021-09-07T08:00:43Z","block_height":69278840,"tx_offset":2,"log_offset":5,"tx_hash":"0x8c217ce730d83ebe45fef00e22be608920e4db9234f4c3bc58e3e58c909aabf6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008abcccc4677c4755ff","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2559255146695043274239"}]}},{"block_signed_at":"2021-09-07T08:00:43Z","block_height":69278840,"tx_offset":2,"log_offset":6,"tx_hash":"0x8c217ce730d83ebe45fef00e22be608920e4db9234f4c3bc58e3e58c909aabf6","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008abcccc4677c4755ff","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2559255146695043274239"}]}}]},{"block_signed_at":"2021-09-07T08:01:25Z","block_height":69278882,"tx_hash":"0x8586a9bc7fce321ec70fae68fc3408653bb7ce91d72165f9d44ff8e4ec3aabc8","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:01:25Z","block_height":69278882,"tx_offset":1,"log_offset":0,"tx_hash":"0x8586a9bc7fce321ec70fae68fc3408653bb7ce91d72165f9d44ff8e4ec3aabc8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008ab9424dd6409c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2559000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T08:01:46Z","block_height":69278903,"tx_hash":"0x3af907c5e5c266be835f1d8058fbb8a0b00b243b9d3ebb1a843941de62b54cb4","tx_offset":7,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T08:07:41Z","block_height":69279258,"tx_hash":"0x38c9b6d784113b6054c75be637ac84462c310fe6012a3e5bd74cd30719201acc","tx_offset":8,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:07:41Z","block_height":69279258,"tx_offset":8,"log_offset":9,"tx_hash":"0x38c9b6d784113b6054c75be637ac84462c310fe6012a3e5bd74cd30719201acc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000088d88671cefe6d0f22","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2524359477117416443682"}]}},{"block_signed_at":"2021-09-07T08:07:41Z","block_height":69279258,"tx_offset":8,"log_offset":10,"tx_hash":"0x38c9b6d784113b6054c75be637ac84462c310fe6012a3e5bd74cd30719201acc","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000088d88671cefe6d0f22","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2524359477117416443682"}]}},{"block_signed_at":"2021-09-07T08:07:41Z","block_height":69279258,"tx_offset":8,"log_offset":11,"tx_hash":"0x38c9b6d784113b6054c75be637ac84462c310fe6012a3e5bd74cd30719201acc","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T08:07:41Z","block_height":69279258,"tx_offset":8,"log_offset":12,"tx_hash":"0x38c9b6d784113b6054c75be637ac84462c310fe6012a3e5bd74cd30719201acc","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000454fd40be6a8ba0f000000000000000000000000000000000000000000000000454fd55cb5eb2a80","decoded":null},{"block_signed_at":"2021-09-07T08:07:41Z","block_height":69279258,"tx_offset":8,"log_offset":13,"tx_hash":"0x38c9b6d784113b6054c75be637ac84462c310fe6012a3e5bd74cd30719201acc","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000316b3b1fdb1f36235e4f800000000000000000000000000000000000000000003e879f7fd2371e169f052","decoded":null},{"block_signed_at":"2021-09-07T08:07:41Z","block_height":69279258,"tx_offset":8,"log_offset":14,"tx_hash":"0x38c9b6d784113b6054c75be637ac84462c310fe6012a3e5bd74cd30719201acc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000088d88671cefe6d0f22","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2524359477117416443682"}]}},{"block_signed_at":"2021-09-07T08:07:41Z","block_height":69279258,"tx_offset":8,"log_offset":15,"tx_hash":"0x38c9b6d784113b6054c75be637ac84462c310fe6012a3e5bd74cd30719201acc","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000088d88671cefe6d0f22","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2524359477117416443682"}]}}]},{"block_signed_at":"2021-09-07T08:07:59Z","block_height":69279276,"tx_hash":"0x7c69f2231d39ab489b8db5b3e3b2412be004b2e0c36e296b39855845e736e9d8","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:07:59Z","block_height":69279276,"tx_offset":6,"log_offset":11,"tx_hash":"0x7c69f2231d39ab489b8db5b3e3b2412be004b2e0c36e296b39855845e736e9d8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000088d38953465df00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2524000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T08:08:44Z","block_height":69279321,"tx_hash":"0xaace0ca7a49eed4fc053004104404d190165a9744121cf1aa9b57f807bb151cf","tx_offset":3,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T08:16:36Z","block_height":69279793,"tx_hash":"0xc924c6c2748f84c883e8211de1d0fe5d3b68785499c247b9ee16e3327f326a28","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:16:36Z","block_height":69279793,"tx_offset":4,"log_offset":12,"tx_hash":"0xc924c6c2748f84c883e8211de1d0fe5d3b68785499c247b9ee16e3327f326a28","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000870469798ea12026b8","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2490628368852991354552"}]}},{"block_signed_at":"2021-09-07T08:16:36Z","block_height":69279793,"tx_offset":4,"log_offset":13,"tx_hash":"0xc924c6c2748f84c883e8211de1d0fe5d3b68785499c247b9ee16e3327f326a28","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000870469798ea12026b8","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2490628368852991354552"}]}},{"block_signed_at":"2021-09-07T08:16:36Z","block_height":69279793,"tx_offset":4,"log_offset":14,"tx_hash":"0xc924c6c2748f84c883e8211de1d0fe5d3b68785499c247b9ee16e3327f326a28","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T08:16:36Z","block_height":69279793,"tx_offset":4,"log_offset":15,"tx_hash":"0xc924c6c2748f84c883e8211de1d0fe5d3b68785499c247b9ee16e3327f326a28","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000454fe69b8e13e8b6000000000000000000000000000000000000000000000000454fe7eb64992250","decoded":null},{"block_signed_at":"2021-09-07T08:16:36Z","block_height":69279793,"tx_offset":4,"log_offset":16,"tx_hash":"0xc924c6c2748f84c883e8211de1d0fe5d3b68785499c247b9ee16e3327f326a28","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030db1325479aae8cd6d5f00000000000000000000000000000000000000000003cfdaa55e8cd66a939f8b","decoded":null},{"block_signed_at":"2021-09-07T08:16:36Z","block_height":69279793,"tx_offset":4,"log_offset":17,"tx_hash":"0xc924c6c2748f84c883e8211de1d0fe5d3b68785499c247b9ee16e3327f326a28","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000870469798ea12026b8","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2490628368852991354552"}]}},{"block_signed_at":"2021-09-07T08:16:36Z","block_height":69279793,"tx_offset":4,"log_offset":18,"tx_hash":"0xc924c6c2748f84c883e8211de1d0fe5d3b68785499c247b9ee16e3327f326a28","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000870469798ea12026b8","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2490628368852991354552"}]}}]},{"block_signed_at":"2021-09-07T08:16:55Z","block_height":69279812,"tx_hash":"0x70ca54233efdabc501fd6dc461459544f4edb8efbcf8b6ccbe4dd72ba48a8cbf","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:16:55Z","block_height":69279812,"tx_offset":0,"log_offset":0,"tx_hash":"0x70ca54233efdabc501fd6dc461459544f4edb8efbcf8b6ccbe4dd72ba48a8cbf","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000870991c61dca0c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2491000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T08:23:08Z","block_height":69280185,"tx_hash":"0x1f2d644c6b85f056c037e9ba2ac5b0fe6cea890e2bb32e06186f04b6076f5bfc","tx_offset":3,"successful":true,"from_address":"0x4496f06d8bb0b234057f35c4568aa0c2b0e949f3","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2001000000000000000000","value_quote":3297.593378663063,"gas_offered":1000000,"gas_spent":31000,"gas_price":25000000000,"fees_paid":"775000000000000","gas_quote":0.0012771788448095321,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":36,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8da85ffa22dbc8bd9","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000242992665451072473"}]}},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":37,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffff27257a005dd2437426","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564035457341015247678567462"}]}},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":38,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8da85ffa22dbc8bd9","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000242992665451072473"}]}},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":39,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8da85ffa22dbc8bd900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4affa917add36f6cc","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000242992665451072473"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3333094540925417748172"}]}},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":40,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000534593b6219ac760","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000364488998176608"}]}},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":41,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000534593b6219ac761","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000364488998176609"}]}},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":42,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000534593b6219ac761000000000000000000000000000000000000000000000002783ff9bbb3d2fac3000000000000000000000000000000000000000000000002783ffc33730f6de5","decoded":null},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":43,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031e7170171a460d724b8a00000000000000000000000000000000000000000003bc3a75c4ee4e8e56ff8d","decoded":null},{"block_signed_at":"2021-09-07T08:31:13Z","block_height":69280670,"tx_offset":3,"log_offset":44,"tx_hash":"0x0ab993d7b276157eab042d2819757cfd1bca470f96199d9cf23a003e648e18b0","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8da85ffa22dbc8bd900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4affa917add36f6cc","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000242992665451072473"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3333094540925417748172"}]}}]},{"block_signed_at":"2021-09-07T08:32:16Z","block_height":69280733,"tx_hash":"0xc727fab7210f340d5bec619e73bd72fe91a07772095a1afc7d2530d8a4209bfb","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3342000000000000000000","value_quote":5507.524773359299,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T08:41:17Z","block_height":69281274,"tx_hash":"0xcc6b26e9bbfb8e7e3a93e1caa6618038eecf06a4a333ba579f52c1dbb518ec90","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:41:17Z","block_height":69281274,"tx_offset":1,"log_offset":2,"tx_hash":"0xcc6b26e9bbfb8e7e3a93e1caa6618038eecf06a4a333ba579f52c1dbb518ec90","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":9,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":10,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffe4e85d62414f5537426","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564031461341015247678567462"}]}},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":11,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":12,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5d9fc76842a871024","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3354568237251811545124"}]}},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":13,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":14,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":15,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb10000000000000000000000000000000000000000000000000002784038e2c802d19c00000000000000000000000000000000000000000000000278403b4c2f95a0e2","decoded":null},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":16,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032668689e22145c64c5c500000000000000000000000000000000000000000003be906769fba4e7e085d3","decoded":null},{"block_signed_at":"2021-09-07T08:41:24Z","block_height":69281281,"tx_offset":6,"log_offset":17,"tx_hash":"0xb8773bc644bb798f21d74651c7440cd94311ddb6982b7f3789653e01db799c81","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5d9fc76842a871024","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3354568237251811545124"}]}}]},{"block_signed_at":"2021-09-07T08:42:28Z","block_height":69281345,"tx_hash":"0xdcbe5daa15d2815ed6a0087e80de78e1a2634a23861f694e86b72c667318b1e1","tx_offset":19,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"2354000000000000000000","value_quote":3879.3277428150177,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T08:43:51Z","block_height":69281428,"tx_hash":"0x2d80b9e026a3932abcedc08334080086c9458b7eea2c41f822acf3a60f25b2e7","tx_offset":10,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"1000000000000000000000","value_quote":1647.9727029800415,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T08:46:12Z","block_height":69281569,"tx_hash":"0xe03e4f7e6e9b5c5f27f018590e5f465eda6490ff646606ac52a1128fcb4e1b1c","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:46:12Z","block_height":69281569,"tx_offset":0,"log_offset":0,"tx_hash":"0xe03e4f7e6e9b5c5f27f018590e5f465eda6490ff646606ac52a1128fcb4e1b1c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":0,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":1,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffd75e63247cc18637426","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564027465341015247678567462"}]}},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":2,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":3,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b18e60d9466cbfe776","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3275333139894236079990"}]}},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":4,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":5,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":6,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278407278fd3ac717000000000000000000000000000000000000000000000002784074dd0b807ec3","decoded":null},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":7,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031d098183a9468e94848500000000000000000000000000000000000000000003ca55a16d57bb078d982b","decoded":null},{"block_signed_at":"2021-09-07T08:49:27Z","block_height":69281764,"tx_offset":1,"log_offset":8,"tx_hash":"0x7b986a4008e2ebe15a85c509ee296312aca8a0f4a8ddea8f856c0939456d5eda","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b18e60d9466cbfe776","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3275333139894236079990"}]}}]},{"block_signed_at":"2021-09-07T08:49:45Z","block_height":69281782,"tx_hash":"0xadd069ef8a1ceb7695faaea88fa85ca8c4ce5f11adc5af6d4f66a5edaadcb179","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3275000000000000000000","value_quote":5397.110602259637,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T08:56:25Z","block_height":69282182,"tx_hash":"0x58b9cbf7b657fcd36f6201ac209dad51cd47ecb448212d8c4c700286e9f10ef9","tx_offset":4,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T08:56:25Z","block_height":69282182,"tx_offset":4,"log_offset":3,"tx_hash":"0x58b9cbf7b657fcd36f6201ac209dad51cd47ecb448212d8c4c700286e9f10ef9","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T09:19:57Z","block_height":69283594,"tx_hash":"0x358ea1e3feb972a1755807edb168f2ce5fa470b83a81f4f08d5a41bd7ccdc211","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T09:19:57Z","block_height":69283594,"tx_offset":0,"log_offset":0,"tx_hash":"0x358ea1e3feb972a1755807edb168f2ce5fa470b83a81f4f08d5a41bd7ccdc211","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008387470a5e7c9ab64f","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2426271244975351707215"}]}},{"block_signed_at":"2021-09-07T09:19:57Z","block_height":69283594,"tx_offset":0,"log_offset":1,"tx_hash":"0x358ea1e3feb972a1755807edb168f2ce5fa470b83a81f4f08d5a41bd7ccdc211","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008387470a5e7c9ab64f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2426271244975351707215"}]}},{"block_signed_at":"2021-09-07T09:19:57Z","block_height":69283594,"tx_offset":0,"log_offset":2,"tx_hash":"0x358ea1e3feb972a1755807edb168f2ce5fa470b83a81f4f08d5a41bd7ccdc211","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T09:19:57Z","block_height":69283594,"tx_offset":0,"log_offset":3,"tx_hash":"0x358ea1e3feb972a1755807edb168f2ce5fa470b83a81f4f08d5a41bd7ccdc211","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045509a3d38fdc92d00000000000000000000000000000000000000000000000045509b67ea511e46","decoded":null},{"block_signed_at":"2021-09-07T09:19:57Z","block_height":69283594,"tx_offset":0,"log_offset":4,"tx_hash":"0x358ea1e3feb972a1755807edb168f2ce5fa470b83a81f4f08d5a41bd7ccdc211","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000326bfd6edbaf034f6b34000000000000000000000000000000000000000000003d520a6bd1e0be791778d","decoded":null},{"block_signed_at":"2021-09-07T09:19:57Z","block_height":69283594,"tx_offset":0,"log_offset":5,"tx_hash":"0x358ea1e3feb972a1755807edb168f2ce5fa470b83a81f4f08d5a41bd7ccdc211","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008387470a5e7c9ab64f","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2426271244975351707215"}]}},{"block_signed_at":"2021-09-07T09:19:57Z","block_height":69283594,"tx_offset":0,"log_offset":6,"tx_hash":"0x358ea1e3feb972a1755807edb168f2ce5fa470b83a81f4f08d5a41bd7ccdc211","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008387470a5e7c9ab64f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2426271244975351707215"}]}}]},{"block_signed_at":"2021-09-07T09:20:26Z","block_height":69283623,"tx_hash":"0xdda84c68de0df924c4a043832cc53cfa3f51f15adce008582a4658c9ba822b9b","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77293,"gas_spent":51529,"gas_price":25000000000,"fees_paid":"1288225000000000","gas_quote":0.002122959635296464,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T09:20:26Z","block_height":69283623,"tx_offset":2,"log_offset":14,"tx_hash":"0xdda84c68de0df924c4a043832cc53cfa3f51f15adce008582a4658c9ba822b9b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000834c0087b1ac180000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2422000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T09:22:07Z","block_height":69283724,"tx_hash":"0x523b8327dcad6bb9ae0e200ac81002a002ef04ec374c0f58e9c7107dc72205c3","tx_offset":8,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":0,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8daea5ef5ad72b64f","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000271244975351707215"}]}},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":1,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffc9d0b47e8d66af0bdd7","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564023465069770272326860247"}]}},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":2,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8daea5ef5ad72b64f","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000271244975351707215"}]}},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":3,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8daea5ef5ad72b64f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b57e6e215acb2d8e67","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000271244975351707215"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3347970933111485468263"}]}},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":4,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005345ba4122f2bb68","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000406867463027560"}]}},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":5,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005345ba4122f2bb69","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000406867463027561"}]}},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":6,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005345ba4122f2bb6900000000000000000000000000000000000000000000000278409a10cc83c4d000000000000000000000000000000000000000000000000278409c65c64149bf","decoded":null},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":7,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032ecb4341d6d3d227733700000000000000000000000000000000000000000003cb77c8ec3894203d0f1a","decoded":null},{"block_signed_at":"2021-09-07T09:29:26Z","block_height":69284163,"tx_offset":1,"log_offset":8,"tx_hash":"0x1afb458a663cd755a623bd8c4ab33f5b910786cc7e7c0d26bf489cdc02bee516","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8daea5ef5ad72b64f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b57e6e215acb2d8e67","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000271244975351707215"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3347970933111485468263"}]}}]},{"block_signed_at":"2021-09-07T09:31:40Z","block_height":69284297,"tx_hash":"0x6cce7c881e11ce4e21df63b6883502aa7667268b3852a129bec48b2b194c5ea5","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3348000000000000000000","value_quote":5517.412609577179,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T09:32:23Z","block_height":69284340,"tx_hash":"0xadccee261eb9fce3d27176460de0774a00ebeef180b318513c8e954dda8a78c4","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T09:32:23Z","block_height":69284340,"tx_offset":1,"log_offset":0,"tx_hash":"0xadccee261eb9fce3d27176460de0774a00ebeef180b318513c8e954dda8a78c4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","tx_offset":10,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":58,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":59,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffbc46ba40c8d8e00bdd7","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564019469069770272326860247"}]}},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":60,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":61,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b83c5c9c4574f8f50f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3398550432724819703055"}]}},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":62,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":63,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":64,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027840a56e29d0af020000000000000000000000000000000000000000000000027840a7b66d828d9d","decoded":null},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":65,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000336dc59b606bd27c2099200000000000000000000000000000000000000000003c574fd016744b120adb0","decoded":null},{"block_signed_at":"2021-09-07T09:45:18Z","block_height":69285115,"tx_offset":10,"log_offset":66,"tx_hash":"0x26a0a3d75b508ae2f144c8b0003abfbb80997c42f4a44d550560ea25198ee984","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b83c5c9c4574f8f50f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3398550432724819703055"}]}}]},{"block_signed_at":"2021-09-07T09:46:19Z","block_height":69285176,"tx_hash":"0xcbda8603786c1364d4cd448c9ff6c07b60b29191ddef82cd4ae80a33ce68c737","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3399000000000000000000","value_quote":5601.459217429162,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T09:50:20Z","block_height":69285417,"tx_hash":"0x326c0b72ba24219e826f3ea08a85c844ed4da84ad9fdbad4bacac0ab94b2a6ff","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T09:50:20Z","block_height":69285417,"tx_offset":6,"log_offset":31,"tx_hash":"0x326c0b72ba24219e826f3ea08a85c844ed4da84ad9fdbad4bacac0ab94b2a6ff","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T10:08:28Z","block_height":69286505,"tx_hash":"0x9903ef3022872a69745d57712cf481f7e563b62df6a54a67959c3e8fc8bb96a6","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":48546,"gas_spent":32364,"gas_price":25000000000,"fees_paid":"809100000000000","gas_quote":0.0013333747139811516,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T10:08:28Z","block_height":69286505,"tx_offset":2,"log_offset":4,"tx_hash":"0x9903ef3022872a69745d57712cf481f7e563b62df6a54a67959c3e8fc8bb96a6","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564039457584007913129639935"}]}}]},{"block_signed_at":"2021-09-07T10:14:32Z","block_height":69286869,"tx_hash":"0x0fdd387ae4506dcb04584f33fc5f0204e807fd71a497cfc2fcbe1e886966d941","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T10:14:32Z","block_height":69286869,"tx_offset":4,"log_offset":0,"tx_hash":"0x0fdd387ae4506dcb04584f33fc5f0204e807fd71a497cfc2fcbe1e886966d941","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008258ee6227b641deb7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2404484896824737521335"}]}},{"block_signed_at":"2021-09-07T10:14:32Z","block_height":69286869,"tx_offset":4,"log_offset":1,"tx_hash":"0x0fdd387ae4506dcb04584f33fc5f0204e807fd71a497cfc2fcbe1e886966d941","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008258ee6227b641deb7","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2404484896824737521335"}]}},{"block_signed_at":"2021-09-07T10:14:32Z","block_height":69286869,"tx_offset":4,"log_offset":2,"tx_hash":"0x0fdd387ae4506dcb04584f33fc5f0204e807fd71a497cfc2fcbe1e886966d941","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T10:14:32Z","block_height":69286869,"tx_offset":4,"log_offset":3,"tx_hash":"0x0fdd387ae4506dcb04584f33fc5f0204e807fd71a497cfc2fcbe1e886966d941","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004550e62f024afdb00000000000000000000000000000000000000000000000004550e735faf6b5bd","decoded":null},{"block_signed_at":"2021-09-07T10:14:32Z","block_height":69286869,"tx_offset":4,"log_offset":4,"tx_hash":"0x0fdd387ae4506dcb04584f33fc5f0204e807fd71a497cfc2fcbe1e886966d941","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032b17a65c2a42f46a2a3100000000000000000000000000000000000000000003d18e01b678544181790b","decoded":null},{"block_signed_at":"2021-09-07T10:14:32Z","block_height":69286869,"tx_offset":4,"log_offset":5,"tx_hash":"0x0fdd387ae4506dcb04584f33fc5f0204e807fd71a497cfc2fcbe1e886966d941","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008258ee6227b641deb7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2404484896824737521335"}]}},{"block_signed_at":"2021-09-07T10:14:32Z","block_height":69286869,"tx_offset":4,"log_offset":6,"tx_hash":"0x0fdd387ae4506dcb04584f33fc5f0204e807fd71a497cfc2fcbe1e886966d941","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008258ee6227b641deb7","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2404484896824737521335"}]}}]},{"block_signed_at":"2021-09-07T10:14:51Z","block_height":69286888,"tx_hash":"0x2e71584986b5d506c9774a0a3f79ec94d7434db3ae6f5c7518e2568469ca0085","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T10:14:51Z","block_height":69286888,"tx_offset":6,"log_offset":19,"tx_hash":"0x2e71584986b5d506c9774a0a3f79ec94d7434db3ae6f5c7518e2568469ca0085","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000821ab0d44149800000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2400000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T10:16:27Z","block_height":69286984,"tx_hash":"0x6d022fa9351b6ee572004fc08bc80781cc546cbd587cd468f847ac64dc0f67b7","tx_offset":0,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T10:23:09Z","block_height":69287386,"tx_hash":"0xece8d5af472ebaa374329cbb0c17709376ee031db57d607491284e999e1c5f5d","tx_offset":8,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":247544,"gas_price":25000000000,"fees_paid":"6188600000000000","gas_quote":0.010198643869662285,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T10:23:09Z","block_height":69287386,"tx_offset":8,"log_offset":12,"tx_hash":"0xece8d5af472ebaa374329cbb0c17709376ee031db57d607491284e999e1c5f5d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000083d2748db9420a4cc6","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2431688375328031001798"}]}},{"block_signed_at":"2021-09-07T10:23:09Z","block_height":69287386,"tx_offset":8,"log_offset":13,"tx_hash":"0xece8d5af472ebaa374329cbb0c17709376ee031db57d607491284e999e1c5f5d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000083d2748db9420a4cc6","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2431688375328031001798"}]}},{"block_signed_at":"2021-09-07T10:23:09Z","block_height":69287386,"tx_offset":8,"log_offset":14,"tx_hash":"0xece8d5af472ebaa374329cbb0c17709376ee031db57d607491284e999e1c5f5d","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T10:23:09Z","block_height":69287386,"tx_offset":8,"log_offset":15,"tx_hash":"0xece8d5af472ebaa374329cbb0c17709376ee031db57d607491284e999e1c5f5d","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004550e9796e29fe090000000000000000000000000000000000000000000000004550ea87fdc14ef4","decoded":null},{"block_signed_at":"2021-09-07T10:23:09Z","block_height":69287386,"tx_offset":8,"log_offset":16,"tx_hash":"0xece8d5af472ebaa374329cbb0c17709376ee031db57d607491284e999e1c5f5d","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000325ca88d004d2cb1a399c00000000000000000000000000000000000000000003d62648e3c7aa4c46e858","decoded":null},{"block_signed_at":"2021-09-07T10:23:09Z","block_height":69287386,"tx_offset":8,"log_offset":17,"tx_hash":"0xece8d5af472ebaa374329cbb0c17709376ee031db57d607491284e999e1c5f5d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000083d2748db9420a4cc6","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2431688375328031001798"}]}},{"block_signed_at":"2021-09-07T10:23:09Z","block_height":69287386,"tx_offset":8,"log_offset":18,"tx_hash":"0xece8d5af472ebaa374329cbb0c17709376ee031db57d607491284e999e1c5f5d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000083d2748db9420a4cc6","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2431688375328031001798"}]}}]},{"block_signed_at":"2021-09-07T10:23:26Z","block_height":69287403,"tx_hash":"0xe9407c1c37cbbf96177458fff7a1d8630a22f802fb34873c8c2aa339071df15c","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77293,"gas_spent":51529,"gas_price":25000000000,"fees_paid":"1288225000000000","gas_quote":0.002122959635296464,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T10:23:26Z","block_height":69287403,"tx_offset":3,"log_offset":2,"tx_hash":"0xe9407c1c37cbbf96177458fff7a1d8630a22f802fb34873c8c2aa339071df15c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000083d6c7aab636000000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2432000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T10:28:22Z","block_height":69287699,"tx_hash":"0xd3a19f2cbe413f30ba258600ad8bbbdce2626b1d7cba8f1eee94d6e535e5893c","tx_offset":9,"successful":true,"from_address":"0x4496f06d8bb0b234057f35c4568aa0c2b0e949f3","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2001000000000000000000","value_quote":3297.593378663063,"gas_offered":1000000,"gas_spent":31000,"gas_price":25000000000,"fees_paid":"775000000000000","gas_quote":0.0012771788448095321,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":444250,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":37,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8d98e4d3255bc2b7d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000173272152768523133"}]}},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":38,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffff272671b2cdaa43d482","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564035457410735760361116802"}]}},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":39,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8d98e4d3255bc2b7d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000173272152768523133"}]}},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":40,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8d98e4d3255bc2b7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b280c66a3e51b2a2b6","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000173272152768523133"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3292799666018434851510"}]}},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":41,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005345349886044010","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000259908229152784"}]}},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":42,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005345349886044011","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000259908229152785"}]}},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":43,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000053453498860440110000000000000000000000000000000000000000000000027840e3801ec213850000000000000000000000000000000000000000000000027840e58c08621441","decoded":null},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":44,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003284d499f9025252d23e500000000000000000000000000000000000000000003d3d7f2816595689ff248","decoded":null},{"block_signed_at":"2021-09-07T10:33:02Z","block_height":69287979,"tx_offset":5,"log_offset":45,"tx_hash":"0x4161c1294b5aece26c06c56aeb49e7a8402d4debfdd27e86b3d7db217fc2e864","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8d98e4d3255bc2b7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b280c66a3e51b2a2b6","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000173272152768523133"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3292799666018434851510"}]}}]},{"block_signed_at":"2021-09-07T10:33:50Z","block_height":69288027,"tx_hash":"0xc417d01d2bff807756a1c5d281c118e5da75f9be646272dde15ae4327723622c","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3294000000000000000000","value_quote":5428.422083616257,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T10:38:11Z","block_height":69288288,"tx_hash":"0xb0b2f02b735f92af7b89199f84fe4480ffef0ebe7b3398edbd0ee6d1498573b3","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T10:38:11Z","block_height":69288288,"tx_offset":0,"log_offset":0,"tx_hash":"0xb0b2f02b735f92af7b89199f84fe4480ffef0ebe7b3398edbd0ee6d1498573b3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000cd30232c56da040000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3785051200000000000000"}]}}]},{"block_signed_at":"2021-09-07T10:59:49Z","block_height":69289586,"tx_hash":"0x6b4f0d4d630084dabffcb0bc1fcc2ed52ca62bae8e19aab9bd42e6f32b8d3d1e","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T10:59:49Z","block_height":69289586,"tx_offset":2,"log_offset":2,"tx_hash":"0x6b4f0d4d630084dabffcb0bc1fcc2ed52ca62bae8e19aab9bd42e6f32b8d3d1e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007f9956f0e11686c6a5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2353785780946449385125"}]}},{"block_signed_at":"2021-09-07T10:59:49Z","block_height":69289586,"tx_offset":2,"log_offset":3,"tx_hash":"0x6b4f0d4d630084dabffcb0bc1fcc2ed52ca62bae8e19aab9bd42e6f32b8d3d1e","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007f9956f0e11686c6a5","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2353785780946449385125"}]}},{"block_signed_at":"2021-09-07T10:59:49Z","block_height":69289586,"tx_offset":2,"log_offset":4,"tx_hash":"0x6b4f0d4d630084dabffcb0bc1fcc2ed52ca62bae8e19aab9bd42e6f32b8d3d1e","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T10:59:49Z","block_height":69289586,"tx_offset":2,"log_offset":5,"tx_hash":"0x6b4f0d4d630084dabffcb0bc1fcc2ed52ca62bae8e19aab9bd42e6f32b8d3d1e","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455111b2d334798b000000000000000000000000000000000000000000000000455112c2f8c7fcb1","decoded":null},{"block_signed_at":"2021-09-07T10:59:49Z","block_height":69289586,"tx_offset":2,"log_offset":6,"tx_hash":"0x6b4f0d4d630084dabffcb0bc1fcc2ed52ca62bae8e19aab9bd42e6f32b8d3d1e","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033367aa25d62cfdd3996900000000000000000000000000000000000000000003c6c153303c082ced645b","decoded":null},{"block_signed_at":"2021-09-07T10:59:49Z","block_height":69289586,"tx_offset":2,"log_offset":7,"tx_hash":"0x6b4f0d4d630084dabffcb0bc1fcc2ed52ca62bae8e19aab9bd42e6f32b8d3d1e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007f9956f0e11686c6a5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2353785780946449385125"}]}},{"block_signed_at":"2021-09-07T10:59:49Z","block_height":69289586,"tx_offset":2,"log_offset":8,"tx_hash":"0x6b4f0d4d630084dabffcb0bc1fcc2ed52ca62bae8e19aab9bd42e6f32b8d3d1e","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007f9956f0e11686c6a5","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2353785780946449385125"}]}}]},{"block_signed_at":"2021-09-07T11:00:17Z","block_height":69289614,"tx_hash":"0x58344b407673a532f30a1149c9181f54f93555f40aa752f1005401e52e937798","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:00:17Z","block_height":69289614,"tx_offset":1,"log_offset":17,"tx_hash":"0x58344b407673a532f30a1149c9181f54f93555f40aa752f1005401e52e937798","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007f8e6f49458e240000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2353000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T11:00:54Z","block_height":69289651,"tx_hash":"0x622bc2b6bac4d091012b56b7684a6517f1354b18a2f046f0672000f43eac22af","tx_offset":7,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T11:03:45Z","block_height":69289822,"tx_hash":"0xd13ac15bb8c2eef8125e3a515b50f9ffed83804bcb87bd9240ed4253e846c9ff","tx_offset":10,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:03:45Z","block_height":69289822,"tx_offset":10,"log_offset":19,"tx_hash":"0xd13ac15bb8c2eef8125e3a515b50f9ffed83804bcb87bd9240ed4253e846c9ff","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007d23aaf4ae9ed23487","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2308413144781888304263"}]}},{"block_signed_at":"2021-09-07T11:03:45Z","block_height":69289822,"tx_offset":10,"log_offset":20,"tx_hash":"0xd13ac15bb8c2eef8125e3a515b50f9ffed83804bcb87bd9240ed4253e846c9ff","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007d23aaf4ae9ed23487","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2308413144781888304263"}]}},{"block_signed_at":"2021-09-07T11:03:45Z","block_height":69289822,"tx_offset":10,"log_offset":21,"tx_hash":"0xd13ac15bb8c2eef8125e3a515b50f9ffed83804bcb87bd9240ed4253e846c9ff","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T11:03:45Z","block_height":69289822,"tx_offset":10,"log_offset":22,"tx_hash":"0xd13ac15bb8c2eef8125e3a515b50f9ffed83804bcb87bd9240ed4253e846c9ff","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455125ea92c8c08d000000000000000000000000000000000000000000000000455126fa3555e5bf","decoded":null},{"block_signed_at":"2021-09-07T11:03:45Z","block_height":69289822,"tx_offset":10,"log_offset":23,"tx_hash":"0xd13ac15bb8c2eef8125e3a515b50f9ffed83804bcb87bd9240ed4253e846c9ff","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033b6aa199794a86ba2a6f00000000000000000000000000000000000000000003bd64f8aa22e08afda7a4","decoded":null},{"block_signed_at":"2021-09-07T11:03:45Z","block_height":69289822,"tx_offset":10,"log_offset":24,"tx_hash":"0xd13ac15bb8c2eef8125e3a515b50f9ffed83804bcb87bd9240ed4253e846c9ff","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007d23aaf4ae9ed23487","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2308413144781888304263"}]}},{"block_signed_at":"2021-09-07T11:03:45Z","block_height":69289822,"tx_offset":10,"log_offset":25,"tx_hash":"0xd13ac15bb8c2eef8125e3a515b50f9ffed83804bcb87bd9240ed4253e846c9ff","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007d23aaf4ae9ed23487","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2308413144781888304263"}]}}]},{"block_signed_at":"2021-09-07T11:04:04Z","block_height":69289841,"tx_hash":"0x24da898f1082f302f66fc163053919a376651238c64f70ae8724e5f079247a4e","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:04:04Z","block_height":69289841,"tx_offset":3,"log_offset":3,"tx_hash":"0x24da898f1082f302f66fc163053919a376651238c64f70ae8724e5f079247a4e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007d2bcfe264c8f40000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2309000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T11:06:17Z","block_height":69289974,"tx_hash":"0x644a6895fb7536b4775a1369917c1e23bc6f202dd686f5103b0e69b399acfd35","tx_offset":3,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T11:07:02Z","block_height":69290019,"tx_hash":"0x1e7d45fd5d0bf360d8b7298c7d4e5cc9d3aef0686058ed212c79bf2ce190efa1","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:07:02Z","block_height":69290019,"tx_offset":4,"log_offset":22,"tx_hash":"0x1e7d45fd5d0bf360d8b7298c7d4e5cc9d3aef0686058ed212c79bf2ce190efa1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007a90ea40a5917eb7e8","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2260945006758431995880"}]}},{"block_signed_at":"2021-09-07T11:07:02Z","block_height":69290019,"tx_offset":4,"log_offset":23,"tx_hash":"0x1e7d45fd5d0bf360d8b7298c7d4e5cc9d3aef0686058ed212c79bf2ce190efa1","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007a90ea40a5917eb7e8","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2260945006758431995880"}]}},{"block_signed_at":"2021-09-07T11:07:02Z","block_height":69290019,"tx_offset":4,"log_offset":24,"tx_hash":"0x1e7d45fd5d0bf360d8b7298c7d4e5cc9d3aef0686058ed212c79bf2ce190efa1","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T11:07:02Z","block_height":69290019,"tx_offset":4,"log_offset":25,"tx_hash":"0x1e7d45fd5d0bf360d8b7298c7d4e5cc9d3aef0686058ed212c79bf2ce190efa1","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045513b8ec569502a00000000000000000000000000000000000000000000000045513c9d11ac41a8","decoded":null},{"block_signed_at":"2021-09-07T11:07:02Z","block_height":69290019,"tx_offset":4,"log_offset":26,"tx_hash":"0x1e7d45fd5d0bf360d8b7298c7d4e5cc9d3aef0686058ed212c79bf2ce190efa1","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003440e106974b8883e125600000000000000000000000000000000000000000003b38095f3e780ada0a295","decoded":null},{"block_signed_at":"2021-09-07T11:07:02Z","block_height":69290019,"tx_offset":4,"log_offset":27,"tx_hash":"0x1e7d45fd5d0bf360d8b7298c7d4e5cc9d3aef0686058ed212c79bf2ce190efa1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007a90ea40a5917eb7e8","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2260945006758431995880"}]}},{"block_signed_at":"2021-09-07T11:07:02Z","block_height":69290019,"tx_offset":4,"log_offset":28,"tx_hash":"0x1e7d45fd5d0bf360d8b7298c7d4e5cc9d3aef0686058ed212c79bf2ce190efa1","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007a90ea40a5917eb7e8","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2260945006758431995880"}]}}]},{"block_signed_at":"2021-09-07T11:07:23Z","block_height":69290040,"tx_hash":"0xc07746e5280187a2cf1b0aabc95c0e9b07dc645bcd90cc24161110a10304365f","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:07:23Z","block_height":69290040,"tx_offset":7,"log_offset":5,"tx_hash":"0xc07746e5280187a2cf1b0aabc95c0e9b07dc645bcd90cc24161110a10304365f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007ad7113237ab280000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2266000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T11:14:13Z","block_height":69290450,"tx_hash":"0x750dc3137adbc783bc240fcbe3cc3d013e0db5606b267b52d40bca0ab2a6cab7","tx_offset":2,"successful":true,"from_address":"0x4496f06d8bb0b234057f35c4568aa0c2b0e949f3","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2001000000000000000000","value_quote":3297.593378663063,"gas_offered":1000000,"gas_spent":31000,"gas_price":25000000000,"fees_paid":"775000000000000","gas_quote":0.0012771788448095321,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T11:14:58Z","block_height":69290495,"tx_hash":"0x4595d36d6235f53ece5742968fcfe4ddb6f91606340eb5a35360907cf7d338ce","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:14:58Z","block_height":69290495,"tx_offset":2,"log_offset":0,"tx_hash":"0x4595d36d6235f53ece5742968fcfe4ddb6f91606340eb5a35360907cf7d338ce","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000078992999f1284a665c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2224645810468036437596"}]}},{"block_signed_at":"2021-09-07T11:14:58Z","block_height":69290495,"tx_offset":2,"log_offset":1,"tx_hash":"0x4595d36d6235f53ece5742968fcfe4ddb6f91606340eb5a35360907cf7d338ce","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000078992999f1284a665c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2224645810468036437596"}]}},{"block_signed_at":"2021-09-07T11:14:58Z","block_height":69290495,"tx_offset":2,"log_offset":2,"tx_hash":"0x4595d36d6235f53ece5742968fcfe4ddb6f91606340eb5a35360907cf7d338ce","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T11:14:58Z","block_height":69290495,"tx_offset":2,"log_offset":3,"tx_hash":"0x4595d36d6235f53ece5742968fcfe4ddb6f91606340eb5a35360907cf7d338ce","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045514ebb73a215d400000000000000000000000000000000000000000000000045514fc9505c4d54","decoded":null},{"block_signed_at":"2021-09-07T11:14:58Z","block_height":69290495,"tx_offset":2,"log_offset":4,"tx_hash":"0x4595d36d6235f53ece5742968fcfe4ddb6f91606340eb5a35360907cf7d338ce","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033914ce0a63b6975f6eb400000000000000000000000000000000000000000003980c195e2e11e59ef636","decoded":null},{"block_signed_at":"2021-09-07T11:14:58Z","block_height":69290495,"tx_offset":2,"log_offset":5,"tx_hash":"0x4595d36d6235f53ece5742968fcfe4ddb6f91606340eb5a35360907cf7d338ce","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000078992999f1284a665c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2224645810468036437596"}]}},{"block_signed_at":"2021-09-07T11:14:58Z","block_height":69290495,"tx_offset":2,"log_offset":6,"tx_hash":"0x4595d36d6235f53ece5742968fcfe4ddb6f91606340eb5a35360907cf7d338ce","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000078992999f1284a665c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2224645810468036437596"}]}}]},{"block_signed_at":"2021-09-07T11:15:15Z","block_height":69290512,"tx_hash":"0x45aa6a95da115cb9a473bf207755adf6bfaaece46e40225b4044de3d883b6e25","tx_offset":11,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:15:15Z","block_height":69290512,"tx_offset":11,"log_offset":0,"tx_hash":"0x45aa6a95da115cb9a473bf207755adf6bfaaece46e40225b4044de3d883b6e25","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000078abf4a62583880000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2226000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T11:16:17Z","block_height":69290574,"tx_hash":"0x44b205b62bdf37fc3d0f639465c2e8c6a256ef2821a012cd8cad1fcf74f5a8ab","tx_offset":3,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T11:19:28Z","block_height":69290765,"tx_hash":"0x0c5a5b40c7d79786ba193a3f0f97cb30f5639717005cabb1a3fb969ea0b977f0","tx_offset":0,"successful":false,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":444250,"gas_spent":47565,"gas_price":25000000000,"fees_paid":"1189125000000000","gas_quote":0.001959645540431142,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461139,"gas_spent":291884,"gas_price":25000000000,"fees_paid":"7297100000000000","gas_quote":0.012025421610915661,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":9,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ccd9f3e797747ce000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3778840942000000000000"}]}},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":10,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffe5a4c7dcb3635c6f482","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564031678569793760361116802"}]}},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":11,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ccd9f3e797747ce000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3778840942000000000000"}]}},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":12,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000ccd9f3e797747ce00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b833b0bc1f145b1a48","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3778840942000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3397925593296064420424"}]}},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":13,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000004ea9b5b92feb3200","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5668261413000000000"}]}},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":14,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000004ea9b5b92feb3200","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5668261413000000000"}]}},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":15,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000004ea9b5b92feb32000000000000000000000000000000000000000000000000027840fd3b71ec23ec0000000000000000000000000000000000000000000000027840ff29dbb0dc79","decoded":null},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":16,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033a3ee318f0b2c20df8be0000000000000000000000000000000000000000000394e930bb65f7d8824082","decoded":null},{"block_signed_at":"2021-09-07T11:19:48Z","block_height":69290785,"tx_offset":3,"log_offset":17,"tx_hash":"0x8f1b829e02d1fcde0bdcf041758727a156c51e129f9fa2df31c7c4cc0acaa296","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000ccd9f3e797747ce00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b833b0bc1f145b1a48","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3778840942000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3397925593296064420424"}]}}]},{"block_signed_at":"2021-09-07T11:21:20Z","block_height":69290877,"tx_hash":"0x8baa894148d4a77fa0790b1bba8653be73798a64da4d10d65fef48525aa7a4a9","tx_offset":8,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3399000000000000000000","value_quote":5601.459217429162,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T11:24:15Z","block_height":69291052,"tx_hash":"0xd54aef0d70b9cd65a3c9d779a76b0520c00f46da931a802739f0e95451e23797","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":51137,"gas_price":25000000000,"fees_paid":"1278425000000000","gas_quote":0.0021068095028072592,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:24:15Z","block_height":69291052,"tx_offset":3,"log_offset":0,"tx_hash":"0xd54aef0d70b9cd65a3c9d779a76b0520c00f46da931a802739f0e95451e23797","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000001271265d38a294c000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"340194700000000000000"}]}}]},{"block_signed_at":"2021-09-07T11:25:20Z","block_height":69291117,"tx_hash":"0x910077e19fd30a39b3fbde4d3e0fb9ead82ce238ad97c81007b63caee8096c7f","tx_offset":4,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":72290,"gas_spent":41137,"gas_price":25000000000,"fees_paid":"1028425000000000","gas_quote":0.001694816327062249,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:25:20Z","block_height":69291117,"tx_offset":4,"log_offset":6,"tx_hash":"0x910077e19fd30a39b3fbde4d3e0fb9ead82ce238ad97c81007b63caee8096c7f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ca4753ef46f847d1b8e8c20947f6e2e78bc1145e","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c5f9ae5adfee900000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3652000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T11:26:02Z","block_height":69291159,"tx_hash":"0x998d82cccceef349650f1c7a3ff402afbeafa576a4698dc3158d2890dddf1eaa","tx_offset":1,"successful":false,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":47565,"gas_price":25000000000,"fees_paid":"1189125000000000","gas_quote":0.001959645540431142,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":1,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d86ad4b8f6e005f970","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3992194700954806122864"}]}},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":2,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffd81e1a9123f55c0fb12","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564027686375092805554993938"}]}},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":3,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d86ad4b8f6e005f970","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3992194700954806122864"}]}},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":4,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d86ad4b8f6e005f97000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bfc9f455c2f085b861","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3992194700954806122864"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3537880468670212585569"}]}},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":5,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000531aafe4b8e97b20","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5988292051432209184"}]}},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":6,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000531aafe4b8e97b20","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5988292051432209184"}]}},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":7,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000531aafe4b8e97b2000000000000000000000000000000000000000000000000278411295077907120000000000000000000000000000000000000000000000027841149e5a328510","decoded":null},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":8,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000331c5c48220cb8453ce220000000000000000000000000000000000000000000398dc53c588e0aba40a7a","decoded":null},{"block_signed_at":"2021-09-07T11:26:10Z","block_height":69291167,"tx_offset":1,"log_offset":9,"tx_hash":"0xcb356c85feee54e3c5fd5bdcb6812087fa139eaa8589c8b69a8a01e00a121196","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d86ad4b8f6e005f97000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bfc9f455c2f085b861","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3992194700954806122864"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3537880468670212585569"}]}}]},{"block_signed_at":"2021-09-07T11:26:31Z","block_height":69291188,"tx_hash":"0x37e38199c299d200fcfa045b525fe0c84746a64d037b368b3edd926da4d517ec","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3537000000000000000000","value_quote":5828.879450440406,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T11:28:10Z","block_height":69291287,"tx_hash":"0x79b5d21d2d614ceef01f986b4741a9c5cc07c7d6426019f365ffd0d50cbc0d14","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:28:10Z","block_height":69291287,"tx_offset":3,"log_offset":7,"tx_hash":"0x79b5d21d2d614ceef01f986b4741a9c5cc07c7d6426019f365ffd0d50cbc0d14","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000005a91281521059e8000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"1670666600000000000000"}]}}]},{"block_signed_at":"2021-09-07T11:34:09Z","block_height":69291646,"tx_hash":"0xf76193ae49b7eb44540059b140662d07f5f6f5fbb37be3c00fbb8230587fc286","tx_offset":4,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":72418,"gas_spent":41137,"gas_price":25000000000,"fees_paid":"1028425000000000","gas_quote":0.001694816327062249,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T11:34:09Z","block_height":69291646,"tx_offset":4,"log_offset":2,"tx_hash":"0xf76193ae49b7eb44540059b140662d07f5f6f5fbb37be3c00fbb8230587fc286","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000ca4753ef46f847d1b8e8c20947f6e2e78bc1145e","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007e17bc0452e6980000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2326000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":444154,"gas_spent":288030,"gas_price":25000000000,"fees_paid":"7200750000000000","gas_quote":0.011866639440983533,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":0,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a8e41973ec368000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996666600000000000000"}]}},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":1,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffca938c4f8cb698a7b12","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564023689708492805554993938"}]}},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":2,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a8e41973ec368000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996666600000000000000"}]}},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":3,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8a8e41973ec36800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cecc6f320d648c0e26","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996666600000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3814760327123422678566"}]}},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":4,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000533284a56c009800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994999900000000000"}]}},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":5,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000533284a56c009800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994999900000000000"}]}},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":6,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000533284a56c00980000000000000000000000000000000000000000000000000278414411165e57c0000000000000000000000000000000000000000000000002784145ced77481c7","decoded":null},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":7,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003501b75c6250d12d5c9f20000000000000000000000000000000000000000000376ba2ea1a3d691d98ad3","decoded":null},{"block_signed_at":"2021-09-07T12:22:58Z","block_height":69294575,"tx_offset":0,"log_offset":8,"tx_hash":"0x9131a3a58dc513a980eff2e7e75c133cc2006e24e385fde32767d85577bf9e3f","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8a8e41973ec36800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cecc6f320d648c0e26","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996666600000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3814760327123422678566"}]}}]},{"block_signed_at":"2021-09-07T12:25:56Z","block_height":69294753,"tx_hash":"0x864a9e91d4318ed7158d65ece3049889aaf83b4a6ffacc36ba5656148b37c227","tx_offset":13,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3815000000000000000000","value_quote":6287.015861868859,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T12:27:37Z","block_height":69294854,"tx_hash":"0x367270214c6330ddbf568fb41c9a2a8965097e7aba14f7c953ccf56044f03038","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.01127584122696519,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:27:37Z","block_height":69294854,"tx_offset":0,"log_offset":0,"tx_hash":"0x367270214c6330ddbf568fb41c9a2a8965097e7aba14f7c953ccf56044f03038","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000006e88b252f6b2374e5a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2038991874662568775258"}]}},{"block_signed_at":"2021-09-07T12:27:37Z","block_height":69294854,"tx_offset":0,"log_offset":1,"tx_hash":"0x367270214c6330ddbf568fb41c9a2a8965097e7aba14f7c953ccf56044f03038","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000006e88b252f6b2374e5a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2038991874662568775258"}]}},{"block_signed_at":"2021-09-07T12:27:37Z","block_height":69294854,"tx_offset":0,"log_offset":2,"tx_hash":"0x367270214c6330ddbf568fb41c9a2a8965097e7aba14f7c953ccf56044f03038","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T12:27:37Z","block_height":69294854,"tx_offset":0,"log_offset":3,"tx_hash":"0x367270214c6330ddbf568fb41c9a2a8965097e7aba14f7c953ccf56044f03038","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004551ee9d85ee0fd40000000000000000000000000000000000000000000000004551ef7bd08e426c","decoded":null},{"block_signed_at":"2021-09-07T12:27:37Z","block_height":69294854,"tx_offset":0,"log_offset":4,"tx_hash":"0x367270214c6330ddbf568fb41c9a2a8965097e7aba14f7c953ccf56044f03038","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000035640cf16859e0e6e2e99000000000000000000000000000000000000000000036918b01d3ec766471547","decoded":null},{"block_signed_at":"2021-09-07T12:27:37Z","block_height":69294854,"tx_offset":0,"log_offset":5,"tx_hash":"0x367270214c6330ddbf568fb41c9a2a8965097e7aba14f7c953ccf56044f03038","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000006e88b252f6b2374e5a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2038991874662568775258"}]}},{"block_signed_at":"2021-09-07T12:27:37Z","block_height":69294854,"tx_offset":0,"log_offset":6,"tx_hash":"0x367270214c6330ddbf568fb41c9a2a8965097e7aba14f7c953ccf56044f03038","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000006e88b252f6b2374e5a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2038991874662568775258"}]}}]},{"block_signed_at":"2021-09-07T12:27:59Z","block_height":69294876,"tx_hash":"0x9d8da5d2fd7d19ba5a45f715823707bd06f7013977e970674d2b0fcfad9a4098","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77581,"gas_spent":36721,"gas_price":25000000000,"fees_paid":"918025000000000","gas_quote":0.0015128801406532526,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:27:59Z","block_height":69294876,"tx_offset":3,"log_offset":0,"tx_hash":"0x9d8da5d2fd7d19ba5a45f715823707bd06f7013977e970674d2b0fcfad9a4098","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000006e88b252f6b2374e5a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2038991874662568775258"}]}}]},{"block_signed_at":"2021-09-07T12:29:10Z","block_height":69294947,"tx_hash":"0x73fb0ee9d12cce96d71cbfbacf53b8c7f60bf44459b9967a24beb38824d60498","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:29:10Z","block_height":69294947,"tx_offset":1,"log_offset":0,"tx_hash":"0x73fb0ee9d12cce96d71cbfbacf53b8c7f60bf44459b9967a24beb38824d60498","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T12:29:20Z","block_height":69294957,"tx_hash":"0xdae867060794e5dc8003e8b3747992140f8c794abe6c734755ef4ea3a2671c7c","tx_offset":8,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":0,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":1,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffbd099211c828c9a7b12","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564019693708492805554993938"}]}},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":2,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":3,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d129a9ac65e5093e19","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3858371631585549696537"}]}},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":4,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":5,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":6,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278416f1806ceee23000000000000000000000000000000000000000000000002784170cd92b513e0","decoded":null},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":7,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003515647923b7ce30355a9000000000000000000000000000000000000000000036dd6728ef629d5bc1556","decoded":null},{"block_signed_at":"2021-09-07T12:30:26Z","block_height":69295023,"tx_offset":4,"log_offset":8,"tx_hash":"0x591fa5e20c61238de802ceb7b49316e85b4237479e62412c252fd7db11e4a33e","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d129a9ac65e5093e19","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3858371631585549696537"}]}}]},{"block_signed_at":"2021-09-07T12:31:25Z","block_height":69295082,"tx_hash":"0xf7aeb16f26c33b61851892ff706a48b71a1f0ff0d53324c2f8e3988d2c087f6e","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3859000000000000000000","value_quote":6359.526660799981,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T12:33:04Z","block_height":69295181,"tx_hash":"0x1754fe2344351576cc881caaf6bc20e74efb9379ab3cca14eb0f9d4f9c67e3f2","tx_offset":6,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"1000000000000000000000","value_quote":1647.9727029800415,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T12:33:28Z","block_height":69295205,"tx_hash":"0x1f87aa9cc01af0d324f8d5f16ddba97cdf75135367a67111cff5b6c37e74359a","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:33:28Z","block_height":69295205,"tx_offset":6,"log_offset":42,"tx_hash":"0x1f87aa9cc01af0d324f8d5f16ddba97cdf75135367a67111cff5b6c37e74359a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000002c469459700005e800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"816742527460000000000"}]}}]},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":276820,"gas_price":25000000000,"fees_paid":"6920500000000000","gas_quote":0.011404795090973377,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":13,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000002c469459700005e800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"816742527460000000000"}]}},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":14,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffba4528cc3128c949312","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564018876965965345554993938"}]}},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":15,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000002c469459700005e800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"816742527460000000000"}]}},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":16,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000002c469459700005e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000292714ca35e3c7f56a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"816742527460000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"759132605021908628842"}]}},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":17,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000011007a808d4fe180","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"1225113791190000000"}]}},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":18,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000011007a808d4fe180","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"1225113791190000000"}]}},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":19,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000011007a808d4fe18000000000000000000000000000000000000000000000000278419513954c7d060000000000000000000000000000000000000000000000027841956acef3608e","decoded":null},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":20,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000351980382bbbc8e23cdd9000000000000000000000000000000000000000000038f7fbcde3ed562bc770e","decoded":null},{"block_signed_at":"2021-09-07T12:33:41Z","block_height":69295218,"tx_offset":4,"log_offset":21,"tx_hash":"0x39b59d86187833f07269fa7090d92e60cf642da84eab5300377769ea3e8f69f1","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000002c469459700005e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000292714ca35e3c7f56a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"816742527460000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"759132605021908628842"}]}}]},{"block_signed_at":"2021-09-07T12:35:11Z","block_height":69295308,"tx_hash":"0x90f8ecf8f83bd5d76f06dc783bf720f7e110e78d8ffc41836e245d318c3ca313","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:35:11Z","block_height":69295308,"tx_offset":3,"log_offset":11,"tx_hash":"0x90f8ecf8f83bd5d76f06dc783bf720f7e110e78d8ffc41836e245d318c3ca313","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ac2f5080cc1668e400","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3176249347210000000000"}]}}]},{"block_signed_at":"2021-09-07T12:36:10Z","block_height":69295367,"tx_hash":"0x43043560562d28e969d2272832ac0c16eea9c939bac0d69332d7f4ce90d189df","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":51137,"gas_price":25000000000,"fees_paid":"1278425000000000","gas_quote":0.0021068095028072592,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:36:10Z","block_height":69295367,"tx_offset":1,"log_offset":0,"tx_hash":"0x43043560562d28e969d2272832ac0c16eea9c939bac0d69332d7f4ce90d189df","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000001df47c96fe8e7dc000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"552572700000000000000"}]}}]},{"block_signed_at":"2021-09-07T12:37:05Z","block_height":69295422,"tx_hash":"0x07317d68d6a5b34e0be596626a694c8df0f9b0b48469403ef1ceeedf5a0ebf5b","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:37:05Z","block_height":69295422,"tx_offset":5,"log_offset":11,"tx_hash":"0x07317d68d6a5b34e0be596626a694c8df0f9b0b48469403ef1ceeedf5a0ebf5b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ab81b61b66b9ed0083","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3163739924809007300739"}]}},{"block_signed_at":"2021-09-07T12:37:05Z","block_height":69295422,"tx_offset":5,"log_offset":12,"tx_hash":"0x07317d68d6a5b34e0be596626a694c8df0f9b0b48469403ef1ceeedf5a0ebf5b","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000ab81b61b66b9ed0083","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3163739924809007300739"}]}},{"block_signed_at":"2021-09-07T12:37:05Z","block_height":69295422,"tx_offset":5,"log_offset":13,"tx_hash":"0x07317d68d6a5b34e0be596626a694c8df0f9b0b48469403ef1ceeedf5a0ebf5b","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T12:37:05Z","block_height":69295422,"tx_offset":5,"log_offset":14,"tx_hash":"0x07317d68d6a5b34e0be596626a694c8df0f9b0b48469403ef1ceeedf5a0ebf5b","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e7336287142000000000000000000000000000000000000000000000000000045522158e11e065100000000000000000000000000000000000000000000000045522295d1cbb72f","decoded":null},{"block_signed_at":"2021-09-07T12:37:05Z","block_height":69295422,"tx_offset":5,"log_offset":15,"tx_hash":"0x07317d68d6a5b34e0be596626a694c8df0f9b0b48469403ef1ceeedf5a0ebf5b","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000356ce02228ded16b3de2c000000000000000000000000000000000000000000038780a479181d3367bbfc","decoded":null},{"block_signed_at":"2021-09-07T12:37:05Z","block_height":69295422,"tx_offset":5,"log_offset":16,"tx_hash":"0x07317d68d6a5b34e0be596626a694c8df0f9b0b48469403ef1ceeedf5a0ebf5b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ab81b61b66b9ed0083","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3163739924809007300739"}]}},{"block_signed_at":"2021-09-07T12:37:05Z","block_height":69295422,"tx_offset":5,"log_offset":17,"tx_hash":"0x07317d68d6a5b34e0be596626a694c8df0f9b0b48469403ef1ceeedf5a0ebf5b","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000ab81b61b66b9ed0083","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3163739924809007300739"}]}}]},{"block_signed_at":"2021-09-07T12:37:23Z","block_height":69295440,"tx_hash":"0x6edeca441c05308746069967503adbb7199d5e8740d0bf666a60bca8340c52fa","tx_offset":13,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:37:23Z","block_height":69295440,"tx_offset":13,"log_offset":74,"tx_hash":"0x6edeca441c05308746069967503adbb7199d5e8740d0bf666a60bca8340c52fa","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000009cc68ff586fdb00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2892000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T12:38:40Z","block_height":69295517,"tx_hash":"0xb1316b34268bb4ff50e3b77aff28f5feee00848a2ecefccb2759261b13c27b67","tx_offset":11,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2300000000000000000000","value_quote":3790.3372168540955,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":8,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8def33daa6123a483","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000561972019007300739"}]}},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":9,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffffacb739985682b70ee8f","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564014876403993326547693199"}]}},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":10,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8def33daa6123a483","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000561972019007300739"}]}},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":11,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8def33daa6123a48300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce874b226b85bba991","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000561972019007300739"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3809778202847741716881"}]}},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":12,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000534746e0623196e7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000842958028510951"}]}},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":13,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000534746e0623196e7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000842958028510951"}]}},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":14,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000534746e0623196e700000000000000000000000000000000000000000000000278419caa3556554700000000000000000000000000000000000000000000000278419e4ddbf54d4c","decoded":null},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":15,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000035929664b56875714d5a200000000000000000000000000000000000000000003823b01be96765ffdf9af","decoded":null},{"block_signed_at":"2021-09-07T12:41:37Z","block_height":69295694,"tx_offset":7,"log_offset":16,"tx_hash":"0x0781bcce4bb7ce53f1cb75dfd3a4e008bc6edeadfe83e3f7443704f8d2212b6c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8def33daa6123a48300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce874b226b85bba991","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000561972019007300739"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3809778202847741716881"}]}}]},{"block_signed_at":"2021-09-07T12:41:56Z","block_height":69295713,"tx_hash":"0xbe79fdbd303172375737e024978224882671479e91db7098aaedd31a5ce247ec","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3868000000000000000000","value_quote":6374.3584151268005,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T12:45:12Z","block_height":69295909,"tx_hash":"0x815896a235ba0796cf69381fdbcf481d3745373c14717a1448471ffe218da89f","tx_offset":9,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:45:12Z","block_height":69295909,"tx_offset":9,"log_offset":4,"tx_hash":"0x815896a235ba0796cf69381fdbcf481d3745373c14717a1448471ffe218da89f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T12:46:52Z","block_height":69296009,"tx_hash":"0x26a6f90fff47d4ceac58a24f548180985bec5bcb5109b5c7bc56f7d87b0d5e57","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:46:52Z","block_height":69296009,"tx_offset":0,"log_offset":0,"tx_hash":"0x26a6f90fff47d4ceac58a24f548180985bec5bcb5109b5c7bc56f7d87b0d5e57","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ab39cf8201994cdc09","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3158558927728052853769"}]}},{"block_signed_at":"2021-09-07T12:46:52Z","block_height":69296009,"tx_offset":0,"log_offset":1,"tx_hash":"0x26a6f90fff47d4ceac58a24f548180985bec5bcb5109b5c7bc56f7d87b0d5e57","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000ab39cf8201994cdc09","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3158558927728052853769"}]}},{"block_signed_at":"2021-09-07T12:46:52Z","block_height":69296009,"tx_offset":0,"log_offset":2,"tx_hash":"0x26a6f90fff47d4ceac58a24f548180985bec5bcb5109b5c7bc56f7d87b0d5e57","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T12:46:52Z","block_height":69296009,"tx_offset":0,"log_offset":3,"tx_hash":"0x26a6f90fff47d4ceac58a24f548180985bec5bcb5109b5c7bc56f7d87b0d5e57","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e73362871420000000000000000000000000000000000000000000000000000455232e666cf04840000000000000000000000000000000000000000000000004552341b4c0c40d4","decoded":null},{"block_signed_at":"2021-09-07T12:46:52Z","block_height":69296009,"tx_offset":0,"log_offset":4,"tx_hash":"0x26a6f90fff47d4ceac58a24f548180985bec5bcb5109b5c7bc56f7d87b0d5e57","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000035480d73efa46d575b9da000000000000000000000000000000000000000000038397b1928618ded963b8","decoded":null},{"block_signed_at":"2021-09-07T12:46:52Z","block_height":69296009,"tx_offset":0,"log_offset":5,"tx_hash":"0x26a6f90fff47d4ceac58a24f548180985bec5bcb5109b5c7bc56f7d87b0d5e57","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ab39cf8201994cdc09","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3158558927728052853769"}]}},{"block_signed_at":"2021-09-07T12:46:52Z","block_height":69296009,"tx_offset":0,"log_offset":6,"tx_hash":"0x26a6f90fff47d4ceac58a24f548180985bec5bcb5109b5c7bc56f7d87b0d5e57","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000ab39cf8201994cdc09","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3158558927728052853769"}]}}]},{"block_signed_at":"2021-09-07T12:47:20Z","block_height":69296037,"tx_hash":"0xdb0205067c184ad3a8db4d9eb81ea115b9a4039cd927485be8a924a4172e6fb5","tx_offset":10,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:47:20Z","block_height":69296037,"tx_offset":10,"log_offset":18,"tx_hash":"0xdb0205067c184ad3a8db4d9eb81ea115b9a4039cd927485be8a924a4172e6fb5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000aafa8af1644e080000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3154000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T12:50:31Z","block_height":69296228,"tx_hash":"0x2ac74871d06e7c689b107dd8d93cd0a1565802f5e4741cfafe42629e681f40ab","tx_offset":5,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":0,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dee86ce62834dc09","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000558927728052853769"}]}},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":1,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff9f294b11882033c1286","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564010875845065598494839430"}]}},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":2,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dee86ce62834dc09","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000558927728052853769"}]}},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":3,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dee86ce62834dc0900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cf886d8b49e6416eeb","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000558927728052853769"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3828306689969008766699"}]}},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":4,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000534742b92d5f4fb0","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000838391592079280"}]}},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":5,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000534742b92d5f4fb1","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000838391592079281"}]}},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":6,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000534742b92d5f4fb10000000000000000000000000000000000000000000000027841b0a0e4d8af780000000000000000000000000000000000000000000000027841b22f7f768504","decoded":null},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":7,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003598bac8ca0e9773db3cd000000000000000000000000000000000000000000037e495ad7a1c3cb01c640","decoded":null},{"block_signed_at":"2021-09-07T12:55:26Z","block_height":69296523,"tx_offset":0,"log_offset":8,"tx_hash":"0x39f888d793ad7b68425e3b05595df4c1134772f626e87b03424756d3dfdef648","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dee86ce62834dc0900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cf886d8b49e6416eeb","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000558927728052853769"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3828306689969008766699"}]}}]},{"block_signed_at":"2021-09-07T12:55:59Z","block_height":69296556,"tx_hash":"0x73c7c58272beef2dbfebb3f9e0dc61a6c04ba8d3e444e80978b3a6400cff2abf","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3829000000000000000000","value_quote":6310.087479710578,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:00:20Z","block_height":69296817,"tx_hash":"0xc8870caef9d18973e5c472b85351929d495a45eee636b734e817987f8e8c0157","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:00:20Z","block_height":69296817,"tx_offset":6,"log_offset":49,"tx_hash":"0xc8870caef9d18973e5c472b85351929d495a45eee636b734e817987f8e8c0157","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000006aa4f845feb9e99c00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"1967242199990000000000"}]}}]},{"block_signed_at":"2021-09-07T13:00:26Z","block_height":69296823,"tx_hash":"0x8be48223d769d87c2e3b67f4acf35e033658cd20d86957f05524e258da715175","tx_offset":10,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":51137,"gas_price":25000000000,"fees_paid":"1278425000000000","gas_quote":0.0021068095028072592,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:00:26Z","block_height":69296823,"tx_offset":10,"log_offset":43,"tx_hash":"0x8be48223d769d87c2e3b67f4acf35e033658cd20d86957f05524e258da715175","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000006dc328bb7b85766400","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2024757800010000000000"}]}}]},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":11,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d86821017a3f600000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3992000000000000000000"}]}},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":12,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff91a2c901707c3dc1286","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564006883845065598494839430"}]}},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":13,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d86821017a3f600000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3992000000000000000000"}]}},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":14,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d86821017a3f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cdbea4c0e9596cf957","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3992000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3795319851982305163607"}]}},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":15,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005319a646330a0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5988000000000000000"}]}},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":16,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005319a646330a0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5988000000000000000"}]}},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":17,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005319a646330a00000000000000000000000000000000000000000000000000027841bd24d14ffaca0000000000000000000000000000000000000000000000027841be8b3fd845fc","decoded":null},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":18,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000352b4defb6556fc1c9a4a000000000000000000000000000000000000000000037cf3375b81e9495c5636","decoded":null},{"block_signed_at":"2021-09-07T13:04:35Z","block_height":69297072,"tx_offset":2,"log_offset":19,"tx_hash":"0x73d5d384468be208333a59fd7f5baf48d1c8d5952983039de90a29414f72b08a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d86821017a3f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cdbea4c0e9596cf957","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3992000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3795319851982305163607"}]}}]},{"block_signed_at":"2021-09-07T13:05:24Z","block_height":69297121,"tx_hash":"0xe99a0e4a1822ee2b8c7cf4ffd665030b5a763966e786270b2bcd6fbdac0f96cd","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3795000000000000000000","value_quote":6254.056407809258,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:08:06Z","block_height":69297283,"tx_hash":"0x303636f50b350068780ca607129c4ddeea6f0d8c26c5d7befa8ad3178eff9f11","tx_offset":4,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:08:06Z","block_height":69297283,"tx_offset":4,"log_offset":9,"tx_hash":"0x303636f50b350068780ca607129c4ddeea6f0d8c26c5d7befa8ad3178eff9f11","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007938bccc35530ce400","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2236144400010000000000"}]}}]},{"block_signed_at":"2021-09-07T13:08:24Z","block_height":69297301,"tx_hash":"0x573ac87dcbc51a80f8d226499b09bbde14ddb27c8a7c4b02b551e843a4a0af53","tx_offset":4,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":51137,"gas_price":25000000000,"fees_paid":"1278425000000000","gas_quote":0.0021068095028072592,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:08:24Z","block_height":69297301,"tx_offset":4,"log_offset":2,"tx_hash":"0x573ac87dcbc51a80f8d226499b09bbde14ddb27c8a7c4b02b551e843a4a0af53","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000005f2f643544ec531c00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"1755855599990000000000"}]}}]},{"block_signed_at":"2021-09-07T13:11:34Z","block_height":69297491,"tx_hash":"0x04e05e59e1c1078a6659419f0403c5d43d864e6500e6a126f0f9947f4c893a24","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:11:34Z","block_height":69297491,"tx_offset":3,"log_offset":1,"tx_hash":"0x04e05e59e1c1078a6659419f0403c5d43d864e6500e6a126f0f9947f4c893a24","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000aea18a8d0ec7f18d52","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3221373740106978004306"}]}},{"block_signed_at":"2021-09-07T13:11:34Z","block_height":69297491,"tx_offset":3,"log_offset":2,"tx_hash":"0x04e05e59e1c1078a6659419f0403c5d43d864e6500e6a126f0f9947f4c893a24","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000aea18a8d0ec7f18d52","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3221373740106978004306"}]}},{"block_signed_at":"2021-09-07T13:11:34Z","block_height":69297491,"tx_offset":3,"log_offset":3,"tx_hash":"0x04e05e59e1c1078a6659419f0403c5d43d864e6500e6a126f0f9947f4c893a24","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T13:11:34Z","block_height":69297491,"tx_offset":3,"log_offset":4,"tx_hash":"0x04e05e59e1c1078a6659419f0403c5d43d864e6500e6a126f0f9947f4c893a24","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e73362871420000000000000000000000000000000000000000000000000000455256b5c73b01c3000000000000000000000000000000000000000000000000455257bf455f40ab","decoded":null},{"block_signed_at":"2021-09-07T13:11:34Z","block_height":69297491,"tx_offset":3,"log_offset":5,"tx_hash":"0x04e05e59e1c1078a6659419f0403c5d43d864e6500e6a126f0f9947f4c893a24","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000343f9363a586d53ccfdfb0000000000000000000000000000000000000000000383ae10c0e54dee744741","decoded":null},{"block_signed_at":"2021-09-07T13:11:34Z","block_height":69297491,"tx_offset":3,"log_offset":6,"tx_hash":"0x04e05e59e1c1078a6659419f0403c5d43d864e6500e6a126f0f9947f4c893a24","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000aea18a8d0ec7f18d52","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3221373740106978004306"}]}},{"block_signed_at":"2021-09-07T13:11:34Z","block_height":69297491,"tx_offset":3,"log_offset":7,"tx_hash":"0x04e05e59e1c1078a6659419f0403c5d43d864e6500e6a126f0f9947f4c893a24","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000aea18a8d0ec7f18d52","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3221373740106978004306"}]}}]},{"block_signed_at":"2021-09-07T13:12:12Z","block_height":69297529,"tx_hash":"0x42089e35c84f4e748c9a52595c251ccad0dc16f6f54278ca10955ba0f591be86","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:12:12Z","block_height":69297529,"tx_offset":2,"log_offset":0,"tx_hash":"0x42089e35c84f4e748c9a52595c251ccad0dc16f6f54278ca10955ba0f591be86","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ae2d550ccbe2140000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3213000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T13:19:44Z","block_height":69297981,"tx_hash":"0x1eaedf81e522f6aca2d9cb69d75a3666d8635214366acf610cba38979c9d711b","tx_offset":0,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":444250,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":34,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dc5681bd253d8d52","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000373740106978004306"}]}},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":35,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff8415039954a9e9e8534","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640564002883471325491516835124"}]}},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":36,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dc5681bd253d8d52","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000373740106978004306"}]}},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":37,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dc5681bd253d8d5200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cf4a307225d0b968da","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000373740106978004306"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3823821921522307131610"}]}},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":38,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005346461525d0dc3e","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000560610160467006"}]}},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":39,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005346461525d0dc3e","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000560610160467006"}]}},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":40,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005346461525d0dc3e0000000000000000000000000000000000000000000000027841e1eaf129ca430000000000000000000000000000000000000000000000027841e34c69b945ae","decoded":null},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":41,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003510bd90f72a1fd9ec5b800000000000000000000000000000000000000000003766d8ab2dd0bb82279b0","decoded":null},{"block_signed_at":"2021-09-07T13:19:53Z","block_height":69297990,"tx_offset":4,"log_offset":42,"tx_hash":"0x2a3fe5a32de1faaa173c506d682c454aa1a0d8c7738210dde24278c0a1d3b437","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dc5681bd253d8d5200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cf4a307225d0b968da","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000373740106978004306"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3823821921522307131610"}]}}]},{"block_signed_at":"2021-09-07T13:21:32Z","block_height":69298089,"tx_hash":"0xb81cf8ee0e9501cbea61abca832ece3aa2e698a7376a4457cc90f7f72157da1b","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3824000000000000000000","value_quote":6301.847616195679,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:23:15Z","block_height":69298192,"tx_hash":"0x52d9882a80d91f25fcf6e7f2121b56f7dc3ccd70b48ceccbd75a9e6b898f22f4","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:23:15Z","block_height":69298192,"tx_offset":6,"log_offset":21,"tx_hash":"0x52d9882a80d91f25fcf6e7f2121b56f7dc3ccd70b48ceccbd75a9e6b898f22f4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000aa01e71a8458390000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3136083600000000000000"}]}}]},{"block_signed_at":"2021-09-07T13:23:21Z","block_height":69298198,"tx_hash":"0x6442b2f82d0bcf2b5a010b3cf3c231a05e3cc19e2f9d27de4a5dcbd39896a801","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":51137,"gas_price":25000000000,"fees_paid":"1278425000000000","gas_quote":0.0021068095028072592,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:23:21Z","block_height":69298198,"tx_offset":3,"log_offset":22,"tx_hash":"0x6442b2f82d0bcf2b5a010b3cf3c231a05e3cc19e2f9d27de4a5dcbd39896a801","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000002e6639e6f5e7270000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"855916400000000000000"}]}}]},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":0,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d86821017a3f600000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3992000000000000000000"}]}},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":1,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff768e81893d05f3e8534","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563998891471325491516835124"}]}},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":2,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d86821017a3f600000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3992000000000000000000"}]}},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":3,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d86821017a3f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce0ac6dc849082c0f2","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3992000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3800805829631853904114"}]}},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":4,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005319a646330a0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5988000000000000000"}]}},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":5,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005319a646330a0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5988000000000000000"}]}},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":6,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005319a646330a00000000000000000000000000000000000000000000000000027841ef227234d2ec0000000000000000000000000000000000000000000000027841f08198b3d8af","decoded":null},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":7,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000034fd184f57b5d3937bd100000000000000000000000000000000000000000000378a35d984b54e7645b57","decoded":null},{"block_signed_at":"2021-09-07T13:25:49Z","block_height":69298346,"tx_offset":0,"log_offset":8,"tx_hash":"0x1ed73099bc42bdadbeb07069d777f20de0e2a1a2f77f0dbef8786c54b84e466c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d86821017a3f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce0ac6dc849082c0f2","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3992000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3800805829631853904114"}]}}]},{"block_signed_at":"2021-09-07T13:26:22Z","block_height":69298379,"tx_hash":"0x3dcde8561a526c63e6a3646b3561c7fdbdad1ea829671428d355ee1635350117","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3801000000000000000000","value_quote":6263.944244027137,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:30:54Z","block_height":69298651,"tx_hash":"0x063e53a1c1e7ed964a0ce65be9bf9402cf70d86a308d6a11315df2c9b5b56173","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.01127584122696519,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:30:54Z","block_height":69298651,"tx_offset":0,"log_offset":0,"tx_hash":"0x063e53a1c1e7ed964a0ce65be9bf9402cf70d86a308d6a11315df2c9b5b56173","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000a68aa1e40662045073","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3072149032400335425651"}]}},{"block_signed_at":"2021-09-07T13:30:54Z","block_height":69298651,"tx_offset":0,"log_offset":1,"tx_hash":"0x063e53a1c1e7ed964a0ce65be9bf9402cf70d86a308d6a11315df2c9b5b56173","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000a68aa1e40662045073","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3072149032400335425651"}]}},{"block_signed_at":"2021-09-07T13:30:54Z","block_height":69298651,"tx_offset":0,"log_offset":2,"tx_hash":"0x063e53a1c1e7ed964a0ce65be9bf9402cf70d86a308d6a11315df2c9b5b56173","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T13:30:54Z","block_height":69298651,"tx_offset":0,"log_offset":3,"tx_hash":"0x063e53a1c1e7ed964a0ce65be9bf9402cf70d86a308d6a11315df2c9b5b56173","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e73362871420000000000000000000000000000000000000000000000000000455299b32befe09c00000000000000000000000000000000000000000000000045529ab3b76727a2","decoded":null},{"block_signed_at":"2021-09-07T13:30:54Z","block_height":69298651,"tx_offset":0,"log_offset":4,"tx_hash":"0x063e53a1c1e7ed964a0ce65be9bf9402cf70d86a308d6a11315df2c9b5b56173","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000365518f5831597deb7be5000000000000000000000000000000000000000000037c40eaefdfac7c7c326e","decoded":null},{"block_signed_at":"2021-09-07T13:30:54Z","block_height":69298651,"tx_offset":0,"log_offset":5,"tx_hash":"0x063e53a1c1e7ed964a0ce65be9bf9402cf70d86a308d6a11315df2c9b5b56173","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000a68aa1e40662045073","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3072149032400335425651"}]}},{"block_signed_at":"2021-09-07T13:30:54Z","block_height":69298651,"tx_offset":0,"log_offset":6,"tx_hash":"0x063e53a1c1e7ed964a0ce65be9bf9402cf70d86a308d6a11315df2c9b5b56173","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000a68aa1e40662045073","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3072149032400335425651"}]}}]},{"block_signed_at":"2021-09-07T13:31:17Z","block_height":69298674,"tx_hash":"0x6a4de9195cec3ddad6223748edfa4335b373fed947a43468ae552e4acc1c6f0a","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77581,"gas_spent":36721,"gas_price":25000000000,"fees_paid":"918025000000000","gas_quote":0.0015128801406532526,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:31:17Z","block_height":69298674,"tx_offset":1,"log_offset":0,"tx_hash":"0x6a4de9195cec3ddad6223748edfa4335b373fed947a43468ae552e4acc1c6f0a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000a68aa1e40662045073","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3072149032400335425651"}]}}]},{"block_signed_at":"2021-09-07T13:32:24Z","block_height":69298741,"tx_hash":"0x08650ffbdc84282fcabdb6bedb8351464ab2a78d2ef448116f46dc4b6a8aa4b8","tx_offset":1,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:35:22Z","block_height":69298919,"tx_hash":"0xb39ea882c4e7b22e85effb73b93bc27e4edefdf3bce01940d9a1d677066aaae7","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:35:22Z","block_height":69298919,"tx_offset":3,"log_offset":1,"tx_hash":"0xb39ea882c4e7b22e85effb73b93bc27e4edefdf3bce01940d9a1d677066aaae7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":444058,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":6,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":7,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff6904874b787824e8534","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563994895471325491516835124"}]}},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":8,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":9,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d2122e5bc14f0bc2be","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3875126340906430218942"}]}},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":10,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":11,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":12,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278420da1c3c1c63200000000000000000000000000000000000000000000000278420ef310bf2db5","decoded":null},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":13,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000035311963b7507de21d63c000000000000000000000000000000000000000000036bd3815832e94a0d0ce9","decoded":null},{"block_signed_at":"2021-09-07T13:35:46Z","block_height":69298943,"tx_offset":2,"log_offset":14,"tx_hash":"0xf989974baf799f0a712e394ae4a720e5d3c3f1dda8c87273fc9b6398ea47d016","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d2122e5bc14f0bc2be","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3875126340906430218942"}]}}]},{"block_signed_at":"2021-09-07T13:36:14Z","block_height":69298971,"tx_hash":"0x4e2f9ac9c4fbf708ccf285a6e1c0ccc32640eb0d2e7955c4a0e24c53eb8e91ea","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3875000000000000000000","value_quote":6385.894224047662,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:39:10Z","block_height":69299147,"tx_hash":"0xcaae900c1c8a7e3a7821df4b229def6556eeb281b0f35c5a41afceb7f79c8fb4","tx_offset":5,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:39:10Z","block_height":69299147,"tx_offset":5,"log_offset":0,"tx_hash":"0xcaae900c1c8a7e3a7821df4b229def6556eeb281b0f35c5a41afceb7f79c8fb4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc4688e41c00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"}]}}]},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461139,"gas_spent":288030,"gas_price":25000000000,"fees_paid":"7200750000000000","gas_quote":0.011866639440983533,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":1,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc4688e41c00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"}]}},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":2,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff5b7a8d0db40f96a6934","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563990899471325501516835124"}]}},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":3,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc4688e41c00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"}]}},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":4,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc4688e41c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d074404817d0bae3f9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3845299541905619215353"}]}},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":5,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0ecc1e40","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5993999999985000000"}]}},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":6,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0ecc1e40","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5993999999985000000"}]}},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":7,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0ecc1e4000000000000000000000000000000000000000000000000278421349a467b2ed0000000000000000000000000000000000000000000000027842149aa0745544","decoded":null},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":8,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000034ec3455f17b2e39b3d50000000000000000000000000000000000000000000036e26e3aa3d3b4f02c607","decoded":null},{"block_signed_at":"2021-09-07T13:41:46Z","block_height":69299303,"tx_offset":5,"log_offset":9,"tx_hash":"0x65983ace3ea39bfcc867cbb4a4697d7f221e6b5e16568c851bc7e0fc9d74eb9e","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc4688e41c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d074404817d0bae3f9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3845299541905619215353"}]}}]},{"block_signed_at":"2021-09-07T13:42:04Z","block_height":69299321,"tx_hash":"0xc8b66e3ba6fc7bf92219c573a3572722fd9455e2a85a69a36de82e3e0358d322","tx_offset":12,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3845000000000000000000","value_quote":6336.455042958259,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:45:19Z","block_height":69299516,"tx_hash":"0xced75a2c26e6fa7eedb880fa5c4c2923009c8ba77e362b0fe36de4e942990a07","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:45:19Z","block_height":69299516,"tx_offset":3,"log_offset":10,"tx_hash":"0xced75a2c26e6fa7eedb880fa5c4c2923009c8ba77e362b0fe36de4e942990a07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc4688e41c00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"}]}}]},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461139,"gas_spent":288030,"gas_price":25000000000,"fees_paid":"7200750000000000","gas_quote":0.011866639440983533,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":2,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc4688e41c00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"}]}},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":3,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff4df092cfefa70864d34","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563986903471325511516835124"}]}},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":4,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc4688e41c00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"}]}},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":5,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc4688e41c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cadda6f59d913b77c5","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3742214026074940733381"}]}},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":6,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0ecc1e40","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5993999999985000000"}]}},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":7,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0ecc1e40","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5993999999985000000"}]}},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":8,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0ecc1e40000000000000000000000000000000000000000000000002784229e58262072400000000000000000000000000000000000000000000000278422b366231f49d","decoded":null},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":9,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000343574bd55076ce36d975000000000000000000000000000000000000000000037a28b7781481d78943f9","decoded":null},{"block_signed_at":"2021-09-07T13:45:30Z","block_height":69299527,"tx_offset":1,"log_offset":10,"tx_hash":"0x3f0bef83cbee6264fdf019ccd35313bed4e3cc54af6c04a5b4eb3d0b57280063","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc4688e41c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cadda6f59d913b77c5","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3995999999990000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3742214026074940733381"}]}}]},{"block_signed_at":"2021-09-07T13:45:53Z","block_height":69299550,"tx_hash":"0x0a05a0cc2c343bdd301e916b7de346684e8c22240ceb28785f23dcaa7a482a08","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3742000000000000000000","value_quote":6166.713854551315,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:49:26Z","block_height":69299763,"tx_hash":"0x982e589004f63812e2bbb9214ba049a8713b3f159c0ac86b590cf2b3317fea3a","tx_offset":8,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:49:26Z","block_height":69299763,"tx_offset":8,"log_offset":4,"tx_hash":"0x982e589004f63812e2bbb9214ba049a8713b3f159c0ac86b590cf2b3317fea3a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":460947,"gas_spent":287902,"gas_price":25000000000,"fees_paid":"7197550000000000","gas_quote":0.011861365928333997,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":5,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":6,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff406698922b193964d34","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563982907471325511516835124"}]}},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":7,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":8,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c8fd4a2272268a2151","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3707600253055450882385"}]}},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":9,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":10,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":11,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027842334fdf79549b000000000000000000000000000000000000000000000002784234a01d82420a","decoded":null},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":12,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033f785221eb9078d02d5d000000000000000000000000000000000000000000037e4d50dd8e0c357525f3","decoded":null},{"block_signed_at":"2021-09-07T13:50:17Z","block_height":69299814,"tx_offset":6,"log_offset":13,"tx_hash":"0x19184a6713db9d182e996076885a4207397fc87bc75bbd8154bff4f34cb5344b","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c8fd4a2272268a2151","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3707600253055450882385"}]}}]},{"block_signed_at":"2021-09-07T13:51:07Z","block_height":69299864,"tx_hash":"0x759221b13fb4d639f99ebc668b198bd4e1864b0fdfdc8a398c1c63df52772a96","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3708000000000000000000","value_quote":6110.682782649994,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:52:45Z","block_height":69299962,"tx_hash":"0x1ef08884a23ce1061f15f747a02e61b9992f50a77b9e6be3ee4510adf4fd1644","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.01127584122696519,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:52:45Z","block_height":69299962,"tx_offset":4,"log_offset":1,"tx_hash":"0x1ef08884a23ce1061f15f747a02e61b9992f50a77b9e6be3ee4510adf4fd1644","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000b977d117ad349b43b9","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3421281361629592372153"}]}},{"block_signed_at":"2021-09-07T13:52:45Z","block_height":69299962,"tx_offset":4,"log_offset":2,"tx_hash":"0x1ef08884a23ce1061f15f747a02e61b9992f50a77b9e6be3ee4510adf4fd1644","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000b977d117ad349b43b9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3421281361629592372153"}]}},{"block_signed_at":"2021-09-07T13:52:45Z","block_height":69299962,"tx_offset":4,"log_offset":3,"tx_hash":"0x1ef08884a23ce1061f15f747a02e61b9992f50a77b9e6be3ee4510adf4fd1644","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T13:52:45Z","block_height":69299962,"tx_offset":4,"log_offset":4,"tx_hash":"0x1ef08884a23ce1061f15f747a02e61b9992f50a77b9e6be3ee4510adf4fd1644","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e733628714200000000000000000000000000000000000000000000000000004552b6954474644e0000000000000000000000000000000000000000000000004552b791b39a9d18","decoded":null},{"block_signed_at":"2021-09-07T13:52:45Z","block_height":69299962,"tx_offset":4,"log_offset":5,"tx_hash":"0x1ef08884a23ce1061f15f747a02e61b9992f50a77b9e6be3ee4510adf4fd1644","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032687e9aea4e07dd7fd9a0000000000000000000000000000000000000000000399d5399d4ff39cd213dd","decoded":null},{"block_signed_at":"2021-09-07T13:52:45Z","block_height":69299962,"tx_offset":4,"log_offset":6,"tx_hash":"0x1ef08884a23ce1061f15f747a02e61b9992f50a77b9e6be3ee4510adf4fd1644","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000b977d117ad349b43b9","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3421281361629592372153"}]}},{"block_signed_at":"2021-09-07T13:52:45Z","block_height":69299962,"tx_offset":4,"log_offset":7,"tx_hash":"0x1ef08884a23ce1061f15f747a02e61b9992f50a77b9e6be3ee4510adf4fd1644","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000b977d117ad349b43b9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3421281361629592372153"}]}}]},{"block_signed_at":"2021-09-07T13:54:13Z","block_height":69300050,"tx_hash":"0xf5607a03614620451cbfaaeb7edcdb683ad95e0211a763a87637b569b6aefecf","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":51137,"gas_price":25000000000,"fees_paid":"1278425000000000","gas_quote":0.0021068095028072592,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:54:13Z","block_height":69300050,"tx_offset":0,"log_offset":0,"tx_hash":"0xf5607a03614620451cbfaaeb7edcdb683ad95e0211a763a87637b569b6aefecf","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T13:54:52Z","block_height":69300089,"tx_hash":"0x55fd2f07fb3d77b58a5db5db5410f74b74e713e424f689707f1440a28cbe9e76","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:54:52Z","block_height":69300089,"tx_offset":2,"log_offset":0,"tx_hash":"0x55fd2f07fb3d77b58a5db5db5410f74b74e713e424f689707f1440a28cbe9e76","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000b93c66a3f545c40000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3417000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T13:55:54Z","block_height":69300151,"tx_hash":"0x41141fbde5336d1459d5054af9faddf34d780af2b5d9c0a732e0664db70705a8","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:59:00Z","block_height":69300337,"tx_hash":"0x487ddc8c2e5a9fcb679f59055e6ca39e5c39c1d4e7194862a1130d209074b548","tx_offset":4,"successful":false,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461139,"gas_spent":47501,"gas_price":25000000000,"fees_paid":"1187525000000000","gas_quote":0.0019570087841063737,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T13:59:37Z","block_height":69300374,"tx_hash":"0xf41aeff0089bd73419a69067a778398df2188672a3b2a3c22ba37d0785e09dab","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T13:59:37Z","block_height":69300374,"tx_offset":0,"log_offset":0,"tx_hash":"0xf41aeff0089bd73419a69067a778398df2188672a3b2a3c22ba37d0785e09dab","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c3c083af05c2c4e85e","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3610987218089871206494"}]}},{"block_signed_at":"2021-09-07T13:59:37Z","block_height":69300374,"tx_offset":0,"log_offset":1,"tx_hash":"0xf41aeff0089bd73419a69067a778398df2188672a3b2a3c22ba37d0785e09dab","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000c3c083af05c2c4e85e","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3610987218089871206494"}]}},{"block_signed_at":"2021-09-07T13:59:37Z","block_height":69300374,"tx_offset":0,"log_offset":2,"tx_hash":"0xf41aeff0089bd73419a69067a778398df2188672a3b2a3c22ba37d0785e09dab","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T13:59:37Z","block_height":69300374,"tx_offset":0,"log_offset":3,"tx_hash":"0xf41aeff0089bd73419a69067a778398df2188672a3b2a3c22ba37d0785e09dab","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e73362871420000000000000000000000000000000000000000000000000000455344db667f54a4000000000000000000000000000000000000000000000000455345d7d3679b43","decoded":null},{"block_signed_at":"2021-09-07T13:59:37Z","block_height":69300374,"tx_offset":0,"log_offset":4,"tx_hash":"0xf41aeff0089bd73419a69067a778398df2188672a3b2a3c22ba37d0785e09dab","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030eff26704db6c29fad2700000000000000000000000000000000000000000003b088efe52d36480125cf","decoded":null},{"block_signed_at":"2021-09-07T13:59:37Z","block_height":69300374,"tx_offset":0,"log_offset":5,"tx_hash":"0xf41aeff0089bd73419a69067a778398df2188672a3b2a3c22ba37d0785e09dab","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c3c083af05c2c4e85e","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3610987218089871206494"}]}},{"block_signed_at":"2021-09-07T13:59:37Z","block_height":69300374,"tx_offset":0,"log_offset":6,"tx_hash":"0xf41aeff0089bd73419a69067a778398df2188672a3b2a3c22ba37d0785e09dab","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000c3c083af05c2c4e85e","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3610987218089871206494"}]}}]},{"block_signed_at":"2021-09-07T14:01:31Z","block_height":69300488,"tx_hash":"0x3c4338f0cf1338225862ab9d8581dcc4257d937e421012477f0801c5b57c4a41","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:01:31Z","block_height":69300488,"tx_offset":3,"log_offset":0,"tx_hash":"0x3c4338f0cf1338225862ab9d8581dcc4257d937e421012477f0801c5b57c4a41","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c3c0b1181a1f8c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3611000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:02:02Z","block_height":69300519,"tx_hash":"0x1c35767a4452a28ed52051eeee553a566127233f3c6d747250daf798c04bbca8","tx_offset":3,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:02:23Z","block_height":69300540,"tx_hash":"0x38c64f954cea91a258103cec2c41b7d61915bfe26c9ccfb44f54dd5db623a7f3","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:02:23Z","block_height":69300540,"tx_offset":0,"log_offset":0,"tx_hash":"0x38c64f954cea91a258103cec2c41b7d61915bfe26c9ccfb44f54dd5db623a7f3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000be7555e870d0dd13a0","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3513336293451510911904"}]}},{"block_signed_at":"2021-09-07T14:02:23Z","block_height":69300540,"tx_offset":0,"log_offset":1,"tx_hash":"0x38c64f954cea91a258103cec2c41b7d61915bfe26c9ccfb44f54dd5db623a7f3","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000be7555e870d0dd13a0","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3513336293451510911904"}]}},{"block_signed_at":"2021-09-07T14:02:23Z","block_height":69300540,"tx_offset":0,"log_offset":2,"tx_hash":"0x38c64f954cea91a258103cec2c41b7d61915bfe26c9ccfb44f54dd5db623a7f3","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T14:02:23Z","block_height":69300540,"tx_offset":0,"log_offset":3,"tx_hash":"0x38c64f954cea91a258103cec2c41b7d61915bfe26c9ccfb44f54dd5db623a7f3","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e7336287142000000000000000000000000000000000000000000000000000045536004705ab416000000000000000000000000000000000000000000000000455360fffc4cffaf","decoded":null},{"block_signed_at":"2021-09-07T14:02:23Z","block_height":69300540,"tx_offset":0,"log_offset":4,"tx_hash":"0x38c64f954cea91a258103cec2c41b7d61915bfe26c9ccfb44f54dd5db623a7f3","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000319cc9e5e236638134fa200000000000000000000000000000000000000000003a3ae667c41ffb160d100","decoded":null},{"block_signed_at":"2021-09-07T14:02:23Z","block_height":69300540,"tx_offset":0,"log_offset":5,"tx_hash":"0x38c64f954cea91a258103cec2c41b7d61915bfe26c9ccfb44f54dd5db623a7f3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000be7555e870d0dd13a0","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3513336293451510911904"}]}},{"block_signed_at":"2021-09-07T14:02:23Z","block_height":69300540,"tx_offset":0,"log_offset":6,"tx_hash":"0x38c64f954cea91a258103cec2c41b7d61915bfe26c9ccfb44f54dd5db623a7f3","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000be7555e870d0dd13a0","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3513336293451510911904"}]}}]},{"block_signed_at":"2021-09-07T14:02:45Z","block_height":69300562,"tx_hash":"0xb0ce71d996be5d583b409c896b7ecd2afa1bbbde6be9db8845bb03d1116fc8f9","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":54889,"gas_spent":36593,"gas_price":25000000000,"fees_paid":"914825000000000","gas_quote":0.0015076066280037164,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:02:45Z","block_height":69300562,"tx_offset":4,"log_offset":46,"tx_hash":"0xb0ce71d996be5d583b409c896b7ecd2afa1bbbde6be9db8845bb03d1116fc8f9","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000be70ab27540b440000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3513000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:03:44Z","block_height":69300621,"tx_hash":"0x24db6b6ff4962907285a824a33427bcaccaa9aab527bac1a59016aefcedc19e2","tx_offset":4,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:07:06Z","block_height":69300823,"tx_hash":"0x814320939094744dc7ea23015fd6cf68ced1942b48fb758db3127f3e0b80552d","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:07:06Z","block_height":69300823,"tx_offset":3,"log_offset":11,"tx_hash":"0x814320939094744dc7ea23015fd6cf68ced1942b48fb758db3127f3e0b80552d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000bdd6c30ca722a5e659","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3501909856587660781145"}]}},{"block_signed_at":"2021-09-07T14:07:06Z","block_height":69300823,"tx_offset":3,"log_offset":12,"tx_hash":"0x814320939094744dc7ea23015fd6cf68ced1942b48fb758db3127f3e0b80552d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000bdd6c30ca722a5e659","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3501909856587660781145"}]}},{"block_signed_at":"2021-09-07T14:07:06Z","block_height":69300823,"tx_offset":3,"log_offset":13,"tx_hash":"0x814320939094744dc7ea23015fd6cf68ced1942b48fb758db3127f3e0b80552d","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T14:07:06Z","block_height":69300823,"tx_offset":3,"log_offset":14,"tx_hash":"0x814320939094744dc7ea23015fd6cf68ced1942b48fb758db3127f3e0b80552d","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e733628714200000000000000000000000000000000000000000000000000004553650c88e2da2900000000000000000000000000000000000000000000000045536607d062657c","decoded":null},{"block_signed_at":"2021-09-07T14:07:06Z","block_height":69300823,"tx_offset":3,"log_offset":15,"tx_hash":"0x814320939094744dc7ea23015fd6cf68ced1942b48fb758db3127f3e0b80552d","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032878bc7b9fd5da4248f200000000000000000000000000000000000000000003b1d469e72e45bd2a22f0","decoded":null},{"block_signed_at":"2021-09-07T14:07:06Z","block_height":69300823,"tx_offset":3,"log_offset":16,"tx_hash":"0x814320939094744dc7ea23015fd6cf68ced1942b48fb758db3127f3e0b80552d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000bdd6c30ca722a5e659","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3501909856587660781145"}]}},{"block_signed_at":"2021-09-07T14:07:06Z","block_height":69300823,"tx_offset":3,"log_offset":17,"tx_hash":"0x814320939094744dc7ea23015fd6cf68ced1942b48fb758db3127f3e0b80552d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000bdd6c30ca722a5e659","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3501909856587660781145"}]}}]},{"block_signed_at":"2021-09-07T14:07:19Z","block_height":69300836,"tx_hash":"0x5d0b7bb99a5ffbfd08983f734e7fea5682ace09875a7aace661d35b6ddaf12f9","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:07:19Z","block_height":69300836,"tx_offset":0,"log_offset":0,"tx_hash":"0x5d0b7bb99a5ffbfd08983f734e7fea5682ace09875a7aace661d35b6ddaf12f9","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000bdd8034d9bd9f80000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3502000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":0,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8de4b67147d472610","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000514729758635271696"}]}},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":1,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff32d8b3dbb9d164f2724","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563978906956595752881563428"}]}},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":2,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8de4b67147d472610","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000514729758635271696"}]}},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":3,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8de4b67147d47261000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b823e8e40684be4b3f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000514729758635271696"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3396788478265129847615"}]}},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":4,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005347066d36f8cf8b","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000772094637952907"}]}},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":5,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005347066d36f8cf8c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000772094637952908"}]}},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":6,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005347066d36f8cf8c0000000000000000000000000000000000000000000000027843499f84cb5da700000000000000000000000000000000000000000000000278434aed7ce5d6d3","decoded":null},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":7,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000326cf440c7dacb41dff5700000000000000000000000000000000000000000003b43392b446ed043e42d6","decoded":null},{"block_signed_at":"2021-09-07T14:10:20Z","block_height":69301017,"tx_offset":1,"log_offset":8,"tx_hash":"0x9c15f864b77fb974cb322c23e837983882fadc6fa12f33880698772c9dcb7e3f","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8de4b67147d47261000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b823e8e40684be4b3f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000514729758635271696"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3396788478265129847615"}]}}]},{"block_signed_at":"2021-09-07T14:10:38Z","block_height":69301035,"tx_hash":"0x3e20c6f1c66205db0858d9178738e8fc2611afd5ba5e8289c8d69d00acab43fc","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3402000000000000000000","value_quote":5606.403135538101,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:12:07Z","block_height":69301124,"tx_hash":"0xc0d6163c87db270dd3442adb0f75ffb3fc922a8c14175f94654730afe714d423","tx_offset":1,"successful":true,"from_address":"0x4496f06d8bb0b234057f35c4568aa0c2b0e949f3","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3002000042110000000000","value_quote":4947.214123742215,"gas_offered":1000000,"gas_spent":31000,"gas_price":25000000000,"fees_paid":"775000000000000","gas_quote":0.0012771788448095321,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:14:14Z","block_height":69301251,"tx_hash":"0x2424a3fa3719db0e9f3c8e564d741e5c085389c00ae8512f63ced3d86e81121d","tx_offset":4,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:14:14Z","block_height":69301251,"tx_offset":4,"log_offset":6,"tx_hash":"0x2424a3fa3719db0e9f3c8e564d741e5c085389c00ae8512f63ced3d86e81121d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":3,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":4,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff254eb99df54395f2724","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563974910956595752881563428"}]}},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":5,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":6,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ace935d2b7a717e451","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3189644549948869960785"}]}},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":7,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":8,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":9,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278437768f47ce684000000000000000000000000000000000000000000000002784378b4ea22bd30","decoded":null},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":10,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030dbcfb0b59b97e2be77b00000000000000000000000000000000000000000003d1453b7177e6da90b471","decoded":null},{"block_signed_at":"2021-09-07T14:14:23Z","block_height":69301260,"tx_offset":4,"log_offset":11,"tx_hash":"0x22a8616fca757f71be3aac47a7697ae5c23b0dcef6daf4bfbef4bc9eb3e82f07","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ace935d2b7a717e451","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3189644549948869960785"}]}}]},{"block_signed_at":"2021-09-07T14:14:48Z","block_height":69301285,"tx_hash":"0xe02510fe10ec33851e15d4180c0a71c81c503662a5ac2dbc30c0e12beeea12e5","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3186000000000000000000","value_quote":5250.441031694412,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:18:14Z","block_height":69301491,"tx_hash":"0x10f6bb3f2fe0a5e4839a3becf12a269c21cc90ee98f0bc009ed0104e131a66eb","tx_offset":2,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:18:14Z","block_height":69301491,"tx_offset":2,"log_offset":13,"tx_hash":"0x10f6bb3f2fe0a5e4839a3becf12a269c21cc90ee98f0bc009ed0104e131a66eb","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":1,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":2,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff17c4bf6030b5c6f2724","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563970914956595752881563428"}]}},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":3,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":4,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac8c2ec7b52151c9e8","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3182941211273043495400"}]}},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":5,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":6,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":7,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278438cbc4b8442eb00000000000000000000000000000000000000000000000278438e0299754d76","decoded":null},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":8,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030c3ed22feda6dcaa237d00000000000000000000000000000000000000000003d17552f16c0db9ce27e7","decoded":null},{"block_signed_at":"2021-09-07T14:18:31Z","block_height":69301508,"tx_offset":5,"log_offset":9,"tx_hash":"0xe48ef3e8997c74d89d74215110cc0b9354955f28c999c39a7b787c19e61d627d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac8c2ec7b52151c9e8","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3182941211273043495400"}]}}]},{"block_signed_at":"2021-09-07T14:18:59Z","block_height":69301536,"tx_hash":"0xa24d861ea14a7b581f16b94178413d58eeb25cdb0fcc61f782c5dbec55fbd31a","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3183000000000000000000","value_quote":5245.497113585473,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:22:25Z","block_height":69301742,"tx_hash":"0xf037180cb950499003f4779b76e4e06f467b68409b02f4cfc6f998bdf0223ccc","tx_offset":9,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":416455,"gas_spent":262544,"gas_price":25000000000,"fees_paid":"6563600000000000","gas_quote":0.010816633633279801,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:22:25Z","block_height":69301742,"tx_offset":9,"log_offset":55,"tx_hash":"0xf037180cb950499003f4779b76e4e06f467b68409b02f4cfc6f998bdf0223ccc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c7f41ca35de777ad3c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3688492184536513752380"}]}},{"block_signed_at":"2021-09-07T14:22:25Z","block_height":69301742,"tx_offset":9,"log_offset":56,"tx_hash":"0xf037180cb950499003f4779b76e4e06f467b68409b02f4cfc6f998bdf0223ccc","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000c7f41ca35de777ad3c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3688492184536513752380"}]}},{"block_signed_at":"2021-09-07T14:22:25Z","block_height":69301742,"tx_offset":9,"log_offset":57,"tx_hash":"0xf037180cb950499003f4779b76e4e06f467b68409b02f4cfc6f998bdf0223ccc","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T14:22:25Z","block_height":69301742,"tx_offset":9,"log_offset":58,"tx_hash":"0xf037180cb950499003f4779b76e4e06f467b68409b02f4cfc6f998bdf0223ccc","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e73362871420000000000000000000000000000000000000000000000000000455383e8bd3e28c5000000000000000000000000000000000000000000000000455384dd92899941","decoded":null},{"block_signed_at":"2021-09-07T14:22:25Z","block_height":69301742,"tx_offset":9,"log_offset":59,"tx_hash":"0xf037180cb950499003f4779b76e4e06f467b68409b02f4cfc6f998bdf0223ccc","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000313291521f5636902628900000000000000000000000000000000000000000003c9f15f5815973c1011db","decoded":null},{"block_signed_at":"2021-09-07T14:22:25Z","block_height":69301742,"tx_offset":9,"log_offset":60,"tx_hash":"0xf037180cb950499003f4779b76e4e06f467b68409b02f4cfc6f998bdf0223ccc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c7f41ca35de777ad3c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3688492184536513752380"}]}},{"block_signed_at":"2021-09-07T14:22:25Z","block_height":69301742,"tx_offset":9,"log_offset":61,"tx_hash":"0xf037180cb950499003f4779b76e4e06f467b68409b02f4cfc6f998bdf0223ccc","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000c7f41ca35de777ad3c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3688492184536513752380"}]}}]},{"block_signed_at":"2021-09-07T14:22:54Z","block_height":69301771,"tx_hash":"0x5bc956dd434a1ede4f7482c9c9c6c446cc25bf278ce5ea1ba928ef056f98b8bb","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77581,"gas_spent":36721,"gas_price":25000000000,"fees_paid":"918025000000000","gas_quote":0.0015128801406532526,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:22:54Z","block_height":69301771,"tx_offset":4,"log_offset":0,"tx_hash":"0x5bc956dd434a1ede4f7482c9c9c6c446cc25bf278ce5ea1ba928ef056f98b8bb","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c7f41ca35de777ad3c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3688492184536513752380"}]}}]},{"block_signed_at":"2021-09-07T14:23:08Z","block_height":69301785,"tx_hash":"0xf3b96ab2349f3c2fc4853f1451e47289af7cdb6178c387e7878d0e0d6a6834c7","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:23:08Z","block_height":69301785,"tx_offset":1,"log_offset":0,"tx_hash":"0xf3b96ab2349f3c2fc4853f1451e47289af7cdb6178c387e7878d0e0d6a6834c7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:24:01Z","block_height":69301838,"tx_hash":"0xa8cdcf6ae9a4ea84c3381799c334f0dfaf7a9c1d1863589b140691a7a8b4aa0a","tx_offset":5,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3001000000000000000000","value_quote":4945.566081643104,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":0,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":1,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xfffffffffffffffffffffffffffffffffffffffffffff0a3ac5226c27f7f2724","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563966918956595752881563428"}]}},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":2,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":3,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b0241e8e8420913ca0","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3249229631305681026208"}]}},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":4,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":5,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":6,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278438fda357a12c50000000000000000000000000000000000000000000000027843911dafe5cee6","decoded":null},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":7,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000314c2bcd9e56d6ec6a80600000000000000000000000000000000000000000003c7f99e14f5a21802707e","decoded":null},{"block_signed_at":"2021-09-07T14:25:21Z","block_height":69301918,"tx_offset":0,"log_offset":8,"tx_hash":"0x4696c3d5b30ce9073506ac109e423d54c6d5925e8887bcd8c3ecfbc7e01b0d0a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b0241e8e8420913ca0","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3249229631305681026208"}]}}]},{"block_signed_at":"2021-09-07T14:25:57Z","block_height":69301954,"tx_hash":"0x38b110430aa2321b594ace83243ef215de5cf6e96f32ba37c0dafd2773dd3dbb","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3250000000000000000000","value_quote":5355.911284685135,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:28:16Z","block_height":69302093,"tx_hash":"0xf7d67498f6cf1aa273fc456dd8899cde3ee01c8592b405ccfd9d113d388abd72","tx_offset":2,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:28:16Z","block_height":69302093,"tx_offset":2,"log_offset":7,"tx_hash":"0xf7d67498f6cf1aa273fc456dd8899cde3ee01c8592b405ccfd9d113d388abd72","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","tx_offset":11,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":27,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":28,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffefcb0cae4a79a28f2724","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563962922956595752881563428"}]}},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":29,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":30,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af92d79ca9499f0d24","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3238761310999600368932"}]}},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":31,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":32,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":33,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb10000000000000000000000000000000000000000000000000002784393a0626f5926000000000000000000000000000000000000000000000002784394e31778df38","decoded":null},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":34,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003136b653039f2da085b1c00000000000000000000000000000000000000000003c9738449cd44a786c308","decoded":null},{"block_signed_at":"2021-09-07T14:29:37Z","block_height":69302174,"tx_offset":11,"log_offset":35,"tx_hash":"0x9e283bdaa81037da2e987c7d3649238109dfc2b5379b92e2cc5b3283d6e35e97","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af92d79ca9499f0d24","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3238761310999600368932"}]}}]},{"block_signed_at":"2021-09-07T14:30:10Z","block_height":69302207,"tx_hash":"0xfc633aaedae98eacc5bae9f923a1d9551de94df62567773d53313e6232bf5017","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3239000000000000000000","value_quote":5337.783584952355,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:34:10Z","block_height":69302447,"tx_hash":"0x66b96d81ec1779e9e0cb0ae3a3e10d4e23aae8d0aeda7c3dc341ca52906feda9","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:34:10Z","block_height":69302447,"tx_offset":0,"log_offset":0,"tx_hash":"0x66b96d81ec1779e9e0cb0ae3a3e10d4e23aae8d0aeda7c3dc341ca52906feda9","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:35:05Z","block_height":69302502,"tx_hash":"0x522b0796920616ed1f4c61424f77f92ddfc8d683fcf7c88e474bdb7c26556dd2","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":393598,"gas_spent":247544,"gas_price":25000000000,"fees_paid":"6188600000000000","gas_quote":0.010198643869662285,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:35:05Z","block_height":69302502,"tx_offset":1,"log_offset":7,"tx_hash":"0x522b0796920616ed1f4c61424f77f92ddfc8d683fcf7c88e474bdb7c26556dd2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c7950c87bd74302fbf","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3681642179127340445631"}]}},{"block_signed_at":"2021-09-07T14:35:05Z","block_height":69302502,"tx_offset":1,"log_offset":8,"tx_hash":"0x522b0796920616ed1f4c61424f77f92ddfc8d683fcf7c88e474bdb7c26556dd2","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000c7950c87bd74302fbf","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3681642179127340445631"}]}},{"block_signed_at":"2021-09-07T14:35:05Z","block_height":69302502,"tx_offset":1,"log_offset":9,"tx_hash":"0x522b0796920616ed1f4c61424f77f92ddfc8d683fcf7c88e474bdb7c26556dd2","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T14:35:05Z","block_height":69302502,"tx_offset":1,"log_offset":10,"tx_hash":"0x522b0796920616ed1f4c61424f77f92ddfc8d683fcf7c88e474bdb7c26556dd2","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e7336287142000000000000000000000000000000000000000000000000000045538c81c2cff65600000000000000000000000000000000000000000000000045538d8145052291","decoded":null},{"block_signed_at":"2021-09-07T14:35:05Z","block_height":69302502,"tx_offset":1,"log_offset":11,"tx_hash":"0x522b0796920616ed1f4c61424f77f92ddfc8d683fcf7c88e474bdb7c26556dd2","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000313d376609cab7467e52600000000000000000000000000000000000000000003c8f5f58685cfa0e173d2","decoded":null},{"block_signed_at":"2021-09-07T14:35:05Z","block_height":69302502,"tx_offset":1,"log_offset":12,"tx_hash":"0x522b0796920616ed1f4c61424f77f92ddfc8d683fcf7c88e474bdb7c26556dd2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c7950c87bd74302fbf","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3681642179127340445631"}]}},{"block_signed_at":"2021-09-07T14:35:05Z","block_height":69302502,"tx_offset":1,"log_offset":13,"tx_hash":"0x522b0796920616ed1f4c61424f77f92ddfc8d683fcf7c88e474bdb7c26556dd2","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000c7950c87bd74302fbf","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3681642179127340445631"}]}}]},{"block_signed_at":"2021-09-07T14:35:32Z","block_height":69302529,"tx_hash":"0x8a0dec6a83d3d9e4e58423b4328ed7f0ee3fa6fc8cfa0269831398ec471282f8","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:35:32Z","block_height":69302529,"tx_offset":2,"log_offset":2,"tx_hash":"0x8a0dec6a83d3d9e4e58423b4328ed7f0ee3fa6fc8cfa0269831398ec471282f8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c754a0326b47540000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3677000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:36:47Z","block_height":69302604,"tx_hash":"0x403ca414f92eb7560462e7c429e0751e9ee0215089ada25b80fc5df1c0a900da","tx_offset":0,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3001000000000000000000","value_quote":4945.566081643104,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:40:56Z","block_height":69302853,"tx_hash":"0x5261d0da9c6a759b2725c3e10432258dd9e414af9407dcf9b1941c35c4f9e8e9","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:40:56Z","block_height":69302853,"tx_offset":1,"log_offset":0,"tx_hash":"0x5261d0da9c6a759b2725c3e10432258dd9e414af9407dcf9b1941c35c4f9e8e9","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c0432548c636092273","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3546613215543060669043"}]}},{"block_signed_at":"2021-09-07T14:40:56Z","block_height":69302853,"tx_offset":1,"log_offset":1,"tx_hash":"0x5261d0da9c6a759b2725c3e10432258dd9e414af9407dcf9b1941c35c4f9e8e9","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000c0432548c636092273","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3546613215543060669043"}]}},{"block_signed_at":"2021-09-07T14:40:56Z","block_height":69302853,"tx_offset":1,"log_offset":2,"tx_hash":"0x5261d0da9c6a759b2725c3e10432258dd9e414af9407dcf9b1941c35c4f9e8e9","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T14:40:56Z","block_height":69302853,"tx_offset":1,"log_offset":3,"tx_hash":"0x5261d0da9c6a759b2725c3e10432258dd9e414af9407dcf9b1941c35c4f9e8e9","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e733628714200000000000000000000000000000000000000000000000000004553a44ec76f418e0000000000000000000000000000000000000000000000004553a54c6b66a174","decoded":null},{"block_signed_at":"2021-09-07T14:40:56Z","block_height":69302853,"tx_offset":1,"log_offset":4,"tx_hash":"0x5261d0da9c6a759b2725c3e10432258dd9e414af9407dcf9b1941c35c4f9e8e9","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000322c20e5546c2b1de568200000000000000000000000000000000000000000003b720f22e449278a407f7","decoded":null},{"block_signed_at":"2021-09-07T14:40:56Z","block_height":69302853,"tx_offset":1,"log_offset":5,"tx_hash":"0x5261d0da9c6a759b2725c3e10432258dd9e414af9407dcf9b1941c35c4f9e8e9","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c0432548c636092273","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3546613215543060669043"}]}},{"block_signed_at":"2021-09-07T14:40:56Z","block_height":69302853,"tx_offset":1,"log_offset":6,"tx_hash":"0x5261d0da9c6a759b2725c3e10432258dd9e414af9407dcf9b1941c35c4f9e8e9","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000c0432548c636092273","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3546613215543060669043"}]}}]},{"block_signed_at":"2021-09-07T14:41:29Z","block_height":69302886,"tx_hash":"0x153ce311c49dd4fb98319fac217f38815e5b1257069d92e0e043dbe95e9bae87","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:41:29Z","block_height":69302886,"tx_offset":5,"log_offset":17,"tx_hash":"0x153ce311c49dd4fb98319fac217f38815e5b1257069d92e0e043dbe95e9bae87","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000c0a9a86a19da480000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3554000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:43:37Z","block_height":69303014,"tx_hash":"0x247780e825c25d65fdf3ce2c2e4b9127f68f8015f39528f6be14497f9e125ee8","tx_offset":1,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3001000000000000000000","value_quote":4945.566081643104,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":444250,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":20,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8798d1047658d5232","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3993255394670401114674"}]}},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":21,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffeef293213a323d01d4f2","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563958929701201082480448754"}]}},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":22,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8798d1047658d5232","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3993255394670401114674"}]}},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":23,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8798d1047658d523200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b86b14c7a45c7d31c6","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3993255394670401114674"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3401916921132890272198"}]}},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":24,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532056efb91cc188","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5989883092005601672"}]}},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":25,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532056efb91cc188","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5989883092005601672"}]}},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":26,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532056efb91cc18800000000000000000000000000000000000000000000000278439b2de168d62c00000000000000000000000000000000000000000000000278439c7c254dbfbd","decoded":null},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":27,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003275d33a32c9c867b711100000000000000000000000000000000000000000003b1b442f49008fcc73fa2","decoded":null},{"block_signed_at":"2021-09-07T14:44:00Z","block_height":69303037,"tx_offset":3,"log_offset":28,"tx_hash":"0xbf516bc4eacbfcc14b78560a378c2eab03fc975d5c54961b47410a18e5842294","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8798d1047658d523200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b86b14c7a45c7d31c6","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3993255394670401114674"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3401916921132890272198"}]}}]},{"block_signed_at":"2021-09-07T14:44:42Z","block_height":69303079,"tx_hash":"0x39edc37b23284a2ff24d3de03f33af69a61224d736e11d145611fdca4ddcd311","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3404000000000000000000","value_quote":5609.699080944061,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:48:19Z","block_height":69303296,"tx_hash":"0x6e80cf2465cc39075cfe0740c9da4dc75a99f1f2a95e8f8f2105c6ac19e7c2d5","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:48:19Z","block_height":69303296,"tx_offset":0,"log_offset":0,"tx_hash":"0x6e80cf2465cc39075cfe0740c9da4dc75a99f1f2a95e8f8f2105c6ac19e7c2d5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:50:17Z","block_height":69303414,"tx_hash":"0x83f9e4bb123f321552744469a3efa6eb04f4853aacb8e4efb752ecf8bed5956d","tx_offset":4,"successful":false,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":47437,"gas_price":25000000000,"fees_paid":"1185925000000000","gas_quote":0.001954372027781606,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","tx_offset":11,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":9,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":10,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffee19f37d5de96011d4f2","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563954933701201082480448754"}]}},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":11,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":12,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b40f60b35e4fb338ba","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3321522015993697876154"}]}},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":13,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":14,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":15,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027843b8e9c84caf500000000000000000000000000000000000000000000000027843ba334da0b4bf","decoded":null},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":16,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031d7fea5542a25eca221000000000000000000000000000000000000000000003bd6858f4a22a3b2ef66f","decoded":null},{"block_signed_at":"2021-09-07T14:50:47Z","block_height":69303444,"tx_offset":11,"log_offset":17,"tx_hash":"0x5c7cb2c33d4e1385d1d2c963a44068acaa611efb80d6aee09e6064e64eb06e0d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b40f60b35e4fb338ba","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3321522015993697876154"}]}}]},{"block_signed_at":"2021-09-07T14:51:11Z","block_height":69303468,"tx_hash":"0x89d2f0da25b33c58b888e1fc6f454daa62e2588895928aada7e678ad14055ab1","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3322000000000000000000","value_quote":5474.565319299698,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T14:54:13Z","block_height":69303650,"tx_hash":"0xaadfa8b667a6415ca352e25d073affb12682994cf75b954c62be7fbe11e6b022","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:54:13Z","block_height":69303650,"tx_offset":3,"log_offset":0,"tx_hash":"0xaadfa8b667a6415ca352e25d073affb12682994cf75b954c62be7fbe11e6b022","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":444058,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":2,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":3,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffed4153d981a08321d4f2","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563950937701201082480448754"}]}},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":4,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":5,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b50fc238a5b5ad9707","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3339996209681848440583"}]}},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":6,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":7,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":8,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027843c10ecd1eeedd0000000000000000000000000000000000000000000000027843c2568eecac3b","decoded":null},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":9,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031fa47ad75cae360174ce00000000000000000000000000000000000000000003baac33f6ee8ca10c7be9","decoded":null},{"block_signed_at":"2021-09-07T14:56:03Z","block_height":69303760,"tx_offset":1,"log_offset":10,"tx_hash":"0x1cbb394b68e175d3f1d0ebf707b7c929f2be7d21c0506bc858c09a1f938f829c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b50fc238a5b5ad9707","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3339996209681848440583"}]}}]},{"block_signed_at":"2021-09-07T14:56:46Z","block_height":69303803,"tx_hash":"0x6153e0be39cd82f32dc87e00941861cbaeeb8c682a44f648c4baac6fe2ea7f02","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3340000000000000000000","value_quote":5504.228827953339,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T15:01:20Z","block_height":69304077,"tx_hash":"0x9b6fe8e978a2ed8dcd5c627f113e902344f9711aa96a1c11a032d782588ca6b2","tx_offset":7,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:01:20Z","block_height":69304077,"tx_offset":7,"log_offset":21,"tx_hash":"0x9b6fe8e978a2ed8dcd5c627f113e902344f9711aa96a1c11a032d782588ca6b2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":27,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":28,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffec68b435a557a631d4f2","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563946941701201082480448754"}]}},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":29,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":30,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a60a11886cb0f9a24b","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3062885027251175924299"}]}},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":31,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":32,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":33,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278441ad42602ea7a00000000000000000000000000000000000000000000000278441c0e31e191b4","decoded":null},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":34,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002fdc43982f316e3ee60fd00000000000000000000000000000000000000000003e4e7cedcf200a37664c3","decoded":null},{"block_signed_at":"2021-09-07T15:03:28Z","block_height":69304205,"tx_offset":1,"log_offset":35,"tx_hash":"0xf9c2b7382220496dfe990f4b92328239e07eaba9e0775f77f30226b8b3589a3b","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a60a11886cb0f9a24b","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3062885027251175924299"}]}}]},{"block_signed_at":"2021-09-07T15:03:47Z","block_height":69304224,"tx_hash":"0x6cff77d275fd04216a5e070d85d74b2f89dc251c01d830f95acbb7f09fa8e02d","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3062000000000000000000","value_quote":5046.092416524887,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T15:14:16Z","block_height":69304853,"tx_hash":"0x488b5a202c7f884101a84e1483f7796e282a838beba867188082f1f6da0e8706","tx_offset":8,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:14:16Z","block_height":69304853,"tx_offset":8,"log_offset":32,"tx_hash":"0x488b5a202c7f884101a84e1483f7796e282a838beba867188082f1f6da0e8706","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a678bd8c85a94800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996492265940000000000"}]}}]},{"block_signed_at":"2021-09-07T15:16:31Z","block_height":69304988,"tx_hash":"0xd14def3e7d1bcbfb9c065f74a4df6c999553f794b4e9f2021defa32ca5a5edf8","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":376614,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:16:31Z","block_height":69304988,"tx_offset":7,"log_offset":82,"tx_hash":"0xd14def3e7d1bcbfb9c065f74a4df6c999553f794b4e9f2021defa32ca5a5edf8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ddd2f28f8a3099914b","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4091930809805823381835"}]}},{"block_signed_at":"2021-09-07T15:16:31Z","block_height":69304988,"tx_offset":7,"log_offset":83,"tx_hash":"0xd14def3e7d1bcbfb9c065f74a4df6c999553f794b4e9f2021defa32ca5a5edf8","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000ddd2f28f8a3099914b","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"4091930809805823381835"}]}},{"block_signed_at":"2021-09-07T15:16:31Z","block_height":69304988,"tx_offset":7,"log_offset":84,"tx_hash":"0xd14def3e7d1bcbfb9c065f74a4df6c999553f794b4e9f2021defa32ca5a5edf8","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x0000000000000000000000000000000000000000000000003e73362871420000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"4500000000000000000"}]}},{"block_signed_at":"2021-09-07T15:16:31Z","block_height":69304988,"tx_offset":7,"log_offset":85,"tx_hash":"0xd14def3e7d1bcbfb9c065f74a4df6c999553f794b4e9f2021defa32ca5a5edf8","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e7336287142000000000000000000000000000000000000000000000000000045547f4cbb5d571f0000000000000000000000000000000000000000000000004554803fd6ed8cc9","decoded":null},{"block_signed_at":"2021-09-07T15:16:31Z","block_height":69304988,"tx_offset":7,"log_offset":86,"tx_hash":"0xd14def3e7d1bcbfb9c065f74a4df6c999553f794b4e9f2021defa32ca5a5edf8","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002ea14abc2c59770340ce900000000000000000000000000000000000000000003fbd520811e1b10b94197","decoded":null},{"block_signed_at":"2021-09-07T15:16:31Z","block_height":69304988,"tx_offset":7,"log_offset":87,"tx_hash":"0xd14def3e7d1bcbfb9c065f74a4df6c999553f794b4e9f2021defa32ca5a5edf8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000ddd2f28f8a3099914b","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4091930809805823381835"}]}},{"block_signed_at":"2021-09-07T15:16:31Z","block_height":69304988,"tx_offset":7,"log_offset":88,"tx_hash":"0xd14def3e7d1bcbfb9c065f74a4df6c999553f794b4e9f2021defa32ca5a5edf8","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2a15d09519be000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000ddd2f28f8a3099914b","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"4091930809805823381835"}]}}]},{"block_signed_at":"2021-09-07T15:16:50Z","block_height":69305007,"tx_hash":"0x4b2fa4aea088533f085d8b53c093754faf3aa342d41d98e60c257b66cdf22715","tx_offset":18,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:16:50Z","block_height":69305007,"tx_offset":18,"log_offset":32,"tx_hash":"0x4b2fa4aea088533f085d8b53c093754faf3aa342d41d98e60c257b66cdf22715","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000dd9c6584d904e00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4088000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T15:18:45Z","block_height":69305122,"tx_hash":"0x14698fbc514e4335a3b4206635aa0f66267f3086927dfea147f5153358601ff1","tx_offset":125,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"3000000000000000000000","value_quote":4943.9181089401245,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","tx_offset":8,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":44,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dd05c83db162d94b","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000423075745823381835"}]}},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":45,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffeb8fd72fdd19f4cefba7","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563942941278125336657066919"}]}},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":46,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dd05c83db162d94b","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000423075745823381835"}]}},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":47,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dd05c83db162d94b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a439acd76766397826","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000423075745823381835"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3029421961483619235878"}]}},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":48,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000534689636ba877e0","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000634613618735072"}]}},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":49,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000534689636ba877e1","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000634613618735073"}]}},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":50,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000534689636ba877e100000000000000000000000000000000000000000000000278453005e5fea6200000000000000000000000000000000000000000000000027845314ac9c6e8b0","decoded":null},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":51,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002f7e711dd52e445fde17a00000000000000000000000000000000000000000003e94db0ffaa9b52094696","decoded":null},{"block_signed_at":"2021-09-07T15:24:20Z","block_height":69305457,"tx_offset":8,"log_offset":52,"tx_hash":"0x25d76e54ecf6f416823534c4dd3edc7c0b465a14f0955a4201e72b81f898f4d3","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dd05c83db162d94b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a439acd76766397826","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000423075745823381835"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3029421961483619235878"}]}}]},{"block_signed_at":"2021-09-07T15:24:54Z","block_height":69305491,"tx_hash":"0xec787e6fe3d980665cdba364396cdb15b846cff7b51c1e5278873bcdc7d0edf7","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"4030000000000000000000","value_quote":6641.329993009567,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T15:39:14Z","block_height":69306351,"tx_hash":"0xafb34a3be45a57d3d4bbb957c0b8de6ee4bb66ba19c34e166331d0678b8f8816","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.01127584122696519,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:39:14Z","block_height":69306351,"tx_offset":0,"log_offset":0,"tx_hash":"0xafb34a3be45a57d3d4bbb957c0b8de6ee4bb66ba19c34e166331d0678b8f8816","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008e2fc432ee6c02f051","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2622879590481569968209"}]}},{"block_signed_at":"2021-09-07T15:39:14Z","block_height":69306351,"tx_offset":0,"log_offset":1,"tx_hash":"0xafb34a3be45a57d3d4bbb957c0b8de6ee4bb66ba19c34e166331d0678b8f8816","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008e2fc432ee6c02f051","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2622879590481569968209"}]}},{"block_signed_at":"2021-09-07T15:39:14Z","block_height":69306351,"tx_offset":0,"log_offset":2,"tx_hash":"0xafb34a3be45a57d3d4bbb957c0b8de6ee4bb66ba19c34e166331d0678b8f8816","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T15:39:14Z","block_height":69306351,"tx_offset":0,"log_offset":3,"tx_hash":"0xafb34a3be45a57d3d4bbb957c0b8de6ee4bb66ba19c34e166331d0678b8f8816","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004554bcbec7c3f2890000000000000000000000000000000000000000000000004554bd65067602c2","decoded":null},{"block_signed_at":"2021-09-07T15:39:14Z","block_height":69306351,"tx_offset":0,"log_offset":4,"tx_hash":"0xafb34a3be45a57d3d4bbb957c0b8de6ee4bb66ba19c34e166331d0678b8f8816","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002f87e68c94b4d02f392bc00000000000000000000000000000000000000000003e7c994dcc1ed9fa94520","decoded":null},{"block_signed_at":"2021-09-07T15:39:14Z","block_height":69306351,"tx_offset":0,"log_offset":5,"tx_hash":"0xafb34a3be45a57d3d4bbb957c0b8de6ee4bb66ba19c34e166331d0678b8f8816","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008e2fc432ee6c02f051","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2622879590481569968209"}]}},{"block_signed_at":"2021-09-07T15:39:14Z","block_height":69306351,"tx_offset":0,"log_offset":6,"tx_hash":"0xafb34a3be45a57d3d4bbb957c0b8de6ee4bb66ba19c34e166331d0678b8f8816","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008e2fc432ee6c02f051","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2622879590481569968209"}]}}]},{"block_signed_at":"2021-09-07T15:39:52Z","block_height":69306389,"tx_hash":"0xf992f19b29af8e7b92fc4652a0ee3c7a3c96900a5862c84ff2286157d3f91191","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77581,"gas_spent":36721,"gas_price":25000000000,"fees_paid":"918025000000000","gas_quote":0.0015128801406532526,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:39:52Z","block_height":69306389,"tx_offset":2,"log_offset":0,"tx_hash":"0xf992f19b29af8e7b92fc4652a0ee3c7a3c96900a5862c84ff2286157d3f91191","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008e2fc432ee6c02f051","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2622879590481569968209"}]}}]},{"block_signed_at":"2021-09-07T15:40:36Z","block_height":69306433,"tx_hash":"0xd29d20e8090bbfbf3e27cc489e53678d2839af320371e3dad95eb422084c4681","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T15:47:12Z","block_height":69306829,"tx_hash":"0x87b2ad0c20f6d9213d58e71e916b3525876c2b1b0f9d30409af1ab9a700a0ccf","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:47:12Z","block_height":69306829,"tx_offset":3,"log_offset":27,"tx_hash":"0x87b2ad0c20f6d9213d58e71e916b3525876c2b1b0f9d30409af1ab9a700a0ccf","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T15:49:07Z","block_height":69306944,"tx_hash":"0xf006bbd3307e88bfae3e50db0fe4aa7d70fb6c46f1801994b0530c2c901aeaaf","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:49:07Z","block_height":69306944,"tx_offset":3,"log_offset":0,"tx_hash":"0xf006bbd3307e88bfae3e50db0fe4aa7d70fb6c46f1801994b0530c2c901aeaaf","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000898721f18dc0f32278","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2536941267558690136696"}]}},{"block_signed_at":"2021-09-07T15:49:07Z","block_height":69306944,"tx_offset":3,"log_offset":1,"tx_hash":"0xf006bbd3307e88bfae3e50db0fe4aa7d70fb6c46f1801994b0530c2c901aeaaf","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000898721f18dc0f32278","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2536941267558690136696"}]}},{"block_signed_at":"2021-09-07T15:49:07Z","block_height":69306944,"tx_offset":3,"log_offset":2,"tx_hash":"0xf006bbd3307e88bfae3e50db0fe4aa7d70fb6c46f1801994b0530c2c901aeaaf","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T15:49:07Z","block_height":69306944,"tx_offset":3,"log_offset":3,"tx_hash":"0xf006bbd3307e88bfae3e50db0fe4aa7d70fb6c46f1801994b0530c2c901aeaaf","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004554d9bbb2ae65f90000000000000000000000000000000000000000000000004554da66c07d8e83","decoded":null},{"block_signed_at":"2021-09-07T15:49:07Z","block_height":69306944,"tx_offset":3,"log_offset":4,"tx_hash":"0xf006bbd3307e88bfae3e50db0fe4aa7d70fb6c46f1801994b0530c2c901aeaaf","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003054b9a62815cbaa8cc5000000000000000000000000000000000000000000003d75116cafc953400cb74","decoded":null},{"block_signed_at":"2021-09-07T15:49:07Z","block_height":69306944,"tx_offset":3,"log_offset":5,"tx_hash":"0xf006bbd3307e88bfae3e50db0fe4aa7d70fb6c46f1801994b0530c2c901aeaaf","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000898721f18dc0f32278","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2536941267558690136696"}]}},{"block_signed_at":"2021-09-07T15:49:07Z","block_height":69306944,"tx_offset":3,"log_offset":6,"tx_hash":"0xf006bbd3307e88bfae3e50db0fe4aa7d70fb6c46f1801994b0530c2c901aeaaf","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000898721f18dc0f32278","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2536941267558690136696"}]}}]},{"block_signed_at":"2021-09-07T15:49:27Z","block_height":69306964,"tx_hash":"0xac20350f175faa1a545b801ae38708782fb23721ad1aed9d25066898ed3da9b7","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:49:27Z","block_height":69306964,"tx_offset":3,"log_offset":5,"tx_hash":"0xac20350f175faa1a545b801ae38708782fb23721ad1aed9d25066898ed3da9b7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000897a11e3b236a00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2536000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T15:52:52Z","block_height":69307169,"tx_hash":"0x99b055c4684a2f2bb39a4d729afb11447c2fdcb46f8049b5af486c118fdcd3e3","tx_offset":4,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2001000000000000000000","value_quote":3297.593378663063,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T15:53:18Z","block_height":69307195,"tx_hash":"0x1559985ec49bf9fce722f85b3297bb6c8f35c3ac9bb3df1ac1cbc554f0f91c68","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:53:18Z","block_height":69307195,"tx_offset":6,"log_offset":61,"tx_hash":"0x1559985ec49bf9fce722f85b3297bb6c8f35c3ac9bb3df1ac1cbc554f0f91c68","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008a917efba22c83680a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2556134775828433299466"}]}},{"block_signed_at":"2021-09-07T15:53:18Z","block_height":69307195,"tx_offset":6,"log_offset":62,"tx_hash":"0x1559985ec49bf9fce722f85b3297bb6c8f35c3ac9bb3df1ac1cbc554f0f91c68","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008a917efba22c83680a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2556134775828433299466"}]}},{"block_signed_at":"2021-09-07T15:53:18Z","block_height":69307195,"tx_offset":6,"log_offset":63,"tx_hash":"0x1559985ec49bf9fce722f85b3297bb6c8f35c3ac9bb3df1ac1cbc554f0f91c68","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T15:53:18Z","block_height":69307195,"tx_offset":6,"log_offset":64,"tx_hash":"0x1559985ec49bf9fce722f85b3297bb6c8f35c3ac9bb3df1ac1cbc554f0f91c68","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004554de2a19a7e27c0000000000000000000000000000000000000000000000004554ded2d1d2e640","decoded":null},{"block_signed_at":"2021-09-07T15:53:18Z","block_height":69307195,"tx_offset":6,"log_offset":65,"tx_hash":"0x1559985ec49bf9fce722f85b3297bb6c8f35c3ac9bb3df1ac1cbc554f0f91c68","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000302632bd864bc064205bd00000000000000000000000000000000000000000003db0746b922d6e5a4c22e","decoded":null},{"block_signed_at":"2021-09-07T15:53:18Z","block_height":69307195,"tx_offset":6,"log_offset":66,"tx_hash":"0x1559985ec49bf9fce722f85b3297bb6c8f35c3ac9bb3df1ac1cbc554f0f91c68","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008a917efba22c83680a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2556134775828433299466"}]}},{"block_signed_at":"2021-09-07T15:53:18Z","block_height":69307195,"tx_offset":6,"log_offset":67,"tx_hash":"0x1559985ec49bf9fce722f85b3297bb6c8f35c3ac9bb3df1ac1cbc554f0f91c68","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008a917efba22c83680a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2556134775828433299466"}]}}]},{"block_signed_at":"2021-09-07T15:53:36Z","block_height":69307213,"tx_hash":"0x94d263436df42469bb15c8f1bd4485515b5bdbbf57ecba87b69ec5cbeb6a6c62","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":54889,"gas_spent":36593,"gas_price":25000000000,"fees_paid":"914825000000000","gas_quote":0.0015076066280037164,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:53:36Z","block_height":69307213,"tx_offset":6,"log_offset":25,"tx_hash":"0x94d263436df42469bb15c8f1bd4485515b5bdbbf57ecba87b69ec5cbeb6a6c62","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008a8fa029bb4a700000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2556000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T15:55:08Z","block_height":69307305,"tx_hash":"0x7c78f427623a3fe18115e268b3ad3e51be652d23a9571c9acd5d1195d030b38e","tx_offset":5,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T15:59:07Z","block_height":69307544,"tx_hash":"0x9708c2dc6a5a0a01e7bf856cc7444490701033ebc24990886eab9ce3a9c60310","tx_offset":73,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:59:07Z","block_height":69307544,"tx_offset":73,"log_offset":25,"tx_hash":"0x9708c2dc6a5a0a01e7bf856cc7444490701033ebc24990886eab9ce3a9c60310","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000087fc4060d9bbc94eb2","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2508487084535131492018"}]}},{"block_signed_at":"2021-09-07T15:59:07Z","block_height":69307544,"tx_offset":73,"log_offset":26,"tx_hash":"0x9708c2dc6a5a0a01e7bf856cc7444490701033ebc24990886eab9ce3a9c60310","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000087fc4060d9bbc94eb2","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2508487084535131492018"}]}},{"block_signed_at":"2021-09-07T15:59:07Z","block_height":69307544,"tx_offset":73,"log_offset":27,"tx_hash":"0x9708c2dc6a5a0a01e7bf856cc7444490701033ebc24990886eab9ce3a9c60310","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T15:59:07Z","block_height":69307544,"tx_offset":73,"log_offset":28,"tx_hash":"0x9708c2dc6a5a0a01e7bf856cc7444490701033ebc24990886eab9ce3a9c60310","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004554eaa1a4c93fac0000000000000000000000000000000000000000000000004554eb4c069f2cf8","decoded":null},{"block_signed_at":"2021-09-07T15:59:07Z","block_height":69307544,"tx_offset":73,"log_offset":29,"tx_hash":"0x9708c2dc6a5a0a01e7bf856cc7444490701033ebc24990886eab9ce3a9c60310","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000309aae5f1df95ca2c443300000000000000000000000000000000000000000003d1c9cdb0dce007ae10bf","decoded":null},{"block_signed_at":"2021-09-07T15:59:07Z","block_height":69307544,"tx_offset":73,"log_offset":30,"tx_hash":"0x9708c2dc6a5a0a01e7bf856cc7444490701033ebc24990886eab9ce3a9c60310","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000087fc4060d9bbc94eb2","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2508487084535131492018"}]}},{"block_signed_at":"2021-09-07T15:59:07Z","block_height":69307544,"tx_offset":73,"log_offset":31,"tx_hash":"0x9708c2dc6a5a0a01e7bf856cc7444490701033ebc24990886eab9ce3a9c60310","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000087fc4060d9bbc94eb2","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2508487084535131492018"}]}}]},{"block_signed_at":"2021-09-07T15:59:31Z","block_height":69307568,"tx_hash":"0x5cff50b3161687a6309e306669070c93403fb443e60495e908acbe69e8023d1c","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":54889,"gas_spent":36593,"gas_price":25000000000,"fees_paid":"914825000000000","gas_quote":0.0015076066280037164,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T15:59:31Z","block_height":69307568,"tx_offset":3,"log_offset":13,"tx_hash":"0x5cff50b3161687a6309e306669070c93403fb443e60495e908acbe69e8023d1c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000087f57de80be7b00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2508000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T16:06:00Z","block_height":69307957,"tx_hash":"0x044f32d60288659276aec3887fe4202fcdae019f98c374219137c4ca9f72c2af","tx_offset":4,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T16:09:49Z","block_height":69308186,"tx_hash":"0xa65f6b1b873efbe42693dc5de9121120357a1d9ed80856147fd38faeda087231","tx_offset":9,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:09:49Z","block_height":69308186,"tx_offset":9,"log_offset":2,"tx_hash":"0xa65f6b1b873efbe42693dc5de9121120357a1d9ed80856147fd38faeda087231","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000084feeedc660fdf63b7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2453340079990662718391"}]}},{"block_signed_at":"2021-09-07T16:09:49Z","block_height":69308186,"tx_offset":9,"log_offset":3,"tx_hash":"0xa65f6b1b873efbe42693dc5de9121120357a1d9ed80856147fd38faeda087231","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000084feeedc660fdf63b7","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2453340079990662718391"}]}},{"block_signed_at":"2021-09-07T16:09:49Z","block_height":69308186,"tx_offset":9,"log_offset":4,"tx_hash":"0xa65f6b1b873efbe42693dc5de9121120357a1d9ed80856147fd38faeda087231","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T16:09:49Z","block_height":69308186,"tx_offset":9,"log_offset":5,"tx_hash":"0xa65f6b1b873efbe42693dc5de9121120357a1d9ed80856147fd38faeda087231","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455500ea564a935200000000000000000000000000000000000000000000000045550194d7426ca3","decoded":null},{"block_signed_at":"2021-09-07T16:09:49Z","block_height":69308186,"tx_offset":9,"log_offset":6,"tx_hash":"0xa65f6b1b873efbe42693dc5de9121120357a1d9ed80856147fd38faeda087231","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003102861b36bb61796493800000000000000000000000000000000000000000003c447164aa67a1a68c0f0","decoded":null},{"block_signed_at":"2021-09-07T16:09:49Z","block_height":69308186,"tx_offset":9,"log_offset":7,"tx_hash":"0xa65f6b1b873efbe42693dc5de9121120357a1d9ed80856147fd38faeda087231","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000084feeedc660fdf63b7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2453340079990662718391"}]}},{"block_signed_at":"2021-09-07T16:09:49Z","block_height":69308186,"tx_offset":9,"log_offset":8,"tx_hash":"0xa65f6b1b873efbe42693dc5de9121120357a1d9ed80856147fd38faeda087231","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000084feeedc660fdf63b7","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2453340079990662718391"}]}}]},{"block_signed_at":"2021-09-07T16:10:08Z","block_height":69308205,"tx_hash":"0x2d1def47054f73d9b3ff9ca087b825a7dcaea4a0d7907d83afa99fb56102b20b","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:10:08Z","block_height":69308205,"tx_offset":3,"log_offset":17,"tx_hash":"0x2d1def47054f73d9b3ff9ca087b825a7dcaea4a0d7907d83afa99fb56102b20b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000084d0948357fb080000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2450000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T16:12:26Z","block_height":69308343,"tx_hash":"0xec7aa6dc0e600830985939f9723b5584e5c473e10f7201bc19b0c28f167a2a2f","tx_offset":0,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T16:13:08Z","block_height":69308385,"tx_hash":"0xa682e49459a4bcbe6fbc15dafa2a775d42783e04bc45f71205e130bd7779d27c","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":376614,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:13:08Z","block_height":69308385,"tx_offset":1,"log_offset":0,"tx_hash":"0xa682e49459a4bcbe6fbc15dafa2a775d42783e04bc45f71205e130bd7779d27c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000084270860c266eab7d9","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2437782822085020268505"}]}},{"block_signed_at":"2021-09-07T16:13:08Z","block_height":69308385,"tx_offset":1,"log_offset":1,"tx_hash":"0xa682e49459a4bcbe6fbc15dafa2a775d42783e04bc45f71205e130bd7779d27c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000084270860c266eab7d9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2437782822085020268505"}]}},{"block_signed_at":"2021-09-07T16:13:08Z","block_height":69308385,"tx_offset":1,"log_offset":2,"tx_hash":"0xa682e49459a4bcbe6fbc15dafa2a775d42783e04bc45f71205e130bd7779d27c","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T16:13:08Z","block_height":69308385,"tx_offset":1,"log_offset":3,"tx_hash":"0xa682e49459a4bcbe6fbc15dafa2a775d42783e04bc45f71205e130bd7779d27c","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455504de28238ca400000000000000000000000000000000000000000000000045550588a91b65f5","decoded":null},{"block_signed_at":"2021-09-07T16:13:08Z","block_height":69308385,"tx_offset":1,"log_offset":4,"tx_hash":"0xa682e49459a4bcbe6fbc15dafa2a775d42783e04bc45f71205e130bd7779d27c","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000313c852680d97e7a9383500000000000000000000000000000000000000000003c2982d7272c8c45f1ad2","decoded":null},{"block_signed_at":"2021-09-07T16:13:08Z","block_height":69308385,"tx_offset":1,"log_offset":5,"tx_hash":"0xa682e49459a4bcbe6fbc15dafa2a775d42783e04bc45f71205e130bd7779d27c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000084270860c266eab7d9","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2437782822085020268505"}]}},{"block_signed_at":"2021-09-07T16:13:08Z","block_height":69308385,"tx_offset":1,"log_offset":6,"tx_hash":"0xa682e49459a4bcbe6fbc15dafa2a775d42783e04bc45f71205e130bd7779d27c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000084270860c266eab7d9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2437782822085020268505"}]}}]},{"block_signed_at":"2021-09-07T16:13:32Z","block_height":69308409,"tx_hash":"0x64272cd7a3280b94b3d397afede3e9e33e27b1d91d9d03af09a0f84562564e80","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:13:32Z","block_height":69308409,"tx_offset":7,"log_offset":33,"tx_hash":"0x64272cd7a3280b94b3d397afede3e9e33e27b1d91d9d03af09a0f84562564e80","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000842a0bf2ec22580000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2438000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T16:15:51Z","block_height":69308548,"tx_hash":"0xb152e43fd053ede3b81f45ca2cb633117aa749cd2093e39bf148935352887eed","tx_offset":1,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T16:16:44Z","block_height":69308601,"tx_hash":"0xc438c60b9b91e6d8c957ea3e636222c3e92641337d9b95dad6551f0a9b61cdad","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:16:44Z","block_height":69308601,"tx_offset":2,"log_offset":0,"tx_hash":"0xc438c60b9b91e6d8c957ea3e636222c3e92641337d9b95dad6551f0a9b61cdad","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000083fd45b7450db89acd","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2434773668228150893261"}]}},{"block_signed_at":"2021-09-07T16:16:44Z","block_height":69308601,"tx_offset":2,"log_offset":1,"tx_hash":"0xc438c60b9b91e6d8c957ea3e636222c3e92641337d9b95dad6551f0a9b61cdad","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000083fd45b7450db89acd","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2434773668228150893261"}]}},{"block_signed_at":"2021-09-07T16:16:44Z","block_height":69308601,"tx_offset":2,"log_offset":2,"tx_hash":"0xc438c60b9b91e6d8c957ea3e636222c3e92641337d9b95dad6551f0a9b61cdad","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T16:16:44Z","block_height":69308601,"tx_offset":2,"log_offset":3,"tx_hash":"0xc438c60b9b91e6d8c957ea3e636222c3e92641337d9b95dad6551f0a9b61cdad","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455507af546162e200000000000000000000000000000000000000000000000045550859d5593c33","decoded":null},{"block_signed_at":"2021-09-07T16:16:44Z","block_height":69308601,"tx_offset":2,"log_offset":4,"tx_hash":"0xc438c60b9b91e6d8c957ea3e636222c3e92641337d9b95dad6551f0a9b61cdad","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031455581528cd0569509500000000000000000000000000000000000000000003c21430f3c2f042410576","decoded":null},{"block_signed_at":"2021-09-07T16:16:44Z","block_height":69308601,"tx_offset":2,"log_offset":5,"tx_hash":"0xc438c60b9b91e6d8c957ea3e636222c3e92641337d9b95dad6551f0a9b61cdad","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000083fd45b7450db89acd","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2434773668228150893261"}]}},{"block_signed_at":"2021-09-07T16:16:44Z","block_height":69308601,"tx_offset":2,"log_offset":6,"tx_hash":"0xc438c60b9b91e6d8c957ea3e636222c3e92641337d9b95dad6551f0a9b61cdad","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000083fd45b7450db89acd","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2434773668228150893261"}]}}]},{"block_signed_at":"2021-09-07T16:17:07Z","block_height":69308624,"tx_hash":"0x5c125d07bd565dc2bd162c7fb26dd2c6490264c64ccb8556d9b27dd9c6cad704","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77293,"gas_spent":51529,"gas_price":25000000000,"fees_paid":"1288225000000000","gas_quote":0.002122959635296464,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:17:07Z","block_height":69308624,"tx_offset":0,"log_offset":0,"tx_hash":"0x5c125d07bd565dc2bd162c7fb26dd2c6490264c64ccb8556d9b27dd9c6cad704","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000840069ced12c2c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2435000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T16:21:17Z","block_height":69308874,"tx_hash":"0x776e8d6c84b10b13cadeffef13c0753c9486510a406c4bab069f6923594c9f50","tx_offset":4,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T16:22:17Z","block_height":69308934,"tx_hash":"0x488e1d8c6518d94496c6910191f7fd88c4627b7715d2d078715189c88341f360","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:22:17Z","block_height":69308934,"tx_offset":0,"log_offset":0,"tx_hash":"0x488e1d8c6518d94496c6910191f7fd88c4627b7715d2d078715189c88341f360","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000082323db4d6d33a7872","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2401696978092477282418"}]}},{"block_signed_at":"2021-09-07T16:22:17Z","block_height":69308934,"tx_offset":0,"log_offset":1,"tx_hash":"0x488e1d8c6518d94496c6910191f7fd88c4627b7715d2d078715189c88341f360","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000082323db4d6d33a7872","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2401696978092477282418"}]}},{"block_signed_at":"2021-09-07T16:22:17Z","block_height":69308934,"tx_offset":0,"log_offset":2,"tx_hash":"0x488e1d8c6518d94496c6910191f7fd88c4627b7715d2d078715189c88341f360","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T16:22:17Z","block_height":69308934,"tx_offset":0,"log_offset":3,"tx_hash":"0x488e1d8c6518d94496c6910191f7fd88c4627b7715d2d078715189c88341f360","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045551038b1da93c2000000000000000000000000000000000000000000000000455510e31c54a00b","decoded":null},{"block_signed_at":"2021-09-07T16:22:17Z","block_height":69308934,"tx_offset":0,"log_offset":4,"tx_hash":"0x488e1d8c6518d94496c6910191f7fd88c4627b7715d2d078715189c88341f360","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000319bdeded6c3e1614ac4f00000000000000000000000000000000000000000003bb85f67525ce448926be","decoded":null},{"block_signed_at":"2021-09-07T16:22:17Z","block_height":69308934,"tx_offset":0,"log_offset":5,"tx_hash":"0x488e1d8c6518d94496c6910191f7fd88c4627b7715d2d078715189c88341f360","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000082323db4d6d33a7872","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2401696978092477282418"}]}},{"block_signed_at":"2021-09-07T16:22:17Z","block_height":69308934,"tx_offset":0,"log_offset":6,"tx_hash":"0x488e1d8c6518d94496c6910191f7fd88c4627b7715d2d078715189c88341f360","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000082323db4d6d33a7872","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2401696978092477282418"}]}}]},{"block_signed_at":"2021-09-07T16:22:33Z","block_height":69308950,"tx_hash":"0xc397976e0fdd7ebb06e6904331976f1d9aa4568b8e7d4b67a8b18315595e201b","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:22:33Z","block_height":69308950,"tx_offset":5,"log_offset":5,"tx_hash":"0xc397976e0fdd7ebb06e6904331976f1d9aa4568b8e7d4b67a8b18315595e201b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000082367241a898480000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2402000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T16:22:53Z","block_height":69308970,"tx_hash":"0xd47a286585e269ecb603e8b87cc398ffcd4047bee01436a9b684ad89a6c9dae9","tx_offset":8,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":1,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8d953575f93590803","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000156676318566090755"}]}},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":2,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffeab6fddc85ba6175f3a4","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563938941121449018090976164"}]}},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":3,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8d953575f93590803","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000156676318566090755"}]}},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":4,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8d953575f9359080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70ae132da711ff143","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000156676318566090755"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3376538129212769300803"}]}},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":5,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053451df47ed02230","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000235014477849136"}]}},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":6,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053451df47ed02230","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000235014477849136"}]}},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":7,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000053451df47ed0223000000000000000000000000000000000000000000000000278457caf6ca3578400000000000000000000000000000000000000000000000278457e04a4d3db42","decoded":null},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":8,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000320f8567f76898a0f545200000000000000000000000000000000000000000003b2e68103924db34343ca","decoded":null},{"block_signed_at":"2021-09-07T16:29:47Z","block_height":69309384,"tx_offset":2,"log_offset":9,"tx_hash":"0x12b8078e2b3609a9b98cc7fb608647a6702a3c43729d6afc23606a44829f345a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8d953575f9359080300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70ae132da711ff143","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000156676318566090755"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3376538129212769300803"}]}}]},{"block_signed_at":"2021-09-07T16:31:12Z","block_height":69309469,"tx_hash":"0xa70b4d3f7def6d43ab758b7488e33e8e8ffa796db14c7e94798d012eb948bed5","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3377000000000000000000","value_quote":5565.203817963599,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T16:37:10Z","block_height":69309827,"tx_hash":"0x416005b20cddc78cd7e663d4dc7e532d5fb6dab928b13895669d184810a64d3b","tx_offset":5,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:37:10Z","block_height":69309827,"tx_offset":5,"log_offset":10,"tx_hash":"0x416005b20cddc78cd7e663d4dc7e532d5fb6dab928b13895669d184810a64d3b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8abd8cb2a79272000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996879590480000000000"}]}}]},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461139,"gas_spent":288030,"gas_price":25000000000,"fees_paid":"7200750000000000","gas_quote":0.011866639440983533,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":0,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8abd8cb2a79272000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996879590480000000000"}]}},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":1,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe9de5203ba8fe84ed3a4","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563934944241858538090976164"}]}},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":2,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8abd8cb2a79272000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996879590480000000000"}]}},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":3,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8abd8cb2a7927200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4047d668d55c3ff0c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996879590480000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3320737460773175164684"}]}},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":4,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005333a7377cda8e00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5995319385720000000"}]}},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":5,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005333a7377cda8e00","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5995319385720000000"}]}},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":6,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005333a7377cda8e00000000000000000000000000000000000000000000000002784588d1c9f6a79600000000000000000000000000000000000000000000000278458a266925b44f","decoded":null},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":7,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031aa720a97830211c17f500000000000000000000000000000000000000000003ba6d9e8cb6d3f41c8b97","decoded":null},{"block_signed_at":"2021-09-07T16:40:51Z","block_height":69310048,"tx_offset":0,"log_offset":8,"tx_hash":"0xc9fa798df80dd86bd2853755b27ae16edff4f456d4e62f0191e694252b90a8f7","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8abd8cb2a7927200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4047d668d55c3ff0c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996879590480000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3320737460773175164684"}]}}]},{"block_signed_at":"2021-09-07T16:41:39Z","block_height":69310096,"tx_hash":"0xcd36c5660a10d5b5633792d337571ed18d03dcf36a44015064f4e63c2cec7e35","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3320000000000000000000","value_quote":5471.269373893738,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T16:47:12Z","block_height":69310429,"tx_hash":"0x35539d339fb21430d9c7e11093a4d387b8daf58cb819efa3e854952d09249f3c","tx_offset":5,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:47:12Z","block_height":69310429,"tx_offset":5,"log_offset":43,"tx_hash":"0x35539d339fb21430d9c7e11093a4d387b8daf58cb819efa3e854952d09249f3c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T16:54:26Z","block_height":69310863,"tx_hash":"0xfa0cadb7fdfa676a97466d52db7eda1c9d974cff9d13b32a0cf29ebffd8c84f2","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:54:26Z","block_height":69310863,"tx_offset":2,"log_offset":2,"tx_hash":"0xfa0cadb7fdfa676a97466d52db7eda1c9d974cff9d13b32a0cf29ebffd8c84f2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000081d6834da2460dd04f","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2395087269213953183823"}]}},{"block_signed_at":"2021-09-07T16:54:26Z","block_height":69310863,"tx_offset":2,"log_offset":3,"tx_hash":"0xfa0cadb7fdfa676a97466d52db7eda1c9d974cff9d13b32a0cf29ebffd8c84f2","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000081d6834da2460dd04f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2395087269213953183823"}]}},{"block_signed_at":"2021-09-07T16:54:26Z","block_height":69310863,"tx_offset":2,"log_offset":4,"tx_hash":"0xfa0cadb7fdfa676a97466d52db7eda1c9d974cff9d13b32a0cf29ebffd8c84f2","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T16:54:26Z","block_height":69310863,"tx_offset":2,"log_offset":5,"tx_hash":"0xfa0cadb7fdfa676a97466d52db7eda1c9d974cff9d13b32a0cf29ebffd8c84f2","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455532fbba43012e000000000000000000000000000000000000000000000000455533a476550164","decoded":null},{"block_signed_at":"2021-09-07T16:54:26Z","block_height":69310863,"tx_offset":2,"log_offset":6,"tx_hash":"0xfa0cadb7fdfa676a97466d52db7eda1c9d974cff9d13b32a0cf29ebffd8c84f2","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031ad6121b7a1cf3e4678300000000000000000000000000000000000000000003ba35407062ccb8109f28","decoded":null},{"block_signed_at":"2021-09-07T16:54:26Z","block_height":69310863,"tx_offset":2,"log_offset":7,"tx_hash":"0xfa0cadb7fdfa676a97466d52db7eda1c9d974cff9d13b32a0cf29ebffd8c84f2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000081d6834da2460dd04f","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2395087269213953183823"}]}},{"block_signed_at":"2021-09-07T16:54:26Z","block_height":69310863,"tx_offset":2,"log_offset":8,"tx_hash":"0xfa0cadb7fdfa676a97466d52db7eda1c9d974cff9d13b32a0cf29ebffd8c84f2","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000081d6834da2460dd04f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2395087269213953183823"}]}}]},{"block_signed_at":"2021-09-07T16:55:11Z","block_height":69310908,"tx_hash":"0x074977e99c9f10cbe0e4a86a1c1b33e76818fdb52352ccd6d3bd9cd7ce534e09","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:55:11Z","block_height":69310908,"tx_offset":5,"log_offset":0,"tx_hash":"0x074977e99c9f10cbe0e4a86a1c1b33e76818fdb52352ccd6d3bd9cd7ce534e09","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000081d54d42bf048c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2395000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T16:55:50Z","block_height":69310947,"tx_hash":"0xaab5236299470d18ba529208ab5e3a36430a1d8fdc8cd6a0c10085e8685fe760","tx_offset":10,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T16:59:16Z","block_height":69311153,"tx_hash":"0x5b0d46e712f47bb574d3ecf78efe12cbeddf0a9892dba88940a95424192b0062","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T16:59:16Z","block_height":69311153,"tx_offset":1,"log_offset":2,"tx_hash":"0x5b0d46e712f47bb574d3ecf78efe12cbeddf0a9892dba88940a95424192b0062","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000807817ce269970d612","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2369836853309016692242"}]}},{"block_signed_at":"2021-09-07T16:59:16Z","block_height":69311153,"tx_offset":1,"log_offset":3,"tx_hash":"0x5b0d46e712f47bb574d3ecf78efe12cbeddf0a9892dba88940a95424192b0062","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000807817ce269970d612","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2369836853309016692242"}]}},{"block_signed_at":"2021-09-07T16:59:16Z","block_height":69311153,"tx_offset":1,"log_offset":4,"tx_hash":"0x5b0d46e712f47bb574d3ecf78efe12cbeddf0a9892dba88940a95424192b0062","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T16:59:16Z","block_height":69311153,"tx_offset":1,"log_offset":5,"tx_hash":"0x5b0d46e712f47bb574d3ecf78efe12cbeddf0a9892dba88940a95424192b0062","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455539969f5698e700000000000000000000000000000000000000000000000045553a3f8d8dda98","decoded":null},{"block_signed_at":"2021-09-07T16:59:16Z","block_height":69311153,"tx_offset":1,"log_offset":6,"tx_hash":"0x5b0d46e712f47bb574d3ecf78efe12cbeddf0a9892dba88940a95424192b0062","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031f0eeea77e001d89a10300000000000000000000000000000000000000000003b52a862609ed56c93996","decoded":null},{"block_signed_at":"2021-09-07T16:59:16Z","block_height":69311153,"tx_offset":1,"log_offset":7,"tx_hash":"0x5b0d46e712f47bb574d3ecf78efe12cbeddf0a9892dba88940a95424192b0062","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000807817ce269970d612","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2369836853309016692242"}]}},{"block_signed_at":"2021-09-07T16:59:16Z","block_height":69311153,"tx_offset":1,"log_offset":8,"tx_hash":"0x5b0d46e712f47bb574d3ecf78efe12cbeddf0a9892dba88940a95424192b0062","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000807817ce269970d612","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2369836853309016692242"}]}}]},{"block_signed_at":"2021-09-07T17:00:10Z","block_height":69311207,"tx_hash":"0xd334e8e015cb8531599f6614d51fd4e227d22317f9fb2f3876b689421c19f61f","tx_offset":11,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:00:10Z","block_height":69311207,"tx_offset":11,"log_offset":72,"tx_hash":"0xd334e8e015cb8531599f6614d51fd4e227d22317f9fb2f3876b689421c19f61f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000080bfbefcb5f0bc0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2375000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:00:29Z","block_height":69311226,"tx_hash":"0xd2bbd5ba714bee1d88e70f1a7ce7e9e34b29e5396b24bdd0da24d45202521120","tx_offset":1,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:03:25Z","block_height":69311402,"tx_hash":"0xaef0e47e83ed2820202f5ad85f9a3ce6849f4e1f29ab868fdd9102d29292c206","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:03:25Z","block_height":69311402,"tx_offset":4,"log_offset":37,"tx_hash":"0xaef0e47e83ed2820202f5ad85f9a3ce6849f4e1f29ab868fdd9102d29292c206","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008005dd8bbe68de6b9c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2361605889024784755612"}]}},{"block_signed_at":"2021-09-07T17:03:25Z","block_height":69311402,"tx_offset":4,"log_offset":38,"tx_hash":"0xaef0e47e83ed2820202f5ad85f9a3ce6849f4e1f29ab868fdd9102d29292c206","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008005dd8bbe68de6b9c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2361605889024784755612"}]}},{"block_signed_at":"2021-09-07T17:03:25Z","block_height":69311402,"tx_offset":4,"log_offset":39,"tx_hash":"0xaef0e47e83ed2820202f5ad85f9a3ce6849f4e1f29ab868fdd9102d29292c206","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:03:25Z","block_height":69311402,"tx_offset":4,"log_offset":40,"tx_hash":"0xaef0e47e83ed2820202f5ad85f9a3ce6849f4e1f29ab868fdd9102d29292c206","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045553bc5f07c468c00000000000000000000000000000000000000000000000045553c6edeb3883d","decoded":null},{"block_signed_at":"2021-09-07T17:03:25Z","block_height":69311402,"tx_offset":4,"log_offset":41,"tx_hash":"0xaef0e47e83ed2820202f5ad85f9a3ce6849f4e1f29ab868fdd9102d29292c206","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000320833992068fc65b1f2b00000000000000000000000000000000000000000003b397816478fff14d6c74","decoded":null},{"block_signed_at":"2021-09-07T17:03:25Z","block_height":69311402,"tx_offset":4,"log_offset":42,"tx_hash":"0xaef0e47e83ed2820202f5ad85f9a3ce6849f4e1f29ab868fdd9102d29292c206","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008005dd8bbe68de6b9c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2361605889024784755612"}]}},{"block_signed_at":"2021-09-07T17:03:25Z","block_height":69311402,"tx_offset":4,"log_offset":43,"tx_hash":"0xaef0e47e83ed2820202f5ad85f9a3ce6849f4e1f29ab868fdd9102d29292c206","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008005dd8bbe68de6b9c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2361605889024784755612"}]}}]},{"block_signed_at":"2021-09-07T17:03:44Z","block_height":69311421,"tx_hash":"0xd91533ab370542699dad002a422e1c68c773c4ccd823491d412b8d5e1f91def1","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:03:44Z","block_height":69311421,"tx_offset":0,"log_offset":0,"tx_hash":"0xd91533ab370542699dad002a422e1c68c773c4ccd823491d412b8d5e1f91def1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007ffd74fee2c9440000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2361000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:05:37Z","block_height":69311534,"tx_hash":"0xcf478f8487f3e85ff932d3fea9d59e817aff3c2afb2a20f51255fb6223b5a0dc","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:08:02Z","block_height":69311679,"tx_hash":"0xcfc9bcf45025ea87731c1b9fdf29d95cdf40a39f919eb50374b3527d44cc49e4","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:08:02Z","block_height":69311679,"tx_offset":4,"log_offset":1,"tx_hash":"0xcfc9bcf45025ea87731c1b9fdf29d95cdf40a39f919eb50374b3527d44cc49e4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007dacc926c50604fa0d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2318293534486187801101"}]}},{"block_signed_at":"2021-09-07T17:08:02Z","block_height":69311679,"tx_offset":4,"log_offset":2,"tx_hash":"0xcfc9bcf45025ea87731c1b9fdf29d95cdf40a39f919eb50374b3527d44cc49e4","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007dacc926c50604fa0d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2318293534486187801101"}]}},{"block_signed_at":"2021-09-07T17:08:02Z","block_height":69311679,"tx_offset":4,"log_offset":3,"tx_hash":"0xcfc9bcf45025ea87731c1b9fdf29d95cdf40a39f919eb50374b3527d44cc49e4","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:08:02Z","block_height":69311679,"tx_offset":4,"log_offset":4,"tx_hash":"0xcfc9bcf45025ea87731c1b9fdf29d95cdf40a39f919eb50374b3527d44cc49e4","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045554767f5b72c6800000000000000000000000000000000000000000000000045554810c2679036","decoded":null},{"block_signed_at":"2021-09-07T17:08:02Z","block_height":69311679,"tx_offset":4,"log_offset":5,"tx_hash":"0xcfc9bcf45025ea87731c1b9fdf29d95cdf40a39f919eb50374b3527d44cc49e4","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000327f9a566787f5f669e1f00000000000000000000000000000000000000000003aae39821c658bf2e00fa","decoded":null},{"block_signed_at":"2021-09-07T17:08:02Z","block_height":69311679,"tx_offset":4,"log_offset":6,"tx_hash":"0xcfc9bcf45025ea87731c1b9fdf29d95cdf40a39f919eb50374b3527d44cc49e4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007dacc926c50604fa0d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2318293534486187801101"}]}},{"block_signed_at":"2021-09-07T17:08:02Z","block_height":69311679,"tx_offset":4,"log_offset":7,"tx_hash":"0xcfc9bcf45025ea87731c1b9fdf29d95cdf40a39f919eb50374b3527d44cc49e4","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007dacc926c50604fa0d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2318293534486187801101"}]}}]},{"block_signed_at":"2021-09-07T17:08:16Z","block_height":69311693,"tx_hash":"0xca5bfa345f52b82dabdcaa7a11125809d7718b7b4d7e24810af94bad1032128e","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:08:16Z","block_height":69311693,"tx_offset":1,"log_offset":2,"tx_hash":"0xca5bfa345f52b82dabdcaa7a11125809d7718b7b4d7e24810af94bad1032128e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007da8b64eb5ab780000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2318000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:10:44Z","block_height":69311841,"tx_hash":"0xc4eab4d8a1e114e9c3775a2c10f91c357034d8a375cd247b3c4df44828350ad0","tx_offset":6,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":2,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d865ae1d87c14e0c0a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3991823546033942432778"}]}},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":3,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe905ec559d082700c79a","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563930952418312504148543386"}]}},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":4,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d865ae1d87c14e0c0a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3991823546033942432778"}]}},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":5,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d865ae1d87c14e0c0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd07dcc1b8686732c9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3991823546033942432778"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3782149075761369658057"}]}},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":6,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005318b58c5d170771","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5987735319050913649"}]}},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":7,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005318b58c5d170771","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5987735319050913649"}]}},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":8,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005318b58c5d1707710000000000000000000000000000000000000000000000027845a648ca57268a0000000000000000000000000000000000000000000000027845a799b30e215a","decoded":null},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":9,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000350a5147501eee211a854000000000000000000000000000000000000000000037dd8feb2f43095b5b6cd","decoded":null},{"block_signed_at":"2021-09-07T17:10:54Z","block_height":69311851,"tx_offset":7,"log_offset":10,"tx_hash":"0x9114606250534617379fdae83dbae4b0d28903c35a94779e47be2401e118c903","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d865ae1d87c14e0c0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd07dcc1b8686732c9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3991823546033942432778"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3782149075761369658057"}]}}]},{"block_signed_at":"2021-09-07T17:11:19Z","block_height":69311876,"tx_hash":"0x8659aad69ae046f5cb4ea5039c726519de907e2d37e4f237163025a1f7ca2fb4","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","to_address_label":null,"value":"900000000000000000000","value_quote":1483.1754326820374,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:11:29Z","block_height":69311886,"tx_hash":"0x1b745d0149869ab0075f5ef7adc0a6851be5f6477346b0e47c1b1b079afded23","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"2883000000000000000000","value_quote":4751.105302691461,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:14:20Z","block_height":69312057,"tx_hash":"0xb774e2b2e9e783015b1f30fa1fe1834f9833b410e1c9b54b4e966b2b6a17532c","tx_offset":5,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:14:20Z","block_height":69312057,"tx_offset":5,"log_offset":8,"tx_hash":"0xb774e2b2e9e783015b1f30fa1fe1834f9833b410e1c9b54b4e966b2b6a17532c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:14:45Z","block_height":69312082,"tx_hash":"0xb06bc53cdd88ec33f8706e375e20ab6ddf1a3dc8ebb509ef3ab8757c04c46f47","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2005638790536891710620","value_quote":3305.237978842703,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:14:45Z","block_height":69312082,"tx_offset":0,"log_offset":0,"tx_hash":"0xb06bc53cdd88ec33f8706e375e20ab6ddf1a3dc8ebb509ef3ab8757c04c46f47","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007329515ab6ae72fdf5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2124352829045924363765"}]}},{"block_signed_at":"2021-09-07T17:14:45Z","block_height":69312082,"tx_offset":0,"log_offset":1,"tx_hash":"0xb06bc53cdd88ec33f8706e375e20ab6ddf1a3dc8ebb509ef3ab8757c04c46f47","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006cb9d45da9df83bc9c0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007329515ab6ae72fdf5","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2005638790536891710620"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2124352829045924363765"}]}},{"block_signed_at":"2021-09-07T17:14:45Z","block_height":69312082,"tx_offset":0,"log_offset":2,"tx_hash":"0xb06bc53cdd88ec33f8706e375e20ab6ddf1a3dc8ebb509ef3ab8757c04c46f47","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029c030c7ce8b13dd","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3008458185805337565"}]}},{"block_signed_at":"2021-09-07T17:14:45Z","block_height":69312082,"tx_offset":0,"log_offset":3,"tx_hash":"0xb06bc53cdd88ec33f8706e375e20ab6ddf1a3dc8ebb509ef3ab8757c04c46f47","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029c030c7ce8b13de000000000000000000000000000000000000000000000000455596747a076b4b0000000000000000000000000000000000000000000000004555971dc08d3940","decoded":null},{"block_signed_at":"2021-09-07T17:14:45Z","block_height":69312082,"tx_offset":0,"log_offset":4,"tx_hash":"0xb06bc53cdd88ec33f8706e375e20ab6ddf1a3dc8ebb509ef3ab8757c04c46f47","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000034d3587c38e1cbe3f1eb700000000000000000000000000000000000000000003817b28c1217d0abebc55","decoded":null},{"block_signed_at":"2021-09-07T17:14:45Z","block_height":69312082,"tx_offset":0,"log_offset":5,"tx_hash":"0xb06bc53cdd88ec33f8706e375e20ab6ddf1a3dc8ebb509ef3ab8757c04c46f47","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007329515ab6ae72fdf5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2124352829045924363765"}]}},{"block_signed_at":"2021-09-07T17:14:45Z","block_height":69312082,"tx_offset":0,"log_offset":6,"tx_hash":"0xb06bc53cdd88ec33f8706e375e20ab6ddf1a3dc8ebb509ef3ab8757c04c46f47","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006cb9d45da9df83bc9c0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007329515ab6ae72fdf5","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2005638790536891710620"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2124352829045924363765"}]}}]},{"block_signed_at":"2021-09-07T17:15:29Z","block_height":69312126,"tx_hash":"0xaec22ee9354c9220f411927830f9a1ca5b31526fd43c9e54742bcaa6fa9a8df6","tx_offset":3,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"900000000000000000000","value_quote":1483.1754326820374,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461427,"gas_spent":288222,"gas_price":25000000000,"fees_paid":"7205550000000000","gas_quote":0.011874549709957837,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":24,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000014bc8f536ff8b62fdf5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6120352829045924363765"}]}},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":25,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe7ba236066089b9dc9a5","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563924832065483458224179621"}]}},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":26,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000014bc8f536ff8b62fdf5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6120352829045924363765"}]}},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":27,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000014bc8f536ff8b62fdf50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139080dd67d0d5924f8","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"6120352829045924363765"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"5774411250830673519864"}]}},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":28,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000007f67cab4dd025311","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"9180529243568886545"}]}},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":29,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000007f67cab4dd025312","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"9180529243568886546"}]}},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":30,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000007f67cab4dd0253120000000000000000000000000000000000000000000000027845b59930df77750000000000000000000000000000000000000000000000027845b79dbf531dbe","decoded":null},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":31,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000353ea2fa2e0fcf1e6570200000000000000000000000000000000000000000003858929af9c092b8f4609","decoded":null},{"block_signed_at":"2021-09-07T17:15:42Z","block_height":69312139,"tx_offset":4,"log_offset":32,"tx_hash":"0xdc3e149802bd60a7bc32af0c9d205daeca0bc7410c27c6edda71d417d2bf0247","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000014bc8f536ff8b62fdf50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139080dd67d0d5924f8","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"6120352829045924363765"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"5774411250830673519864"}]}}]},{"block_signed_at":"2021-09-07T17:16:28Z","block_height":69312185,"tx_hash":"0x1243454b258fd41e17157f9c61f5a06578fcd8218123b5a8e37e4a7f9088bfd4","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"4670000000000000000000","value_quote":7696.032522916794,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:19:21Z","block_height":69312358,"tx_hash":"0xae706c580874dbcf5d3fd7ace005c9066bf377df7941c2a655fb0bcc44806ddf","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:19:21Z","block_height":69312358,"tx_offset":0,"log_offset":0,"tx_hash":"0xae706c580874dbcf5d3fd7ace005c9066bf377df7941c2a655fb0bcc44806ddf","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":67,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":68,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe6e183bc89bfbeadc9a5","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563920836065483458224179621"}]}},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":69,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":70,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7a808cd525b4f6127","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3683010224019989291303"}]}},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":71,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":72,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":73,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027845cd712b1189f10000000000000000000000000000000000000000000000027845cec26e056bfb","decoded":null},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":74,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000034c56fcdca0e07df21dfb0000000000000000000000000000000000000000000392305b4f6672b90de123","decoded":null},{"block_signed_at":"2021-09-07T17:19:36Z","block_height":69312373,"tx_offset":3,"log_offset":75,"tx_hash":"0x1dc467214156d45b1408cc5cace7188314666d61bb6ef56f8a60884aca17555c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7a808cd525b4f6127","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3683010224019989291303"}]}}]},{"block_signed_at":"2021-09-07T17:20:36Z","block_height":69312433,"tx_hash":"0xc987bd8a8d28f67dbb7b54ee96a0b31645a6aa7abc7a31712f18aa95f6086425","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3682000000000000000000","value_quote":6067.835492372513,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:26:16Z","block_height":69312773,"tx_hash":"0x121268419dc07b93fda9d99c40bd32043b7a0c837c908de24d2b8ed7912ce4a0","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:26:16Z","block_height":69312773,"tx_offset":6,"log_offset":19,"tx_hash":"0x121268419dc07b93fda9d99c40bd32043b7a0c837c908de24d2b8ed7912ce4a0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000005b8253d9f491500000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"1688044800000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:26:22Z","block_height":69312779,"tx_hash":"0x938aece340ef037bd3423808a4201c5e7b26cf2f0f2c8da7b95d1320805e0fbd","tx_offset":18,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":51137,"gas_price":25000000000,"fees_paid":"1278425000000000","gas_quote":0.0021068095028072592,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:26:22Z","block_height":69312779,"tx_offset":18,"log_offset":17,"tx_hash":"0x938aece340ef037bd3423808a4201c5e7b26cf2f0f2c8da7b95d1320805e0fbd","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007ce5cd2785ae100000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2303955200000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:26:49Z","block_height":69312806,"tx_hash":"0x6c682684d121c22026c7304b104791dea1e3f9164e482f8529c007958a19a683","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:26:49Z","block_height":69312806,"tx_offset":0,"log_offset":0,"tx_hash":"0x6c682684d121c22026c7304b104791dea1e3f9164e482f8529c007958a19a683","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000079103cb6bd3cb8bf8d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2233226043845949046669"}]}},{"block_signed_at":"2021-09-07T17:26:49Z","block_height":69312806,"tx_offset":0,"log_offset":1,"tx_hash":"0x6c682684d121c22026c7304b104791dea1e3f9164e482f8529c007958a19a683","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000079103cb6bd3cb8bf8d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2233226043845949046669"}]}},{"block_signed_at":"2021-09-07T17:26:49Z","block_height":69312806,"tx_offset":0,"log_offset":2,"tx_hash":"0x6c682684d121c22026c7304b104791dea1e3f9164e482f8529c007958a19a683","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:26:49Z","block_height":69312806,"tx_offset":0,"log_offset":3,"tx_hash":"0x6c682684d121c22026c7304b104791dea1e3f9164e482f8529c007958a19a683","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004555aa5de07bbdb90000000000000000000000000000000000000000000000004555ab06a0c7bc3c","decoded":null},{"block_signed_at":"2021-09-07T17:26:49Z","block_height":69312806,"tx_offset":0,"log_offset":4,"tx_hash":"0x6c682684d121c22026c7304b104791dea1e3f9164e482f8529c007958a19a683","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033c99400cf344950bffa4000000000000000000000000000000000000000000039f88ff383e1764d6c1d2","decoded":null},{"block_signed_at":"2021-09-07T17:26:49Z","block_height":69312806,"tx_offset":0,"log_offset":5,"tx_hash":"0x6c682684d121c22026c7304b104791dea1e3f9164e482f8529c007958a19a683","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000079103cb6bd3cb8bf8d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2233226043845949046669"}]}},{"block_signed_at":"2021-09-07T17:26:49Z","block_height":69312806,"tx_offset":0,"log_offset":6,"tx_hash":"0x6c682684d121c22026c7304b104791dea1e3f9164e482f8529c007958a19a683","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000079103cb6bd3cb8bf8d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2233226043845949046669"}]}}]},{"block_signed_at":"2021-09-07T17:27:08Z","block_height":69312825,"tx_hash":"0xff26a83e3a780fede28c4b377a7a143bbaf397c1abe86997b14430ba683505c8","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:27:08Z","block_height":69312825,"tx_offset":5,"log_offset":43,"tx_hash":"0xff26a83e3a780fede28c4b377a7a143bbaf397c1abe86997b14430ba683505c8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000789e13ef71dc240000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2225000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:29:22Z","block_height":69312959,"tx_hash":"0xb7fb4b5cc4f4bfafd0ae42ce0e1a12bb14b0ce66225d8d4f9eed3bf5c04ad7dd","tx_offset":5,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":0,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8da49c8c59ff4bf8d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000226043845949046669"}]}},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":1,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe608a972c0fa1eb90a18","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563916835839439612275132952"}]}},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":2,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8da49c8c59ff4bf8d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000226043845949046669"}]}},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":3,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8da49c8c59ff4bf8d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1d420f788e8f355de","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000226043845949046669"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3575507095528634799582"}]}},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":4,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053457c96d30e51b2","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000339065768923570"}]}},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":5,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053457c96d30e51b2","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000339065768923570"}]}},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":6,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000053457c96d30e51b20000000000000000000000000000000000000000000000027845e92130297c980000000000000000000000000000000000000000000000027845ea72b5a36a6d","decoded":null},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":7,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033db1c97ccfd52094912a000000000000000000000000000000000000000000039e4f60cd959a296b5789","decoded":null},{"block_signed_at":"2021-09-07T17:31:30Z","block_height":69313087,"tx_offset":0,"log_offset":8,"tx_hash":"0x044f7f240e6a6ce15b45a08a15aaf1a4a1aeec9b3a38461ba6a18bda8db75867","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8da49c8c59ff4bf8d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1d420f788e8f355de","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000226043845949046669"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3575507095528634799582"}]}}]},{"block_signed_at":"2021-09-07T17:33:25Z","block_height":69313202,"tx_hash":"0x063ffe7108a09d7b04e68062342cfe4cc01f539e30777da370dc1e6565115362","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3575000000000000000000","value_quote":5891.502413153649,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:36:05Z","block_height":69313362,"tx_hash":"0xd9f65c1e7721d71d04ad3387323782d8983bdc91540cfd89070a9829b4055e60","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.01127584122696519,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:36:05Z","block_height":69313362,"tx_offset":0,"log_offset":0,"tx_hash":"0xd9f65c1e7721d71d04ad3387323782d8983bdc91540cfd89070a9829b4055e60","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000077dff57b59ee3b6add","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2211300485237367859933"}]}},{"block_signed_at":"2021-09-07T17:36:05Z","block_height":69313362,"tx_offset":0,"log_offset":1,"tx_hash":"0xd9f65c1e7721d71d04ad3387323782d8983bdc91540cfd89070a9829b4055e60","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000077dff57b59ee3b6add","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2211300485237367859933"}]}},{"block_signed_at":"2021-09-07T17:36:05Z","block_height":69313362,"tx_offset":0,"log_offset":2,"tx_hash":"0xd9f65c1e7721d71d04ad3387323782d8983bdc91540cfd89070a9829b4055e60","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:36:05Z","block_height":69313362,"tx_offset":0,"log_offset":3,"tx_hash":"0xd9f65c1e7721d71d04ad3387323782d8983bdc91540cfd89070a9829b4055e60","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004555b667a709a68d0000000000000000000000000000000000000000000000004555b710651f3dd9","decoded":null},{"block_signed_at":"2021-09-07T17:36:05Z","block_height":69313362,"tx_offset":0,"log_offset":4,"tx_hash":"0xd9f65c1e7721d71d04ad3387323782d8983bdc91540cfd89070a9829b4055e60","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000340b383baa4c89fa6db02000000000000000000000000000000000000000000039afa780fdd1a4542238c","decoded":null},{"block_signed_at":"2021-09-07T17:36:05Z","block_height":69313362,"tx_offset":0,"log_offset":5,"tx_hash":"0xd9f65c1e7721d71d04ad3387323782d8983bdc91540cfd89070a9829b4055e60","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000077dff57b59ee3b6add","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2211300485237367859933"}]}},{"block_signed_at":"2021-09-07T17:36:05Z","block_height":69313362,"tx_offset":0,"log_offset":6,"tx_hash":"0xd9f65c1e7721d71d04ad3387323782d8983bdc91540cfd89070a9829b4055e60","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000077dff57b59ee3b6add","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2211300485237367859933"}]}}]},{"block_signed_at":"2021-09-07T17:38:15Z","block_height":69313492,"tx_hash":"0x738d30b0e25e954f196127a03b1ca98f8505a92f520e37c56d19137ca4ac946f","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"200000000000000000000","value_quote":329.5945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:39:17Z","block_height":69313554,"tx_hash":"0x92f946af5aee0b615baae92d944433483834bfcab174741812b2863e762ace89","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":51137,"gas_price":25000000000,"fees_paid":"1278425000000000","gas_quote":0.0021068095028072592,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:39:17Z","block_height":69313554,"tx_offset":3,"log_offset":12,"tx_hash":"0x92f946af5aee0b615baae92d944433483834bfcab174741812b2863e762ace89","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:39:27Z","block_height":69313564,"tx_hash":"0xa2c8ce2c44d05a7660f89876025bd77b1e416f05882a41a0bdc6b88909df7c33","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:39:27Z","block_height":69313564,"tx_offset":0,"log_offset":0,"tx_hash":"0xa2c8ce2c44d05a7660f89876025bd77b1e416f05882a41a0bdc6b88909df7c33","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000077a44716d0171c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2207000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:42:48Z","block_height":69313765,"tx_hash":"0xb2af1e34d8b2cb9f3becb7e7303180f6ff42e5d1ead3738ca9ee71e07844313e","tx_offset":1,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:42:59Z","block_height":69313776,"tx_hash":"0xe6fd80d640e5341dea2b7e1e5861de4fab702a70be11225fe9bd52f1768b9610","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:42:59Z","block_height":69313776,"tx_offset":0,"log_offset":0,"tx_hash":"0xe6fd80d640e5341dea2b7e1e5861de4fab702a70be11225fe9bd52f1768b9610","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007666633dc6714fe57f","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2184093609234803975551"}]}},{"block_signed_at":"2021-09-07T17:42:59Z","block_height":69313776,"tx_offset":0,"log_offset":1,"tx_hash":"0xe6fd80d640e5341dea2b7e1e5861de4fab702a70be11225fe9bd52f1768b9610","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007666633dc6714fe57f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2184093609234803975551"}]}},{"block_signed_at":"2021-09-07T17:42:59Z","block_height":69313776,"tx_offset":0,"log_offset":2,"tx_hash":"0xe6fd80d640e5341dea2b7e1e5861de4fab702a70be11225fe9bd52f1768b9610","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:42:59Z","block_height":69313776,"tx_offset":0,"log_offset":3,"tx_hash":"0xe6fd80d640e5341dea2b7e1e5861de4fab702a70be11225fe9bd52f1768b9610","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004555c2b660dd424a0000000000000000000000000000000000000000000000004555c35f1ef2d996","decoded":null},{"block_signed_at":"2021-09-07T17:42:59Z","block_height":69313776,"tx_offset":0,"log_offset":4,"tx_hash":"0xe6fd80d640e5341dea2b7e1e5861de4fab702a70be11225fe9bd52f1768b9610","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000345deca3c214980e15ab9000000000000000000000000000000000000000000039548c7935054edcc3bbb","decoded":null},{"block_signed_at":"2021-09-07T17:42:59Z","block_height":69313776,"tx_offset":0,"log_offset":5,"tx_hash":"0xe6fd80d640e5341dea2b7e1e5861de4fab702a70be11225fe9bd52f1768b9610","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007666633dc6714fe57f","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2184093609234803975551"}]}},{"block_signed_at":"2021-09-07T17:42:59Z","block_height":69313776,"tx_offset":0,"log_offset":6,"tx_hash":"0xe6fd80d640e5341dea2b7e1e5861de4fab702a70be11225fe9bd52f1768b9610","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007666633dc6714fe57f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2184093609234803975551"}]}}]},{"block_signed_at":"2021-09-07T17:43:11Z","block_height":69313788,"tx_hash":"0x7a7d1c6af39d899e86ab77f273e39c0a7175959fc1293ae4f7ff3a6d25674991","tx_offset":3,"successful":true,"from_address":"0x4496f06d8bb0b234057f35c4568aa0c2b0e949f3","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"1799000000000000000000","value_quote":2964.7028926610947,"gas_offered":1000000,"gas_spent":31000,"gas_price":25000000000,"fees_paid":"775000000000000","gas_quote":0.0012771788448095321,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:43:12Z","block_height":69313789,"tx_hash":"0x22b154f8e1a5ecb85e6764b2e28fe6588cbe5227bcc7abfb0623af96ba507202","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:43:12Z","block_height":69313789,"tx_offset":0,"log_offset":0,"tx_hash":"0x22b154f8e1a5ecb85e6764b2e28fe6588cbe5227bcc7abfb0623af96ba507202","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000766516acac0d200000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2184000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:48:06Z","block_height":69314083,"tx_hash":"0xdc5d1049e27ad2cd9673879a7171df8c218c2c102f5a6b58534d42b920918691","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:48:06Z","block_height":69314083,"tx_offset":2,"log_offset":3,"tx_hash":"0xdc5d1049e27ad2cd9673879a7171df8c218c2c102f5a6b58534d42b920918691","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000075c129f768b2923d9e","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2172187984776427355550"}]}},{"block_signed_at":"2021-09-07T17:48:06Z","block_height":69314083,"tx_offset":2,"log_offset":4,"tx_hash":"0xdc5d1049e27ad2cd9673879a7171df8c218c2c102f5a6b58534d42b920918691","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000075c129f768b2923d9e","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2172187984776427355550"}]}},{"block_signed_at":"2021-09-07T17:48:06Z","block_height":69314083,"tx_offset":2,"log_offset":5,"tx_hash":"0xdc5d1049e27ad2cd9673879a7171df8c218c2c102f5a6b58534d42b920918691","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:48:06Z","block_height":69314083,"tx_offset":2,"log_offset":6,"tx_hash":"0xdc5d1049e27ad2cd9673879a7171df8c218c2c102f5a6b58534d42b920918691","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004555c7f9fbdbb3aa0000000000000000000000000000000000000000000000004555c8a2fd9ed9c6","decoded":null},{"block_signed_at":"2021-09-07T17:48:06Z","block_height":69314083,"tx_offset":2,"log_offset":7,"tx_hash":"0xdc5d1049e27ad2cd9673879a7171df8c218c2c102f5a6b58534d42b920918691","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000034829a7aaa9d186d344000000000000000000000000000000000000000000000392c80b4e27d0e772623c","decoded":null},{"block_signed_at":"2021-09-07T17:48:06Z","block_height":69314083,"tx_offset":2,"log_offset":8,"tx_hash":"0xdc5d1049e27ad2cd9673879a7171df8c218c2c102f5a6b58534d42b920918691","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000075c129f768b2923d9e","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2172187984776427355550"}]}},{"block_signed_at":"2021-09-07T17:48:06Z","block_height":69314083,"tx_offset":2,"log_offset":9,"tx_hash":"0xdc5d1049e27ad2cd9673879a7171df8c218c2c102f5a6b58534d42b920918691","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000075c129f768b2923d9e","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2172187984776427355550"}]}}]},{"block_signed_at":"2021-09-07T17:48:21Z","block_height":69314098,"tx_hash":"0x8b4a93214af3bb11bce878310821cdbca464b8cb43b139fcaa006e336ca799d2","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:48:21Z","block_height":69314098,"tx_offset":1,"log_offset":0,"tx_hash":"0x8b4a93214af3bb11bce878310821cdbca464b8cb43b139fcaa006e336ca799d2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000075be8e1c4034700000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2172000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:51:36Z","block_height":69314293,"tx_hash":"0x904887a1d29e9a4467b4c6e2e1210669b3fbcfa57775d8835815dda89f8e4e3c","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T17:56:42Z","block_height":69314599,"tx_hash":"0x2fe4fff6ff068ddddc76afce66b9613ade3d9e6174450dd8010d73c8c7634f93","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:56:42Z","block_height":69314599,"tx_offset":6,"log_offset":1,"tx_hash":"0x2fe4fff6ff068ddddc76afce66b9613ade3d9e6174450dd8010d73c8c7634f93","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000747e8426f940459381","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2148938766947979727745"}]}},{"block_signed_at":"2021-09-07T17:56:42Z","block_height":69314599,"tx_offset":6,"log_offset":2,"tx_hash":"0x2fe4fff6ff068ddddc76afce66b9613ade3d9e6174450dd8010d73c8c7634f93","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000747e8426f940459381","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2148938766947979727745"}]}},{"block_signed_at":"2021-09-07T17:56:42Z","block_height":69314599,"tx_offset":6,"log_offset":3,"tx_hash":"0x2fe4fff6ff068ddddc76afce66b9613ade3d9e6174450dd8010d73c8c7634f93","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T17:56:42Z","block_height":69314599,"tx_offset":6,"log_offset":4,"tx_hash":"0x2fe4fff6ff068ddddc76afce66b9613ade3d9e6174450dd8010d73c8c7634f93","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004555cf169caae9830000000000000000000000000000000000000000000000004555cfbf9e6e0f9f","decoded":null},{"block_signed_at":"2021-09-07T17:56:42Z","block_height":69314599,"tx_offset":6,"log_offset":5,"tx_hash":"0x2fe4fff6ff068ddddc76afce66b9613ade3d9e6174450dd8010d73c8c7634f93","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000034b986896e86dbf4b4c40000000000000000000000000000000000000000000038cb093774cdae76e7977","decoded":null},{"block_signed_at":"2021-09-07T17:56:42Z","block_height":69314599,"tx_offset":6,"log_offset":6,"tx_hash":"0x2fe4fff6ff068ddddc76afce66b9613ade3d9e6174450dd8010d73c8c7634f93","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000747e8426f940459381","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2148938766947979727745"}]}},{"block_signed_at":"2021-09-07T17:56:42Z","block_height":69314599,"tx_offset":6,"log_offset":7,"tx_hash":"0x2fe4fff6ff068ddddc76afce66b9613ade3d9e6174450dd8010d73c8c7634f93","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000747e8426f940459381","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2148938766947979727745"}]}}]},{"block_signed_at":"2021-09-07T17:57:01Z","block_height":69314618,"tx_hash":"0x83b8c224d478161518d8ab7d8ecaa83ccb6b240ae667d6477e30a88dd3819676","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T17:57:01Z","block_height":69314618,"tx_offset":5,"log_offset":4,"tx_hash":"0x83b8c224d478161518d8ab7d8ecaa83ccb6b240ae667d6477e30a88dd3819676","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000747f5db21c2a740000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2149000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T17:58:03Z","block_height":69314680,"tx_hash":"0xaf4dda22c3798503a424490a2d85fd551e980b3a16777ec20e90771e4c375ea2","tx_offset":0,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T18:05:10Z","block_height":69315107,"tx_hash":"0xb0ef480a24d890e8533ba880266bba1989217790c2386fa164997771fef29dfa","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.010657851463347674,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:05:10Z","block_height":69315107,"tx_offset":5,"log_offset":0,"tx_hash":"0xb0ef480a24d890e8533ba880266bba1989217790c2386fa164997771fef29dfa","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000074c206e35f8b302d2a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2153803424643022859562"}]}},{"block_signed_at":"2021-09-07T18:05:10Z","block_height":69315107,"tx_offset":5,"log_offset":1,"tx_hash":"0xb0ef480a24d890e8533ba880266bba1989217790c2386fa164997771fef29dfa","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000074c206e35f8b302d2a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2153803424643022859562"}]}},{"block_signed_at":"2021-09-07T18:05:10Z","block_height":69315107,"tx_offset":5,"log_offset":2,"tx_hash":"0xb0ef480a24d890e8533ba880266bba1989217790c2386fa164997771fef29dfa","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:05:10Z","block_height":69315107,"tx_offset":5,"log_offset":3,"tx_hash":"0xb0ef480a24d890e8533ba880266bba1989217790c2386fa164997771fef29dfa","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004555d33934c9b81b0000000000000000000000000000000000000000000000004555d3e2270ff4c1","decoded":null},{"block_signed_at":"2021-09-07T18:05:10Z","block_height":69315107,"tx_offset":5,"log_offset":4,"tx_hash":"0xb0ef480a24d890e8533ba880266bba1989217790c2386fa164997771fef29dfa","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000034aa4719d4874138f2087000000000000000000000000000000000000000000038db7a9be0bb6d0ca70b6","decoded":null},{"block_signed_at":"2021-09-07T18:05:10Z","block_height":69315107,"tx_offset":5,"log_offset":5,"tx_hash":"0xb0ef480a24d890e8533ba880266bba1989217790c2386fa164997771fef29dfa","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000074c206e35f8b302d2a","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2153803424643022859562"}]}},{"block_signed_at":"2021-09-07T18:05:10Z","block_height":69315107,"tx_offset":5,"log_offset":6,"tx_hash":"0xb0ef480a24d890e8533ba880266bba1989217790c2386fa164997771fef29dfa","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000074c206e35f8b302d2a","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2153803424643022859562"}]}}]},{"block_signed_at":"2021-09-07T18:05:32Z","block_height":69315129,"tx_hash":"0xca8f6d2a894cb43d7c60099e98149ac92678eb9d7b81310856f677f233cd2d56","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.002125596391621232,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:05:32Z","block_height":69315129,"tx_offset":7,"log_offset":10,"tx_hash":"0xca8f6d2a894cb43d7c60099e98149ac92678eb9d7b81310856f677f233cd2d56","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000074c4c1439e6f680000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2154000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T18:05:49Z","block_height":69315146,"tx_hash":"0xfc83dafc3dc3a89d55572c6ab155301be7eb20078b90976e429b988be67360ab","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":3295.945405960083,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.011869276197308301,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":0,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dba6c1b3c7fb4ea5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000324270839601778341"}]}},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":1,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe52fcdcbff4656bdbb73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563912835515168772673354611"}]}},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":2,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dba6c1b3c7fb4ea5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000324270839601778341"}]}},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":3,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dba6c1b3c7fb4ea500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9c4b564c2379186ff","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000324270839601778341"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3721969905003157096191"}]}},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":4,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005346029834a6e7ab","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000486406259402667"}]}},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":5,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005346029834a6e7ac","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000486406259402668"}]}},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":6,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005346029834a6e7ac0000000000000000000000000000000000000000000000027845ff5e8da74a9a000000000000000000000000000000000000000000000002784600b07936f0a3","decoded":null},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":7,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000034d672d78dd9f0872fa52000000000000000000000000000000000000000000038abf2a066b2c20de5f44","decoded":null},{"block_signed_at":"2021-09-07T18:09:54Z","block_height":69315391,"tx_offset":4,"log_offset":8,"tx_hash":"0x25504824387cda7629685564ba38af4d14415f7db17eddf40e2e40df025c43a6","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dba6c1b3c7fb4ea500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9c4b564c2379186ff","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000324270839601778341"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3721969905003157096191"}]}}]},{"block_signed_at":"2021-09-07T18:11:24Z","block_height":69315481,"tx_hash":"0x472ca8bb653f6b30b58c16e5cdc5f8b2e795a57802362287884d6578438617f8","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3721000000000000000000","value_quote":6132.1064277887335,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T18:17:20Z","block_height":69315837,"tx_hash":"0x3bffc8b3bfbf3971607e261229d1665bace0b5b9144e658f61fd34af26ae830c","tx_offset":4,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:17:20Z","block_height":69315837,"tx_offset":4,"log_offset":2,"tx_hash":"0x3bffc8b3bfbf3971607e261229d1665bace0b5b9144e658f61fd34af26ae830c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":0,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":1,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe4572e2822fd79cdbb73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563908839515168772673354611"}]}},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":2,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":3,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c60700fdc7cbb2d12d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3652960008787314528557"}]}},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":4,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":5,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":6,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278460be9f9a8740a00000000000000000000000000000000000000000000000278460d3b490c47df","decoded":null},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":7,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000345fce93d9ba01735f08a0000000000000000000000000000000000000000000392c659e45b388e6faa09","decoded":null},{"block_signed_at":"2021-09-07T18:17:35Z","block_height":69315852,"tx_offset":1,"log_offset":8,"tx_hash":"0x9506c51208a7b62550304b9498c5111fe37d713b35477b455d9a2df8d26fb3f7","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c60700fdc7cbb2d12d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3652960008787314528557"}]}}]},{"block_signed_at":"2021-09-07T18:18:08Z","block_height":69315885,"tx_hash":"0x599a3a45b48991ba1a959f17938ef23bde348bc2eb36cd4f6f2a8855934ff7b7","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3653000000000000000000","value_quote":6020.044283986091,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T18:22:16Z","block_height":69316133,"tx_hash":"0x7f789eb7af83560a2994628ca5575c431a91552661bc0aa36b077f78f92cc196","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:22:16Z","block_height":69316133,"tx_offset":3,"log_offset":3,"tx_hash":"0x7f789eb7af83560a2994628ca5575c431a91552661bc0aa36b077f78f92cc196","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":0,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":1,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe37e8e8446b49cddbb73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563904843515168772673354611"}]}},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":2,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":3,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c44d22d013354b0053","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3621120072118117793875"}]}},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":4,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":5,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":6,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027846122eb6d7dfb900000000000000000000000000000000000000000000000278461380063bb38e","decoded":null},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":7,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000342545fc434d37d0e266a0000000000000000000000000000000000000000000396c93027f21186ec3a62","decoded":null},{"block_signed_at":"2021-09-07T18:22:27Z","block_height":69316144,"tx_offset":1,"log_offset":8,"tx_hash":"0x1c1adb868f919f9bceb8ea1102890c2ee0340f66a4a7520a9128cb883ea0cff4","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c44d22d013354b0053","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3621120072118117793875"}]}}]},{"block_signed_at":"2021-09-07T18:22:52Z","block_height":69316169,"tx_hash":"0x4075c7ca3f960bc7f0183adde15cb3c0279ac26968775739318063a5c94fe253","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3621000000000000000000","value_quote":5967.309157490729,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T18:27:09Z","block_height":69316426,"tx_hash":"0xb0f7a17b5f4dffd0fcde8612c1150475c3f0d6862b52cf3bdd5e6aa89e58c319","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:27:09Z","block_height":69316426,"tx_offset":6,"log_offset":13,"tx_hash":"0xb0f7a17b5f4dffd0fcde8612c1150475c3f0d6862b52cf3bdd5e6aa89e58c319","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":0,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":1,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe2a5eee06a6bbfedbb73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563900847515168772673354611"}]}},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":2,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":3,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c392ac1d12a97362f1","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3607683948764883804913"}]}},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":4,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":5,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":6,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278461875259aa817000000000000000000000000000000000000000000000002784619c674fe7bec","decoded":null},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":7,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000340c7edd91d116f59e0b700000000000000000000000000000000000000000003987e936157c88e74909a","decoded":null},{"block_signed_at":"2021-09-07T18:27:16Z","block_height":69316433,"tx_offset":2,"log_offset":8,"tx_hash":"0xb1d979059ab37983a49df68b30646781e1e15e3536d5b6323169a2b78ce835a0","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c392ac1d12a97362f1","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3607683948764883804913"}]}}]},{"block_signed_at":"2021-09-07T18:27:42Z","block_height":69316459,"tx_hash":"0x8e7bcdcd49b677aa8300cb3dca999545070618ed2c4fd773af12a2bb02420a70","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3608000000000000000000","value_quote":5945.88551235199,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T18:32:16Z","block_height":69316733,"tx_hash":"0xc3de07de75d5301a9a407cda3ede813ec38f4e459e252438e094e3154d6453bd","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:32:16Z","block_height":69316733,"tx_offset":1,"log_offset":0,"tx_hash":"0xc3de07de75d5301a9a407cda3ede813ec38f4e459e252438e094e3154d6453bd","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":1,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":2,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe1cd4f3c8e22e2fdbb73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563896851515168772673354611"}]}},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":3,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":4,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1f3461010779f8bac","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3577751322488442162092"}]}},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":5,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":6,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":7,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027846222491928e0b00000000000000000000000000000000000000000000000278462375e0f661e0","decoded":null},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":8,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033d521315d65a782ed946000000000000000000000000000000000000000000039c55d1be08941fd0f4a9","decoded":null},{"block_signed_at":"2021-09-07T18:35:05Z","block_height":69316902,"tx_offset":2,"log_offset":9,"tx_hash":"0x36f4dea389e01c0ef82468d3b7cc018e112e2869b78409fb6478b520fb24a7b2","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1f3461010779f8bac","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3577751322488442162092"}]}}]},{"block_signed_at":"2021-09-07T18:35:32Z","block_height":69316929,"tx_hash":"0x38a59a48fbe289f96add3f62aecb046030663df03355ea0c3da2902daab037cf","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3578000000000000000000","value_quote":5896.4463312625885,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T18:41:17Z","block_height":69317274,"tx_hash":"0x157da91ffa3fa2a5869d303079d929cb3d5258be3718c7077940c93d65dfba33","tx_offset":2,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T18:41:17Z","block_height":69317274,"tx_offset":2,"log_offset":0,"tx_hash":"0x157da91ffa3fa2a5869d303079d929cb3d5258be3718c7077940c93d65dfba33","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.011864002684658766,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":1,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":2,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe0f4af98b1da060dbb73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563892855515168772673354611"}]}},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":3,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":4,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c2406c116945ffc567","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3583310454759408780647"}]}},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":5,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":6,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":7,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278462b0ab0636cde00000000000000000000000000000000000000000000000278462c5aed7d7129","decoded":null},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":8,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033ea14fea6eef35142f25000000000000000000000000000000000000000000039c5bc5f43b9093942efa","decoded":null},{"block_signed_at":"2021-09-07T19:03:57Z","block_height":69318634,"tx_offset":2,"log_offset":9,"tx_hash":"0xad39615bb7de47123500a96e0b966b02e8a572951ec037c21f8d53fb8c39a12c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c2406c116945ffc567","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3583310454759408780647"}]}}]},{"block_signed_at":"2021-09-07T19:04:29Z","block_height":69318666,"tx_hash":"0x4d1dd4372bbfef014768fc084c7508abe0c62995c4acc9ce1649ff6e89439192","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3583000000000000000000","value_quote":5904.68619477749,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":8.651856690645218E-4,"gas_quote_rate":1.6479727029800415,"log_events":[]},{"block_signed_at":"2021-09-07T19:10:13Z","block_height":69319010,"tx_hash":"0x427b4953ce15645b1173ac09a8df399961b2f3b7cd096929cc0d9b57d57e13e0","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.002724799266424775,"gas_quote_rate":1.6479727029800415,"log_events":[{"block_signed_at":"2021-09-07T19:10:13Z","block_height":69319010,"tx_offset":1,"log_offset":0,"tx_hash":"0x427b4953ce15645b1173ac09a8df399961b2f3b7cd096929cc0d9b57d57e13e0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","tx_offset":17,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":103,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":104,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffe01c0ff4d591291dbb73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563888859515168772673354611"}]}},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":105,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":106,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b7554218251006cede","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3381897664877996461790"}]}},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":107,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":108,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":109,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027846e0f6fc022d420000000000000000000000000000000000000000000000027846e265c859f96a","decoded":null},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":110,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000329c7c4f4a303c615bc8800000000000000000000000000000000000000000003bacc2f2fe3e9ada9f1df","decoded":null},{"block_signed_at":"2021-09-08T00:08:40Z","block_height":69336917,"tx_offset":17,"log_offset":111,"tx_hash":"0xd1565983e1e25f7e773b0bdedb9535fb0e55d43e023fa65f4be4e760a1318236","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b7554218251006cede","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3381897664877996461790"}]}}]},{"block_signed_at":"2021-09-08T00:09:18Z","block_height":69336955,"tx_hash":"0x7d0a255ec99977e7a274305bbf1c4b17238e731e51d36924de352806319e9a69","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3382000000000000000000","value_quote":4898.754959106445,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T00:12:07Z","block_height":69337124,"tx_hash":"0xf00da8d4649b465f910416b4bdfcecaa35919a0779ded320241720772e22e2d9","tx_offset":2,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T00:12:07Z","block_height":69337124,"tx_offset":2,"log_offset":34,"tx_hash":"0xf00da8d4649b465f910416b4bdfcecaa35919a0779ded320241720772e22e2d9","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","tx_offset":10,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":4,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":5,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffdf437050f9484c2dbb73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563884863515168772673354611"}]}},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":6,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":7,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b71f4f6cf8a79c2365","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3378010307242403570533"}]}},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":8,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":9,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":10,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027846e80e9d994d360000000000000000000000000000000000000000000000027846e96473306398","decoded":null},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":11,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032a1953bfe4844484e07600000000000000000000000000000000000000000003bc4568987836e05af486","decoded":null},{"block_signed_at":"2021-09-08T00:24:36Z","block_height":69337873,"tx_offset":10,"log_offset":12,"tx_hash":"0xa4874ac87529e7a23aeea0d5cdd7392325b34bab949ee9024103f403934d4e32","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b71f4f6cf8a79c2365","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3378010307242403570533"}]}}]},{"block_signed_at":"2021-09-08T00:25:03Z","block_height":69337900,"tx_hash":"0x96a8d56c71c8b419ad8b5b5f93f3efa811f3733a682fe0a761e5d1db02d099fa","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3378000000000000000000","value_quote":4892.961044311523,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T00:31:43Z","block_height":69338300,"tx_hash":"0x3bd3899a3bfdd9c63c634370ce8f2caa4577e172d2f04b87bc2179cf86dd585e","tx_offset":18,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.00991085337638855,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T00:31:43Z","block_height":69338300,"tx_offset":18,"log_offset":26,"tx_hash":"0x3bd3899a3bfdd9c63c634370ce8f2caa4577e172d2f04b87bc2179cf86dd585e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007f961aeec76dbccf70","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2353552717356503715696"}]}},{"block_signed_at":"2021-09-08T00:31:43Z","block_height":69338300,"tx_offset":18,"log_offset":27,"tx_hash":"0x3bd3899a3bfdd9c63c634370ce8f2caa4577e172d2f04b87bc2179cf86dd585e","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007f961aeec76dbccf70","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2353552717356503715696"}]}},{"block_signed_at":"2021-09-08T00:31:43Z","block_height":69338300,"tx_offset":18,"log_offset":28,"tx_hash":"0x3bd3899a3bfdd9c63c634370ce8f2caa4577e172d2f04b87bc2179cf86dd585e","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T00:31:43Z","block_height":69338300,"tx_offset":18,"log_offset":29,"tx_hash":"0x3bd3899a3bfdd9c63c634370ce8f2caa4577e172d2f04b87bc2179cf86dd585e","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045566a09213208ea00000000000000000000000000000000000000000000000045566ab3853bce53","decoded":null},{"block_signed_at":"2021-09-08T00:31:43Z","block_height":69338300,"tx_offset":18,"log_offset":30,"tx_hash":"0x3bd3899a3bfdd9c63c634370ce8f2caa4577e172d2f04b87bc2179cf86dd585e","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032b168f6b5354bf2d847900000000000000000000000000000000000000000003bcd7ccf6ed9655aadef9","decoded":null},{"block_signed_at":"2021-09-08T00:31:43Z","block_height":69338300,"tx_offset":18,"log_offset":31,"tx_hash":"0x3bd3899a3bfdd9c63c634370ce8f2caa4577e172d2f04b87bc2179cf86dd585e","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007f961aeec76dbccf70","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2353552717356503715696"}]}},{"block_signed_at":"2021-09-08T00:31:43Z","block_height":69338300,"tx_offset":18,"log_offset":32,"tx_hash":"0x3bd3899a3bfdd9c63c634370ce8f2caa4577e172d2f04b87bc2179cf86dd585e","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007f961aeec76dbccf70","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2353552717356503715696"}]}}]},{"block_signed_at":"2021-09-08T00:32:01Z","block_height":69338318,"tx_hash":"0x83cc27eceb9ee5d97bcf2a4eec3dd97354e3aa61870e7d886bd84f60a7a52ce4","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77581,"gas_spent":36721,"gas_price":25000000000,"fees_paid":"918025000000000","gas_quote":0.0013297396574020385,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T00:32:01Z","block_height":69338318,"tx_offset":0,"log_offset":0,"tx_hash":"0x83cc27eceb9ee5d97bcf2a4eec3dd97354e3aa61870e7d886bd84f60a7a52ce4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007f961aeec76dbccf70","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2353552717356503715696"}]}}]},{"block_signed_at":"2021-09-08T00:34:15Z","block_height":69338452,"tx_hash":"0x969426a6629effcd50823d2bde2a055db4dea53b9680ef9f17ba8db0622e0d90","tx_offset":9,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T00:54:19Z","block_height":69339656,"tx_hash":"0xcd4ac9efa898beb64af058df2ddd978e87b00992879d294a1db45f3eb85645be","tx_offset":11,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.00991085337638855,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T00:54:19Z","block_height":69339656,"tx_offset":11,"log_offset":45,"tx_hash":"0xcd4ac9efa898beb64af058df2ddd978e87b00992879d294a1db45f3eb85645be","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007d58a48029c5dd4b43","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2312230380302113786691"}]}},{"block_signed_at":"2021-09-08T00:54:19Z","block_height":69339656,"tx_offset":11,"log_offset":46,"tx_hash":"0xcd4ac9efa898beb64af058df2ddd978e87b00992879d294a1db45f3eb85645be","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007d58a48029c5dd4b43","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2312230380302113786691"}]}},{"block_signed_at":"2021-09-08T00:54:19Z","block_height":69339656,"tx_offset":11,"log_offset":47,"tx_hash":"0xcd4ac9efa898beb64af058df2ddd978e87b00992879d294a1db45f3eb85645be","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T00:54:19Z","block_height":69339656,"tx_offset":11,"log_offset":48,"tx_hash":"0xcd4ac9efa898beb64af058df2ddd978e87b00992879d294a1db45f3eb85645be","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004556795b16113b6600000000000000000000000000000000000000000000000045567a04fa68a654","decoded":null},{"block_signed_at":"2021-09-08T00:54:19Z","block_height":69339656,"tx_offset":11,"log_offset":49,"tx_hash":"0xcd4ac9efa898beb64af058df2ddd978e87b00992879d294a1db45f3eb85645be","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033302064dc925df267eec00000000000000000000000000000000000000000003b53a1caec3c3e7895cc6","decoded":null},{"block_signed_at":"2021-09-08T00:54:19Z","block_height":69339656,"tx_offset":11,"log_offset":50,"tx_hash":"0xcd4ac9efa898beb64af058df2ddd978e87b00992879d294a1db45f3eb85645be","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007d58a48029c5dd4b43","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2312230380302113786691"}]}},{"block_signed_at":"2021-09-08T00:54:19Z","block_height":69339656,"tx_offset":11,"log_offset":51,"tx_hash":"0xcd4ac9efa898beb64af058df2ddd978e87b00992879d294a1db45f3eb85645be","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007d58a48029c5dd4b43","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2312230380302113786691"}]}}]},{"block_signed_at":"2021-09-08T00:54:46Z","block_height":69339683,"tx_hash":"0x475737c7e37274641e523c8d99c4e1a3592209048d3a2f59c5f3214e2ea35649","tx_offset":10,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77581,"gas_spent":36721,"gas_price":25000000000,"fees_paid":"918025000000000","gas_quote":0.0013297396574020385,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T00:54:46Z","block_height":69339683,"tx_offset":10,"log_offset":5,"tx_hash":"0x475737c7e37274641e523c8d99c4e1a3592209048d3a2f59c5f3214e2ea35649","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007d58a48029c5dd4b43","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2312230380302113786691"}]}}]},{"block_signed_at":"2021-09-08T00:57:50Z","block_height":69339867,"tx_hash":"0x5ea3f79b888cd2dbb5a86336ec768b5b1f5ce51d369bb05ae0c7e4ff9e94120e","tx_offset":1,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T00:59:20Z","block_height":69339957,"tx_hash":"0x09e26210d2d23321f3cec40412156aa4e381ffc7d4b434e8bbaa29f6b88ceb31","tx_offset":8,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T00:59:20Z","block_height":69339957,"tx_offset":8,"log_offset":9,"tx_hash":"0x09e26210d2d23321f3cec40412156aa4e381ffc7d4b434e8bbaa29f6b88ceb31","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a687224b3f98e000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996496317360000000000"}]}}]},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461139,"gas_spent":288030,"gas_price":25000000000,"fees_paid":"7200750000000000","gas_quote":0.010430132989883422,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":0,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a687224b3f98e000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996496317360000000000"}]}},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":1,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffde6ac9c9d6fd0c94db73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563880867018851412673354611"}]}},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":2,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a687224b3f98e000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996496317360000000000"}]}},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":3,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8a687224b3f98e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bbd17fd4ffff99ac06","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996496317360000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3464637160455625354246"}]}},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":4,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053319c56e5997200","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994744476040000000"}]}},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":5,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053319c56e5997200","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994744476040000000"}]}},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":6,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000053319c56e5997200000000000000000000000000000000000000000000000002784707f2296856ef00000000000000000000000000000000000000000000000278470945003c65f8","decoded":null},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":7,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003361bd079ffeeb170e93a00000000000000000000000000000000000000000003b24f5cc7735f23c35539","decoded":null},{"block_signed_at":"2021-09-08T01:52:24Z","block_height":69343141,"tx_offset":6,"log_offset":8,"tx_hash":"0x49ca073696508c67ed659198ca85bfdeb18f2c293805e6e3db9d52caa5692ac6","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8a687224b3f98e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bbd17fd4ffff99ac06","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996496317360000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3464637160455625354246"}]}}]},{"block_signed_at":"2021-09-08T01:52:56Z","block_height":69343173,"tx_hash":"0xb398ec072432a676c42e4de2d1bacb6e75d36cf22957e02402d6f7dabe934aaa","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3465000000000000000000","value_quote":5018.978691101073,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T01:56:13Z","block_height":69343370,"tx_hash":"0xfc1c800ddbe5c74b9a8461820dd213481b578ec669db265c6470ed5b37906a8c","tx_offset":2,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T01:56:13Z","block_height":69343370,"tx_offset":2,"log_offset":0,"tx_hash":"0xfc1c800ddbe5c74b9a8461820dd213481b578ec669db265c6470ed5b37906a8c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":4,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":5,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffdd922a25fab42fa4db73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563876871018851412673354611"}]}},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":6,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":7,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bc329729ebe0304037","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3471633314373830721591"}]}},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":8,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":9,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":10,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278470ebe659ba6a700000000000000000000000000000000000000000000000278471011aebe9069","decoded":null},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":11,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000336fded1e542996b952c400000000000000000000000000000000000000000003b14d0e373f669fe0a557","decoded":null},{"block_signed_at":"2021-09-08T02:00:06Z","block_height":69343603,"tx_offset":6,"log_offset":12,"tx_hash":"0xad5f764bbb66f7f6d4aa1b7b20cfcb80cf14024fcea0d0b18c1d9a665a3d2281","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bc329729ebe0304037","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3471633314373830721591"}]}}]},{"block_signed_at":"2021-09-08T02:00:24Z","block_height":69343621,"tx_hash":"0x8309d51c3819fcaac865e0853335d3a7c8005ff16387a51eb39fdc491288abd5","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3471000000000000000000","value_quote":5027.669563293458,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T02:03:05Z","block_height":69343782,"tx_hash":"0xf3bbc0c5b2aa2851bdd864c3f7de7378d8fe0c72825a32b49f75514ac6342e5c","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T02:03:05Z","block_height":69343782,"tx_offset":0,"log_offset":0,"tx_hash":"0xf3bbc0c5b2aa2851bdd864c3f7de7378d8fe0c72825a32b49f75514ac6342e5c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":0,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":1,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffdcb98a821e6b52b4db73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563872875018851412673354611"}]}},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":2,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":3,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bc299188614bd4c767","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3470983211036039235431"}]}},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":4,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":5,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":6,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb10000000000000000000000000000000000000000000000000002784713651142e470000000000000000000000000000000000000000000000002784714b6cb49818e","decoded":null},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":7,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000338ad41d96e1f205e543f00000000000000000000000000000000000000000003b3696c96a62b61f2cb49","decoded":null},{"block_signed_at":"2021-09-08T02:07:16Z","block_height":69344033,"tx_offset":0,"log_offset":8,"tx_hash":"0x467703349d9ffd133d4c894863fbf861a5da1bc451096a9df99446702264e9e8","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bc299188614bd4c767","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3470983211036039235431"}]}}]},{"block_signed_at":"2021-09-08T02:07:53Z","block_height":69344070,"tx_hash":"0xc6e7d189b92614543c124473ce194fa77505017ee0ff89edad26a02d9c08033b","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3471000000000000000000","value_quote":5027.669563293458,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T02:12:07Z","block_height":69344324,"tx_hash":"0xd0e375d19303f5fe78f49f1ec8274a7b83b2b5b992334a7ac69975312280699c","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T02:12:07Z","block_height":69344324,"tx_offset":6,"log_offset":44,"tx_hash":"0xd0e375d19303f5fe78f49f1ec8274a7b83b2b5b992334a7ac69975312280699c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":31,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":32,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffdbe0eade422275c4db73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563868879018851412673354611"}]}},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":33,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":34,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba139d5547813ab016","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3432507777333639950358"}]}},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":35,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":36,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":37,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278471e8fb3881bbb00000000000000000000000000000000000000000000000278471fe0f17f773e","decoded":null},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":38,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033418d7b96dc0e32281c000000000000000000000000000000000000000000003b8b4d9916cb1ef4c315f","decoded":null},{"block_signed_at":"2021-09-08T02:19:15Z","block_height":69344752,"tx_offset":5,"log_offset":39,"tx_hash":"0xcf6dfca7e3c27597c38fa99608a3545ab112e2f58cbd852b5b4ddf5ddc28e18d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba139d5547813ab016","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3432507777333639950358"}]}}]},{"block_signed_at":"2021-09-08T02:19:44Z","block_height":69344781,"tx_hash":"0x876a67eaf67260d2823dc55475bfbf2f3d53dd39d3e22d8f9206d433a22bc858","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3433000000000000000000","value_quote":4972.627372741698,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T02:26:34Z","block_height":69345191,"tx_hash":"0xce0256a0656115ada1332e962a4df7a6e2366b70e1eef058ff5b489ea5a33624","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T02:26:34Z","block_height":69345191,"tx_offset":1,"log_offset":2,"tx_hash":"0xce0256a0656115ada1332e962a4df7a6e2366b70e1eef058ff5b489ea5a33624","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","tx_offset":8,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":37,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":38,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffdb084b3a65d998d4db73","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563864883018851412673354611"}]}},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":39,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":40,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b07502db9d1cde4a64","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3255058499893112752740"}]}},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":41,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":42,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":43,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278478954626ae54000000000000000000000000000000000000000000000000278478aa66dad95d5","decoded":null},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":44,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032263658401a09b949fa200000000000000000000000000000000000000000003d6ec306b93edef9af7f6","decoded":null},{"block_signed_at":"2021-09-08T04:06:44Z","block_height":69351201,"tx_offset":8,"log_offset":45,"tx_hash":"0x40bac6de00565679513926ef16e133681acf65bf089ba60f7275563e02854a07","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b07502db9d1cde4a64","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3255058499893112752740"}]}}]},{"block_signed_at":"2021-09-08T04:07:13Z","block_height":69351230,"tx_hash":"0x537b9a1b40b54f2d505b47e355a4a73925675b61d829a689db1c723895b760e2","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3255000000000000000000","value_quote":4714.798164367677,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T04:11:07Z","block_height":69351464,"tx_hash":"0x14bb2bc2c6d121fbe893b7c4d7cd1411b07fc2d2d2d04f7f9096899f677c175c","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T04:11:07Z","block_height":69351464,"tx_offset":0,"log_offset":0,"tx_hash":"0x14bb2bc2c6d121fbe893b7c4d7cd1411b07fc2d2d2d04f7f9096899f677c175c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T04:17:13Z","block_height":69351830,"tx_hash":"0xafd14e929eb2e778bcccbf086bb81d71ff6144c721768784cef09d76c9cb51d5","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T04:17:13Z","block_height":69351830,"tx_offset":2,"log_offset":2,"tx_hash":"0xafd14e929eb2e778bcccbf086bb81d71ff6144c721768784cef09d76c9cb51d5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000084ba03a710ae84e01c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2448373958335734800412"}]}},{"block_signed_at":"2021-09-08T04:17:13Z","block_height":69351830,"tx_offset":2,"log_offset":3,"tx_hash":"0xafd14e929eb2e778bcccbf086bb81d71ff6144c721768784cef09d76c9cb51d5","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000084ba03a710ae84e01c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2448373958335734800412"}]}},{"block_signed_at":"2021-09-08T04:17:13Z","block_height":69351830,"tx_offset":2,"log_offset":4,"tx_hash":"0xafd14e929eb2e778bcccbf086bb81d71ff6144c721768784cef09d76c9cb51d5","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T04:17:13Z","block_height":69351830,"tx_offset":2,"log_offset":5,"tx_hash":"0xafd14e929eb2e778bcccbf086bb81d71ff6144c721768784cef09d76c9cb51d5","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004556db4933187e080000000000000000000000000000000000000000000000004556dbf2466bbf8f","decoded":null},{"block_signed_at":"2021-09-08T04:17:13Z","block_height":69351830,"tx_offset":2,"log_offset":6,"tx_hash":"0xafd14e929eb2e778bcccbf086bb81d71ff6144c721768784cef09d76c9cb51d5","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000321866c8c8e648584d24b00000000000000000000000000000000000000000003d7a68f820e00cb8a7d8e","decoded":null},{"block_signed_at":"2021-09-08T04:17:13Z","block_height":69351830,"tx_offset":2,"log_offset":7,"tx_hash":"0xafd14e929eb2e778bcccbf086bb81d71ff6144c721768784cef09d76c9cb51d5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000084ba03a710ae84e01c","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2448373958335734800412"}]}},{"block_signed_at":"2021-09-08T04:17:13Z","block_height":69351830,"tx_offset":2,"log_offset":8,"tx_hash":"0xafd14e929eb2e778bcccbf086bb81d71ff6144c721768784cef09d76c9cb51d5","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000084ba03a710ae84e01c","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2448373958335734800412"}]}}]},{"block_signed_at":"2021-09-08T04:17:43Z","block_height":69351860,"tx_hash":"0x95a75f055b268b4ec2651af6db62790b1cc9748b3927fac4ed13b3d1c708e982","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T04:17:43Z","block_height":69351860,"tx_offset":3,"log_offset":4,"tx_hash":"0x95a75f055b268b4ec2651af6db62790b1cc9748b3927fac4ed13b3d1c708e982","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000847d503b220eb00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2444000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T04:19:38Z","block_height":69351975,"tx_hash":"0x0706559a08c3e5ec5004a0c4a4d70ac5c4462d9d8d154d05a83a4e7f665518bb","tx_offset":5,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T04:44:27Z","block_height":69353464,"tx_hash":"0x9b171188211250fa954b0ab5592a24f401372b5dc3dbd5aadf9f20045c851d4c","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T04:44:27Z","block_height":69353464,"tx_offset":0,"log_offset":0,"tx_hash":"0x9b171188211250fa954b0ab5592a24f401372b5dc3dbd5aadf9f20045c851d4c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000838442a44d8b7233bb","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2426053834070379606971"}]}},{"block_signed_at":"2021-09-08T04:44:27Z","block_height":69353464,"tx_offset":0,"log_offset":1,"tx_hash":"0x9b171188211250fa954b0ab5592a24f401372b5dc3dbd5aadf9f20045c851d4c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000838442a44d8b7233bb","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2426053834070379606971"}]}},{"block_signed_at":"2021-09-08T04:44:27Z","block_height":69353464,"tx_offset":0,"log_offset":2,"tx_hash":"0x9b171188211250fa954b0ab5592a24f401372b5dc3dbd5aadf9f20045c851d4c","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T04:44:27Z","block_height":69353464,"tx_offset":0,"log_offset":3,"tx_hash":"0x9b171188211250fa954b0ab5592a24f401372b5dc3dbd5aadf9f20045c851d4c","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004556ed0b81b7081f0000000000000000000000000000000000000000000000004556edb2d440b16b","decoded":null},{"block_signed_at":"2021-09-08T04:44:27Z","block_height":69353464,"tx_offset":0,"log_offset":4,"tx_hash":"0x9b171188211250fa954b0ab5592a24f401372b5dc3dbd5aadf9f20045c851d4c","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032ac35bd52a02ee8a9d1200000000000000000000000000000000000000000003d9ec4dc0ccd13d72b198","decoded":null},{"block_signed_at":"2021-09-08T04:44:27Z","block_height":69353464,"tx_offset":0,"log_offset":5,"tx_hash":"0x9b171188211250fa954b0ab5592a24f401372b5dc3dbd5aadf9f20045c851d4c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000838442a44d8b7233bb","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2426053834070379606971"}]}},{"block_signed_at":"2021-09-08T04:44:27Z","block_height":69353464,"tx_offset":0,"log_offset":6,"tx_hash":"0x9b171188211250fa954b0ab5592a24f401372b5dc3dbd5aadf9f20045c851d4c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000838442a44d8b7233bb","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2426053834070379606971"}]}}]},{"block_signed_at":"2021-09-08T04:44:52Z","block_height":69353489,"tx_hash":"0x69d624aa7b141fd1a08b46ecd394740c2ba6a5725a30ef444bcb2239b966afb0","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T04:44:52Z","block_height":69353489,"tx_offset":7,"log_offset":5,"tx_hash":"0x69d624aa7b141fd1a08b46ecd394740c2ba6a5725a30ef444bcb2239b966afb0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000838383628049a80000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2426000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T04:45:05Z","block_height":69353502,"tx_hash":"0x5ae6bc54336ff782dfd4b6b62668c932de3ec148293861bfca37358cddaa9303","tx_offset":6,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.01043245055580139,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":0,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dd168a04be8f13d7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000427792406114407383"}]}},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":1,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffda2f6e23dbd4da45c79c","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563860882591059006558947228"}]}},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":2,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dd168a04be8f13d7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000427792406114407383"}]}},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":3,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dd168a04be8f13d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b38b4873504a3eec82","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000427792406114407383"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3312003587752285105282"}]}},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":4,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053468fd2b1f3289b","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000641688609171611"}]}},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":5,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053468fd2b1f3289b","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000641688609171611"}]}},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":6,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000053468fd2b1f3289b0000000000000000000000000000000000000000000000027847b6fd9e8005770000000000000000000000000000000000000000000000027847b84d1f569f5c","decoded":null},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":7,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032e758da3be86540af1cf00000000000000000000000000000000000000000003d5a4d22a58708ea848e9","decoded":null},{"block_signed_at":"2021-09-08T05:08:56Z","block_height":69354933,"tx_offset":0,"log_offset":8,"tx_hash":"0x77bcd2077e663ef5e7b3a6561bc95424f67bc894ec4f7a6bc36e73d1347736bc","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dd168a04be8f13d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b38b4873504a3eec82","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000427792406114407383"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3312003587752285105282"}]}}]},{"block_signed_at":"2021-09-08T05:09:29Z","block_height":69354966,"tx_hash":"0xb4a9a5f04e7f2bcb83d872bc39c4031da7d806c3697fff2299f16c0c76be0df4","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3312000000000000000000","value_quote":4797.3614501953125,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T05:14:07Z","block_height":69355244,"tx_hash":"0x0e0ad6d26a4d346c8744b75cd11637b7a1f56a0cbd77a3fafde14d81e043ceaa","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:14:07Z","block_height":69355244,"tx_offset":3,"log_offset":12,"tx_hash":"0x0e0ad6d26a4d346c8744b75cd11637b7a1f56a0cbd77a3fafde14d81e043ceaa","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":24,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":25,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd956ce7fff8bfd55c79c","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563856886591059006558947228"}]}},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":26,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":27,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1423ebb2c68514182","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3269847159501053051266"}]}},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":28,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":29,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":30,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027847c64eb806796c0000000000000000000000000000000000000000000000027847c79f5ecb82ff","decoded":null},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":31,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032a3d89fa6fbb54f9a26100000000000000000000000000000000000000000003dc0c4b3a98c0d2b1eafa","decoded":null},{"block_signed_at":"2021-09-08T05:37:12Z","block_height":69356629,"tx_offset":2,"log_offset":32,"tx_hash":"0x2029713f8e7d528b484298295b5e0e371daa3115c037b92b9883ff54d36a016c","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b1423ebb2c68514182","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3269847159501053051266"}]}}]},{"block_signed_at":"2021-09-08T05:37:42Z","block_height":69356659,"tx_hash":"0x1da7586df86a6aff44c238f53cffbeb5e79ff9df1bb3274225a5cb5ce78df7b3","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3270000000000000000000","value_quote":4736.525344848633,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T05:42:11Z","block_height":69356928,"tx_hash":"0x8ab8c9df6445ae14a4edc25b248a96a867c25b7a4cbe037c905a72e7013419f9","tx_offset":0,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:42:11Z","block_height":69356928,"tx_offset":0,"log_offset":0,"tx_hash":"0x8ab8c9df6445ae14a4edc25b248a96a867c25b7a4cbe037c905a72e7013419f9","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":0,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":1,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd87e2edc23432065c79c","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563852890591059006558947228"}]}},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":2,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":3,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac011fdf82eee35461","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3172921009749805454433"}]}},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":4,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":5,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":6,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027847de898387340d0000000000000000000000000000000000000000000000027847dfda55a519d2","decoded":null},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":7,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000031e25c1acb45c0175cf9f00000000000000000000000000000000000000000003eb0557b5c7124e040046","decoded":null},{"block_signed_at":"2021-09-08T05:44:54Z","block_height":69357091,"tx_offset":1,"log_offset":8,"tx_hash":"0x8d881f4fcb6a5eb6e9c2d1e99f1b57b731dc5b46e0aadd3c822702640a419c48","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac011fdf82eee35461","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3172921009749805454433"}]}}]},{"block_signed_at":"2021-09-08T05:45:24Z","block_height":69357121,"tx_hash":"0x157d06b10b98b83f76f510526a3bf34cb1065aa053a0f1b50e53b5bf329288a7","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3173000000000000000000","value_quote":4596.022911071776,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T05:49:12Z","block_height":69357349,"tx_hash":"0x3a9d197f9d724fb10636b252d889f0399a3f8b9eca5b744121729afc08d7a0b1","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:49:12Z","block_height":69357349,"tx_offset":6,"log_offset":9,"tx_hash":"0x3a9d197f9d724fb10636b252d889f0399a3f8b9eca5b744121729afc08d7a0b1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T05:51:11Z","block_height":69357468,"tx_hash":"0xc7b59f0a5abd91a814999a5d738c3b87b4014a8f74b29a042ae85db7aee15d4a","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:51:11Z","block_height":69357468,"tx_offset":3,"log_offset":18,"tx_hash":"0xc7b59f0a5abd91a814999a5d738c3b87b4014a8f74b29a042ae85db7aee15d4a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008e7edcd807c4393c61","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2628579077338280049761"}]}},{"block_signed_at":"2021-09-08T05:51:11Z","block_height":69357468,"tx_offset":3,"log_offset":19,"tx_hash":"0xc7b59f0a5abd91a814999a5d738c3b87b4014a8f74b29a042ae85db7aee15d4a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008e7edcd807c4393c61","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2628579077338280049761"}]}},{"block_signed_at":"2021-09-08T05:51:11Z","block_height":69357468,"tx_offset":3,"log_offset":20,"tx_hash":"0xc7b59f0a5abd91a814999a5d738c3b87b4014a8f74b29a042ae85db7aee15d4a","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T05:51:11Z","block_height":69357468,"tx_offset":3,"log_offset":21,"tx_hash":"0xc7b59f0a5abd91a814999a5d738c3b87b4014a8f74b29a042ae85db7aee15d4a","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455712a1f32906b800000000000000000000000000000000000000000000000045571340485b0ad8","decoded":null},{"block_signed_at":"2021-09-08T05:51:11Z","block_height":69357468,"tx_offset":3,"log_offset":22,"tx_hash":"0xc7b59f0a5abd91a814999a5d738c3b87b4014a8f74b29a042ae85db7aee15d4a","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030b8011dce057037b7101000000000000000000000000000000000000000000040303e095f7c515ea2221","decoded":null},{"block_signed_at":"2021-09-08T05:51:11Z","block_height":69357468,"tx_offset":3,"log_offset":23,"tx_hash":"0xc7b59f0a5abd91a814999a5d738c3b87b4014a8f74b29a042ae85db7aee15d4a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008e7edcd807c4393c61","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2628579077338280049761"}]}},{"block_signed_at":"2021-09-08T05:51:11Z","block_height":69357468,"tx_offset":3,"log_offset":24,"tx_hash":"0xc7b59f0a5abd91a814999a5d738c3b87b4014a8f74b29a042ae85db7aee15d4a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008e7edcd807c4393c61","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2628579077338280049761"}]}}]},{"block_signed_at":"2021-09-08T05:51:47Z","block_height":69357504,"tx_hash":"0xe02517632327c1b7d14d6ed4d3f446d699238a2c2017d327d361bf37a83ce63d","tx_offset":15,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:51:47Z","block_height":69357504,"tx_offset":15,"log_offset":26,"tx_hash":"0xe02517632327c1b7d14d6ed4d3f446d699238a2c2017d327d361bf37a83ce63d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008e76d38c425e900000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2628000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T05:52:03Z","block_height":69357520,"tx_hash":"0x09b1e4e38ac2d0e56b07721f3b470ad61ed547a8332c3c9d1b111e3f4c923a97","tx_offset":10,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T05:54:42Z","block_height":69357679,"tx_hash":"0x9c88578e82b47f11c5caa06fd4182999c3d35f38919cf1b7cd642c17a2ab464d","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:54:42Z","block_height":69357679,"tx_offset":3,"log_offset":1,"tx_hash":"0x9c88578e82b47f11c5caa06fd4182999c3d35f38919cf1b7cd642c17a2ab464d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008d8688a1a9019cc3b0","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2610685090338210366384"}]}},{"block_signed_at":"2021-09-08T05:54:42Z","block_height":69357679,"tx_offset":3,"log_offset":2,"tx_hash":"0x9c88578e82b47f11c5caa06fd4182999c3d35f38919cf1b7cd642c17a2ab464d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008d8688a1a9019cc3b0","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2610685090338210366384"}]}},{"block_signed_at":"2021-09-08T05:54:42Z","block_height":69357679,"tx_offset":3,"log_offset":3,"tx_hash":"0x9c88578e82b47f11c5caa06fd4182999c3d35f38919cf1b7cd642c17a2ab464d","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T05:54:42Z","block_height":69357679,"tx_offset":3,"log_offset":4,"tx_hash":"0x9c88578e82b47f11c5caa06fd4182999c3d35f38919cf1b7cd642c17a2ab464d","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455725eecbc3dede0000000000000000000000000000000000000000000000004557268d62ed5a8f","decoded":null},{"block_signed_at":"2021-09-08T05:54:42Z","block_height":69357679,"tx_offset":3,"log_offset":5,"tx_hash":"0x9c88578e82b47f11c5caa06fd4182999c3d35f38919cf1b7cd642c17a2ab464d","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030ecebd9ece45a2166c9900000000000000000000000000000000000000000004005a9ae872a6b6f24df9","decoded":null},{"block_signed_at":"2021-09-08T05:54:42Z","block_height":69357679,"tx_offset":3,"log_offset":6,"tx_hash":"0x9c88578e82b47f11c5caa06fd4182999c3d35f38919cf1b7cd642c17a2ab464d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008d8688a1a9019cc3b0","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2610685090338210366384"}]}},{"block_signed_at":"2021-09-08T05:54:42Z","block_height":69357679,"tx_offset":3,"log_offset":7,"tx_hash":"0x9c88578e82b47f11c5caa06fd4182999c3d35f38919cf1b7cd642c17a2ab464d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008d8688a1a9019cc3b0","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2610685090338210366384"}]}}]},{"block_signed_at":"2021-09-08T05:55:07Z","block_height":69357704,"tx_hash":"0x267f879d33c247e4de5190a51fdc7256437ff7702c503a3712d65c58cc5f1f62","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T05:55:07Z","block_height":69357704,"tx_offset":0,"log_offset":0,"tx_hash":"0x267f879d33c247e4de5190a51fdc7256437ff7702c503a3712d65c58cc5f1f62","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008d53648f85a35c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2607000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T06:02:11Z","block_height":69358128,"tx_hash":"0xb0df7ca020650637ebacdd23292c04a2acf4b164b96ad13907e293b57e92d6b2","tx_offset":1,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461139,"gas_spent":288030,"gas_price":25000000000,"fees_paid":"7200750000000000","gas_quote":0.010430132989883422,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":0,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dad13a31a0da0011","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000264167676490416145"}]}},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":1,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd7a5540ae9117f8bc78b","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563848890326891330068531083"}]}},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":2,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dad13a31a0da0011","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000264167676490416145"}]}},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":3,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dad13a31a0da001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a20bd54a98465b137f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000264167676490416145"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2989225209663279797119"}]}},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":4,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005345b0996b1f0c08","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000396251514735624"}]}},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":5,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005345b0996b1f0c08","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000396251514735624"}]}},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":6,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005345b0996b1f0c080000000000000000000000000000000000000000000000027848312716e5964a00000000000000000000000000000000000000000000000278483255015bd0ff","decoded":null},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":7,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002fec82f8f367def01763c00000000000000000000000000000000000000000003ffe524953200fafb743e","decoded":null},{"block_signed_at":"2021-09-08T06:02:31Z","block_height":69358148,"tx_offset":0,"log_offset":8,"tx_hash":"0x42abb310c20b24aaa25ad3c75983c683752062fca0489307c8cd1435914a8a63","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dad13a31a0da001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a20bd54a98465b137f","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000264167676490416145"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2989225209663279797119"}]}}]},{"block_signed_at":"2021-09-08T06:03:34Z","block_height":69358211,"tx_hash":"0x94ff237e9439c5538697197d81fe53567ccbb242b81f76fc5285945e8dc9776b","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"2989000000000000000000","value_quote":4329.50283050537,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T06:06:06Z","block_height":69358363,"tx_hash":"0x0822b9aa770cf1a8131c3e4364b38748b0a12cf7f1491795540ef1f2ce6840ae","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:06:06Z","block_height":69358363,"tx_offset":1,"log_offset":1,"tx_hash":"0x0822b9aa770cf1a8131c3e4364b38748b0a12cf7f1491795540ef1f2ce6840ae","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a2d655f265af7800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996230380300000000000"}]}}]},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461139,"gas_spent":288030,"gas_price":25000000000,"fees_paid":"7200750000000000","gas_quote":0.010430132989883422,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":69,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a2d655f265af7800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996230380300000000000"}]}},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":70,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd6ccb134931f19dc4f8b","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563844894096511030068531083"}]}},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":71,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a2d655f265af7800","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996230380300000000000"}]}},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":72,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8a2d655f265af780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a06fb2b20083dcb7a1","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996230380300000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2959527742992874780577"}]}},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":73,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053303189739bc880","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994345570450000000"}]}},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":74,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053303189739bc880","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994345570450000000"}]}},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":75,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000053303189739bc88000000000000000000000000000000000000000000000000278483c419aebcd3600000000000000000000000000000000000000000000000278483d6ff9dbbcc7","decoded":null},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":76,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002fae90c3e15cbc36bba420000000000000000000000000000000000000000000403e7eb7099db945fa1a7","decoded":null},{"block_signed_at":"2021-09-08T06:12:00Z","block_height":69358717,"tx_offset":3,"log_offset":77,"tx_hash":"0xadafc7054e22bec15a1129fcf1fbb26c0f6b795b2da07e74d375fea94a229841","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8a2d655f265af780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a06fb2b20083dcb7a1","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996230380300000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2959527742992874780577"}]}}]},{"block_signed_at":"2021-09-08T06:12:41Z","block_height":69358758,"tx_hash":"0xf5d451ceb8093c1a048880d3af4f6531ff0c70a6490f59127a26e07d001d28b6","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"2959000000000000000000","value_quote":4286.048469543458,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T06:18:12Z","block_height":69359089,"tx_hash":"0x52fdbcde170aa94669b95d8bffeb8561b589875dc6eece32567e88d6bdedca89","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.00991085337638855,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:18:12Z","block_height":69359089,"tx_offset":2,"log_offset":2,"tx_hash":"0x52fdbcde170aa94669b95d8bffeb8561b589875dc6eece32567e88d6bdedca89","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000989372a0689ea95561","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2814529830045971207521"}]}},{"block_signed_at":"2021-09-08T06:18:12Z","block_height":69359089,"tx_offset":2,"log_offset":3,"tx_hash":"0x52fdbcde170aa94669b95d8bffeb8561b589875dc6eece32567e88d6bdedca89","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000989372a0689ea95561","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2814529830045971207521"}]}},{"block_signed_at":"2021-09-08T06:18:12Z","block_height":69359089,"tx_offset":2,"log_offset":4,"tx_hash":"0x52fdbcde170aa94669b95d8bffeb8561b589875dc6eece32567e88d6bdedca89","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T06:18:12Z","block_height":69359089,"tx_offset":2,"log_offset":5,"tx_hash":"0x52fdbcde170aa94669b95d8bffeb8561b589875dc6eece32567e88d6bdedca89","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455738afb1ecdab900000000000000000000000000000000000000000000000045573947662c8929","decoded":null},{"block_signed_at":"2021-09-08T06:18:12Z","block_height":69359089,"tx_offset":2,"log_offset":6,"tx_hash":"0x52fdbcde170aa94669b95d8bffeb8561b589875dc6eece32567e88d6bdedca89","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002e8abc7c059d465eda52e000000000000000000000000000000000000000000041a81b74e913dcf68623a","decoded":null},{"block_signed_at":"2021-09-08T06:18:12Z","block_height":69359089,"tx_offset":2,"log_offset":7,"tx_hash":"0x52fdbcde170aa94669b95d8bffeb8561b589875dc6eece32567e88d6bdedca89","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000989372a0689ea95561","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2814529830045971207521"}]}},{"block_signed_at":"2021-09-08T06:18:12Z","block_height":69359089,"tx_offset":2,"log_offset":8,"tx_hash":"0x52fdbcde170aa94669b95d8bffeb8561b589875dc6eece32567e88d6bdedca89","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000989372a0689ea95561","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2814529830045971207521"}]}}]},{"block_signed_at":"2021-09-08T06:18:26Z","block_height":69359103,"tx_hash":"0x624e11be91bbe75a616ea2945ed89ce07698626e85b992989e57adafd4e59740","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77581,"gas_spent":36721,"gas_price":25000000000,"fees_paid":"918025000000000","gas_quote":0.0013297396574020385,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:18:26Z","block_height":69359103,"tx_offset":7,"log_offset":4,"tx_hash":"0x624e11be91bbe75a616ea2945ed89ce07698626e85b992989e57adafd4e59740","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000989372a0689ea95561","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2814529830045971207521"}]}}]},{"block_signed_at":"2021-09-08T06:18:47Z","block_height":69359124,"tx_hash":"0x31464f13b49e09316e7a73a6e1e0a2a84098fb41a8975d6c6c9f38adc1ebfaf5","tx_offset":4,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T06:19:08Z","block_height":69359145,"tx_hash":"0x73d07879b2472aebefa29a3ee38354c318fb61b5651082fdfbf98d975a3463cc","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:19:08Z","block_height":69359145,"tx_offset":3,"log_offset":5,"tx_hash":"0x73d07879b2472aebefa29a3ee38354c318fb61b5651082fdfbf98d975a3463cc","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":20,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":21,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd5f41190b6d63cec4f8b","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563840898096511030068531083"}]}},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":22,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":23,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c33e352027b518c64","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2881430997784950049892"}]}},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":24,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":25,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":26,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278488d1be1ee930900000000000000000000000000000000000000000000000278488e496db9df05","decoded":null},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":27,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002efe1ba01a46ae0a9d6fc00000000000000000000000000000000000000000004106eedb7214e6ed97b1d","decoded":null},{"block_signed_at":"2021-09-08T06:22:14Z","block_height":69359331,"tx_offset":3,"log_offset":28,"tx_hash":"0xd2021a31d3d3bc65f54d49eff7205d9028864b7fd38061558ebcf3723f74bdf0","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c33e352027b518c64","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2881430997784950049892"}]}}]},{"block_signed_at":"2021-09-08T06:22:50Z","block_height":69359367,"tx_hash":"0x43fcf31e01305ca28ca623f1307149adbdd3356a42b2dd86dc094d9b5a0671fc","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"2882000000000000000000","value_quote":4174.515609741211,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T06:32:10Z","block_height":69359927,"tx_hash":"0x7e681a709c1ccb14e7f73feff5d12010326b219f97e032759155f293418edbb2","tx_offset":6,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:32:10Z","block_height":69359927,"tx_offset":6,"log_offset":3,"tx_hash":"0x7e681a709c1ccb14e7f73feff5d12010326b219f97e032759155f293418edbb2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T06:33:06Z","block_height":69359983,"tx_hash":"0x7cc77ca297a72c07740f02260c648b2665b61e57a300cbc7986bbc8a1ed36bea","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:33:06Z","block_height":69359983,"tx_offset":6,"log_offset":21,"tx_hash":"0x7cc77ca297a72c07740f02260c648b2665b61e57a300cbc7986bbc8a1ed36bea","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000941761b6a1af6bb5d7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2731802951450175976919"}]}},{"block_signed_at":"2021-09-08T06:33:06Z","block_height":69359983,"tx_offset":6,"log_offset":22,"tx_hash":"0x7cc77ca297a72c07740f02260c648b2665b61e57a300cbc7986bbc8a1ed36bea","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000941761b6a1af6bb5d7","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2731802951450175976919"}]}},{"block_signed_at":"2021-09-08T06:33:06Z","block_height":69359983,"tx_offset":6,"log_offset":23,"tx_hash":"0x7cc77ca297a72c07740f02260c648b2665b61e57a300cbc7986bbc8a1ed36bea","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T06:33:06Z","block_height":69359983,"tx_offset":6,"log_offset":24,"tx_hash":"0x7cc77ca297a72c07740f02260c648b2665b61e57a300cbc7986bbc8a1ed36bea","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004557607ef5b574c1000000000000000000000000000000000000000000000000455761164af1f6f0","decoded":null},{"block_signed_at":"2021-09-08T06:33:06Z","block_height":69359983,"tx_offset":6,"log_offset":25,"tx_hash":"0x7cc77ca297a72c07740f02260c648b2665b61e57a300cbc7986bbc8a1ed36bea","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002f3e4f0b758bc7049c299000000000000000000000000000000000000000000040b01625b9dbe0c945671","decoded":null},{"block_signed_at":"2021-09-08T06:33:06Z","block_height":69359983,"tx_offset":6,"log_offset":26,"tx_hash":"0x7cc77ca297a72c07740f02260c648b2665b61e57a300cbc7986bbc8a1ed36bea","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000941761b6a1af6bb5d7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2731802951450175976919"}]}},{"block_signed_at":"2021-09-08T06:33:06Z","block_height":69359983,"tx_offset":6,"log_offset":27,"tx_hash":"0x7cc77ca297a72c07740f02260c648b2665b61e57a300cbc7986bbc8a1ed36bea","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000941761b6a1af6bb5d7","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2731802951450175976919"}]}}]},{"block_signed_at":"2021-09-08T06:34:26Z","block_height":69360063,"tx_hash":"0xcf85bddf6c8c74b424edeb6f06d556feb6b5a68c2c1b3c21617be550bc4eae9d","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:34:26Z","block_height":69360063,"tx_offset":5,"log_offset":0,"tx_hash":"0xcf85bddf6c8c74b424edeb6f06d556feb6b5a68c2c1b3c21617be550bc4eae9d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000093d4ba33bc1a3c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2727000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T06:34:51Z","block_height":69360088,"tx_hash":"0x1ad0ded427609bb76f7bbf0f3545527446fcdaca39f719287d2ad13f4053d5ad","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.01043245055580139,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":42,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8e24b5f2e721fb5d7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000802951450175976919"}]}},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":43,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd51b2f4557a7cacc99b4","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563836897293559579892554164"}]}},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":44,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8e24b5f2e721fb5d7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000802951450175976919"}]}},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":45,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8e24b5f2e721fb5d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a05e1fcd76be6c33da","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000802951450175976919"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2958261417267256112090"}]}},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":46,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053488fa17a487edd","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6001204427175263965"}]}},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":47,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053488fa17a487edd","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6001204427175263965"}]}},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":48,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000053488fa17a487edd0000000000000000000000000000000000000000000000027848a2d572eceead0000000000000000000000000000000000000000000000027848a404b393855c","decoded":null},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":49,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002fa4af9f26be37b3394500000000000000000000000000000000000000000000404b08e5e3648ea42586c","decoded":null},{"block_signed_at":"2021-09-08T06:39:19Z","block_height":69360356,"tx_offset":7,"log_offset":50,"tx_hash":"0x5668d72c9cf368fc1f6a19f9002e2112b985876650ebfd5598bf39db745b46f1","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8e24b5f2e721fb5d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a05e1fcd76be6c33da","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000802951450175976919"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2958261417267256112090"}]}}]},{"block_signed_at":"2021-09-08T06:40:43Z","block_height":69360440,"tx_hash":"0xde1e9b8bb5bab2eb11e14ca5c078a42eec9604addd6e5fbbbca20b4c27fe0cb9","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"2958000000000000000000","value_quote":4284.599990844727,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T06:44:17Z","block_height":69360654,"tx_hash":"0x2fc3a35be910e16ddd9b93e92e4cb580ecf4fd1088c692a4fea8402dd297860b","tx_offset":16,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:44:17Z","block_height":69360654,"tx_offset":16,"log_offset":38,"tx_hash":"0x2fc3a35be910e16ddd9b93e92e4cb580ecf4fd1088c692a4fea8402dd297860b","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000e3fb735a941727d400","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4205529830050000000000"}]}}]},{"block_signed_at":"2021-09-08T06:47:25Z","block_height":69360842,"tx_hash":"0xe4c50ab8ed301a5aaa2dd723e96cb4a826d30c8ba92958183d1c2aad9fbfb405","tx_offset":8,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:47:25Z","block_height":69360842,"tx_offset":8,"log_offset":47,"tx_hash":"0xe4c50ab8ed301a5aaa2dd723e96cb4a826d30c8ba92958183d1c2aad9fbfb405","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000091c003c51d3a2cf0f5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2688614009897418027253"}]}},{"block_signed_at":"2021-09-08T06:47:25Z","block_height":69360842,"tx_offset":8,"log_offset":48,"tx_hash":"0xe4c50ab8ed301a5aaa2dd723e96cb4a826d30c8ba92958183d1c2aad9fbfb405","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000091c003c51d3a2cf0f5","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2688614009897418027253"}]}},{"block_signed_at":"2021-09-08T06:47:25Z","block_height":69360842,"tx_offset":8,"log_offset":49,"tx_hash":"0xe4c50ab8ed301a5aaa2dd723e96cb4a826d30c8ba92958183d1c2aad9fbfb405","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T06:47:25Z","block_height":69360842,"tx_offset":8,"log_offset":50,"tx_hash":"0xe4c50ab8ed301a5aaa2dd723e96cb4a826d30c8ba92958183d1c2aad9fbfb405","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455776bb648f83ef00000000000000000000000000000000000000000000000045577753b3e68e4a","decoded":null},{"block_signed_at":"2021-09-08T06:47:25Z","block_height":69360842,"tx_offset":8,"log_offset":51,"tx_hash":"0xe4c50ab8ed301a5aaa2dd723e96cb4a826d30c8ba92958183d1c2aad9fbfb405","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002ff04b6829dade94baa3b0000000000000000000000000000000000000000000409a43a819077f4a05879","decoded":null},{"block_signed_at":"2021-09-08T06:47:25Z","block_height":69360842,"tx_offset":8,"log_offset":52,"tx_hash":"0xe4c50ab8ed301a5aaa2dd723e96cb4a826d30c8ba92958183d1c2aad9fbfb405","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000091c003c51d3a2cf0f5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2688614009897418027253"}]}},{"block_signed_at":"2021-09-08T06:47:25Z","block_height":69360842,"tx_offset":8,"log_offset":53,"tx_hash":"0xe4c50ab8ed301a5aaa2dd723e96cb4a826d30c8ba92958183d1c2aad9fbfb405","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000091c003c51d3a2cf0f5","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2688614009897418027253"}]}}]},{"block_signed_at":"2021-09-08T06:48:01Z","block_height":69360878,"tx_hash":"0xac68f08e8e3309efb4578034767649c67a53633dcdab9f6e962085038bae84b8","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T06:48:01Z","block_height":69360878,"tx_offset":1,"log_offset":0,"tx_hash":"0xac68f08e8e3309efb4578034767649c67a53633dcdab9f6e962085038bae84b8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000009ce25162ee4c780000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2894000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T06:49:18Z","block_height":69360955,"tx_hash":"0xf017a9a5a4ef2c70c5d355d0c1fb25666a2e7cfbf658bfc58ca83db497d66925","tx_offset":6,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.01043245055580139,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":10,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8d925bcc304dcc4f5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000143839947418027253"}]}},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":11,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd442561f9ae4c5efd4bf","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563832897149719632474526911"}]}},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":12,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8d925bcc304dcc4f5","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000143839947418027253"}]}},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":13,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8d925bcc304dcc4f500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a563c5c36c4a5bf9b9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000143839947418027253"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3050902139412114307513"}]}},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":14,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053450c7171cc9e80","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000215759921127040"}]}},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":15,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000000053450c7171cc9e81","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000215759921127041"}]}},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":16,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000000053450c7171cc9e810000000000000000000000000000000000000000000000027848a764ff87d3a30000000000000000000000000000000000000000000000027848a89f2a31f3c1","decoded":null},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":17,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000002fa179566854c02f5b8fa00000000000000000000000000000000000000000003e50d68a5b3092a50a665","decoded":null},{"block_signed_at":"2021-09-08T07:06:17Z","block_height":69361974,"tx_offset":2,"log_offset":18,"tx_hash":"0x879609689e1ff210ecff1ceaa90062d411adf080d0f622861c78caff7a0f5c57","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8d925bcc304dcc4f500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a563c5c36c4a5bf9b9","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000143839947418027253"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3050902139412114307513"}]}}]},{"block_signed_at":"2021-09-08T07:08:14Z","block_height":69362091,"tx_hash":"0xa913b5c43c4a0fdac67214a8d0387998e63d5de1c77abe1aff82390c5c5cebb8","tx_offset":11,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3051000000000000000000","value_quote":4419.308509826661,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T07:10:13Z","block_height":69362210,"tx_hash":"0x56f75c953da1da9fce04e71dc05801cf39d23f86482e21d866677c130f14b4b6","tx_offset":5,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T07:10:13Z","block_height":69362210,"tx_offset":5,"log_offset":31,"tx_hash":"0x56f75c953da1da9fce04e71dc05801cf39d23f86482e21d866677c130f14b4b6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":4,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":5,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd369b67bbe9be8ffd4bf","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563828901149719632474526911"}]}},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":6,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":7,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a8b4663788dcfe6aa4","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3112052142818618927780"}]}},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":8,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":9,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":10,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027848b0fcb69ddea90000000000000000000000000000000000000000000000027848b2392e767e24","decoded":null},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":11,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000302973b820e96f894f61b00000000000000000000000000000000000000000003db5840196071eb306e60","decoded":null},{"block_signed_at":"2021-09-08T07:14:06Z","block_height":69362443,"tx_offset":3,"log_offset":12,"tx_hash":"0x108855aa820512f7efcfffb1b37f090f1335e16df01031ac4508b45dbe33c150","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a8b4663788dcfe6aa4","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3112052142818618927780"}]}}]},{"block_signed_at":"2021-09-08T07:14:41Z","block_height":69362478,"tx_hash":"0x945e3b3a37e307ac89d476b5b3742a8102c0eb5e37a2cb20b8eec3e113b6bba3","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3112000000000000000000","value_quote":4507.665710449219,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T07:19:08Z","block_height":69362745,"tx_hash":"0x277ecbbd27c416a934bc0e83fa47949208b08b312d80da8f12e9ae49617d8717","tx_offset":10,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T07:19:08Z","block_height":69362745,"tx_offset":10,"log_offset":4,"tx_hash":"0x277ecbbd27c416a934bc0e83fa47949208b08b312d80da8f12e9ae49617d8717","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000b4d84cd51d4f200000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3336000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":1,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000b4d84cd51d4f200000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3336000000000000000000"}]}},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":2,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd2b4de2ee97e99dfd4bf","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563825565149719632474526911"}]}},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":3,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000b4d84cd51d4f200000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3336000000000000000000"}]}},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":4,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000b4d84cd51d4f200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e9ecb19b14e542c66","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3336000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2630879925994335251558"}]}},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":5,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000004571c77cd80e0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5004000000000000000"}]}},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":6,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000004571c77cd80e0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5004000000000000000"}]}},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":7,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000004571c77cd80e00000000000000000000000000000000000000000000000000027848c1b6c828f2320000000000000000000000000000000000000000000000027848c2c4b096981e","decoded":null},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":8,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000308a077164a0cbf1219ba00000000000000000000000000000000000000000003d6869ddce0ee4172b585","decoded":null},{"block_signed_at":"2021-09-08T07:48:39Z","block_height":69364516,"tx_offset":2,"log_offset":9,"tx_hash":"0xd4357e12227a27872c75be5a8b13d631da3b56486268ab6fe8d4c6db6960d2a4","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000b4d84cd51d4f200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e9ecb19b14e542c66","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3336000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2630879925994335251558"}]}}]},{"block_signed_at":"2021-09-08T07:48:58Z","block_height":69364535,"tx_hash":"0x3951ab68fa01c002f378bd61c848b51f6d9df7117600f2be84550ab0e91de28a","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"2631000000000000000000","value_quote":3810.9474563598637,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T07:53:25Z","block_height":69364802,"tx_hash":"0xbb495d9b99eef42e60c605c898632e3b1665fd4d92a7da160a6c91dd40822bfe","tx_offset":5,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T07:53:25Z","block_height":69364802,"tx_offset":5,"log_offset":0,"tx_hash":"0xbb495d9b99eef42e60c605c898632e3b1665fd4d92a7da160a6c91dd40822bfe","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":1,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":2,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd1dc3e8b0d35bcefd4bf","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563821569149719632474526911"}]}},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":3,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":4,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a5e4bf0523b51714e3","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3060195670974195504355"}]}},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":5,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":6,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":7,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb100000000000000000000000000000000000000000000000000027848e54527c2c1410000000000000000000000000000000000000000000000027848e6895be149f4","decoded":null},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":8,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030286ca319a80b024693500000000000000000000000000000000000000000003ebfa53b43a30c2cb39e5","decoded":null},{"block_signed_at":"2021-09-08T08:08:49Z","block_height":69365726,"tx_offset":6,"log_offset":9,"tx_hash":"0x749c3c6b4d051c64c356571c7155ae1faa4fd5ff225e0b3111b7137893f0b8b5","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a5e4bf0523b51714e3","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3060195670974195504355"}]}}]},{"block_signed_at":"2021-09-08T08:09:37Z","block_height":69365774,"tx_hash":"0x586e30cb98fdfe3b7906d5259a598c28866922050c7dc2b77a87de4a89bebe02","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3060000000000000000000","value_quote":4432.344818115234,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T08:17:20Z","block_height":69366237,"tx_hash":"0xd2381948a2b9d7e6d492bc7e5c48c3892293cc3aba166cd121c7ae5d18b542b5","tx_offset":4,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T08:17:20Z","block_height":69366237,"tx_offset":4,"log_offset":2,"tx_hash":"0xd2381948a2b9d7e6d492bc7e5c48c3892293cc3aba166cd121c7ae5d18b542b5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","tx_offset":5,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":3,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":4,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd1039ee730ecdfffd4bf","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563817573149719632474526911"}]}},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":5,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":6,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151e6351c445e85de","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2975827258624475825630"}]}},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":7,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":8,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":9,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb10000000000000000000000000000000000000000000000000002784905487bf957c20000000000000000000000000000000000000000000000027849068cc43a1d96","decoded":null},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":10,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000030d83d42120ad72249fb600000000000000000000000000000000000000000004172110e733c1d6ab3cd8","decoded":null},{"block_signed_at":"2021-09-08T08:18:18Z","block_height":69366295,"tx_offset":5,"log_offset":11,"tx_hash":"0x0b4d8b295f7b1c52951c55d32b2ea967d3e87f32fceb2f44645f327744dfeb69","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a151e6351c445e85de","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2975827258624475825630"}]}}]},{"block_signed_at":"2021-09-08T08:18:31Z","block_height":69366308,"tx_hash":"0x4601cdd4eab587ca0dbf0299bcd31d092c187f7f00c658e377622fff0914ed0f","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"2976000000000000000000","value_quote":4310.672607421875,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T08:22:20Z","block_height":69366537,"tx_hash":"0xcb02b388c14889d6a3b46d43b6634e8644409aee89c9c5fdb5a832faec725274","tx_offset":12,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T08:22:20Z","block_height":69366537,"tx_offset":12,"log_offset":27,"tx_hash":"0xcb02b388c14889d6a3b46d43b6634e8644409aee89c9c5fdb5a832faec725274","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":6,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":7,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffd02aff4354a4030fd4bf","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563813577149719632474526911"}]}},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":8,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":9,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a93833b9e5cdfd126d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3121549533343504994925"}]}},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":10,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":11,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":12,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278491cd8c422e53300000000000000000000000000000000000000000000000278491e1ef439af5d","decoded":null},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":13,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000322356d1e799296ac7a340000000000000000000000000000000000000000000400b2710e06f10ee024d8","decoded":null},{"block_signed_at":"2021-09-08T08:31:04Z","block_height":69367061,"tx_offset":3,"log_offset":14,"tx_hash":"0x7de0443873a73cb057f9f407c73fc576e96128a77a8077a68d76125760abf9c2","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a93833b9e5cdfd126d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3121549533343504994925"}]}}]},{"block_signed_at":"2021-09-08T08:32:05Z","block_height":69367122,"tx_hash":"0x9e0b45c2779cee9555b5e64bd4ded1a5895914e1be86a67c12fe6b4b17cbafc1","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3121000000000000000000","value_quote":4520.702018737792,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T08:37:11Z","block_height":69367428,"tx_hash":"0x952c30b3c334c1eb9cdd3f2dcefe32d8b27649f5708f926b5194f1d55ec5a624","tx_offset":3,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T08:37:11Z","block_height":69367428,"tx_offset":3,"log_offset":2,"tx_hash":"0x952c30b3c334c1eb9cdd3f2dcefe32d8b27649f5708f926b5194f1d55ec5a624","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T08:49:20Z","block_height":69368157,"tx_hash":"0xd7f043d3ee75e1610fed9b6124adc0bf7a23e9fa3a0df512162ede0ca4f324da","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":247544,"gas_price":25000000000,"fees_paid":"6188600000000000","gas_quote":0.008964055274963379,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T08:49:20Z","block_height":69368157,"tx_offset":7,"log_offset":33,"tx_hash":"0xd7f043d3ee75e1610fed9b6124adc0bf7a23e9fa3a0df512162ede0ca4f324da","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008707dcf66b7b06cb2d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2490877048545417284397"}]}},{"block_signed_at":"2021-09-08T08:49:20Z","block_height":69368157,"tx_offset":7,"log_offset":34,"tx_hash":"0xd7f043d3ee75e1610fed9b6124adc0bf7a23e9fa3a0df512162ede0ca4f324da","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008707dcf66b7b06cb2d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2490877048545417284397"}]}},{"block_signed_at":"2021-09-08T08:49:20Z","block_height":69368157,"tx_offset":7,"log_offset":35,"tx_hash":"0xd7f043d3ee75e1610fed9b6124adc0bf7a23e9fa3a0df512162ede0ca4f324da","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T08:49:20Z","block_height":69368157,"tx_offset":7,"log_offset":36,"tx_hash":"0xd7f043d3ee75e1610fed9b6124adc0bf7a23e9fa3a0df512162ede0ca4f324da","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045580be7960494aa00000000000000000000000000000000000000000000000045580c8eafb17c79","decoded":null},{"block_signed_at":"2021-09-08T08:49:20Z","block_height":69368157,"tx_offset":7,"log_offset":37,"tx_hash":"0xd7f043d3ee75e1610fed9b6124adc0bf7a23e9fa3a0df512162ede0ca4f324da","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000032ba1505c7ae16ba413e100000000000000000000000000000000000000000003f5597f828e136f85c385","decoded":null},{"block_signed_at":"2021-09-08T08:49:20Z","block_height":69368157,"tx_offset":7,"log_offset":38,"tx_hash":"0xd7f043d3ee75e1610fed9b6124adc0bf7a23e9fa3a0df512162ede0ca4f324da","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008707dcf66b7b06cb2d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2490877048545417284397"}]}},{"block_signed_at":"2021-09-08T08:49:20Z","block_height":69368157,"tx_offset":7,"log_offset":39,"tx_hash":"0xd7f043d3ee75e1610fed9b6124adc0bf7a23e9fa3a0df512162ede0ca4f324da","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000008707dcf66b7b06cb2d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2490877048545417284397"}]}}]},{"block_signed_at":"2021-09-08T08:49:48Z","block_height":69368185,"tx_hash":"0x5c83bd71dfdff037fbab594ab0e28daa5e40146157333979ca2720ee6aed2723","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T08:49:48Z","block_height":69368185,"tx_offset":4,"log_offset":15,"tx_hash":"0x5c83bd71dfdff037fbab594ab0e28daa5e40146157333979ca2720ee6aed2723","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000086c42e349b85180000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2486000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T08:50:32Z","block_height":69368229,"tx_hash":"0x01197e4600afe18d2b95a08090f81f3abeaa56443dd4d5ec1535f4345a31a538","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T09:22:58Z","block_height":69370175,"tx_hash":"0xc29273603f8d10f55e5ac83832495ef293fd1241855d510b09af87f7229ea7a4","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:22:58Z","block_height":69370175,"tx_offset":1,"log_offset":1,"tx_hash":"0xc29273603f8d10f55e5ac83832495ef293fd1241855d510b09af87f7229ea7a4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000085711e8f3a4f151d10","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2461568071659555200272"}]}},{"block_signed_at":"2021-09-08T09:22:58Z","block_height":69370175,"tx_offset":1,"log_offset":2,"tx_hash":"0xc29273603f8d10f55e5ac83832495ef293fd1241855d510b09af87f7229ea7a4","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000085711e8f3a4f151d10","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2461568071659555200272"}]}},{"block_signed_at":"2021-09-08T09:22:58Z","block_height":69370175,"tx_offset":1,"log_offset":3,"tx_hash":"0xc29273603f8d10f55e5ac83832495ef293fd1241855d510b09af87f7229ea7a4","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T09:22:58Z","block_height":69370175,"tx_offset":1,"log_offset":4,"tx_hash":"0xc29273603f8d10f55e5ac83832495ef293fd1241855d510b09af87f7229ea7a4","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455826168b303e07000000000000000000000000000000000000000000000000455826be11349c5b","decoded":null},{"block_signed_at":"2021-09-08T09:22:58Z","block_height":69370175,"tx_offset":1,"log_offset":5,"tx_hash":"0xc29273603f8d10f55e5ac83832495ef293fd1241855d510b09af87f7229ea7a4","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003363a443c4a18731a2a2e00000000000000000000000000000000000000000003f682292363502cafbc56","decoded":null},{"block_signed_at":"2021-09-08T09:22:58Z","block_height":69370175,"tx_offset":1,"log_offset":6,"tx_hash":"0xc29273603f8d10f55e5ac83832495ef293fd1241855d510b09af87f7229ea7a4","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000085711e8f3a4f151d10","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2461568071659555200272"}]}},{"block_signed_at":"2021-09-08T09:22:58Z","block_height":69370175,"tx_offset":1,"log_offset":7,"tx_hash":"0xc29273603f8d10f55e5ac83832495ef293fd1241855d510b09af87f7229ea7a4","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000085711e8f3a4f151d10","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2461568071659555200272"}]}}]},{"block_signed_at":"2021-09-08T09:23:16Z","block_height":69370193,"tx_hash":"0xda0e770bc44699d9faa3243dcbadeb9769288b57177d0f31da4c9624e2a7eed0","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:23:16Z","block_height":69370193,"tx_offset":0,"log_offset":0,"tx_hash":"0xda0e770bc44699d9faa3243dcbadeb9769288b57177d0f31da4c9624e2a7eed0","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000085ae9fee9271480000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2466000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T09:24:31Z","block_height":69370268,"tx_hash":"0xb2be693c6340571c8be0a6a8e4494e34a2ca313d40f2fbe520cdb3dabb726ea7","tx_offset":16,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.01043245055580139,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":0,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a5d13ec0b0abe83d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996445120204972484669"}]}},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":1,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffcf52597215e35263ec82","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563809580704599427502042242"}]}},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":2,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8a5d13ec0b0abe83d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996445120204972484669"}]}},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":3,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8a5d13ec0b0abe83d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4ae6f5fa5edd02799","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996445120204972484669"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3332983303518997718937"}]}},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":4,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005331567e7f3db2a7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994667680307458727"}]}},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":5,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005331567e7f3db2a7","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994667680307458727"}]}},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":6,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005331567e7f3db2a700000000000000000000000000000000000000000000000278495f297da45f510000000000000000000000000000000000000000000000027849607894846dc9","decoded":null},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":7,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033b5dc1dfd92644e0d99b00000000000000000000000000000000000000000003ddedca0676b2f7212c5c","decoded":null},{"block_signed_at":"2021-09-08T09:44:48Z","block_height":69371485,"tx_offset":0,"log_offset":8,"tx_hash":"0x5a47cc0a9920fc34e4359a8ebaaf688cc8e132328d1b5a94e2b8ce637473247a","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8a5d13ec0b0abe83d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4ae6f5fa5edd02799","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996445120204972484669"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3332983303518997718937"}]}}]},{"block_signed_at":"2021-09-08T09:45:12Z","block_height":69371509,"tx_hash":"0xe915e7aa748c50b9304211c4c01472a4928f9eb6def96313d2212f31c44b5eac","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xda6dc30a494e79b458077bd1df60c8f75d541b2c","to_address_label":null,"value":"3333000000000000000000","value_quote":4827.779502868651,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T09:46:36Z","block_height":69371593,"tx_hash":"0x5245d7305b5e41fb56cb5cdfbaf4a3217fecd762dd33ba4e97eff964742ebe74","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":416455,"gas_spent":273690,"gas_price":25000000000,"fees_paid":"6842250000000000","gas_quote":0.00991085337638855,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:46:36Z","block_height":69371593,"tx_offset":2,"log_offset":1,"tx_hash":"0x5245d7305b5e41fb56cb5cdfbaf4a3217fecd762dd33ba4e97eff964742ebe74","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000080ae00c22ea21efc19","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2373721476302966291481"}]}},{"block_signed_at":"2021-09-08T09:46:36Z","block_height":69371593,"tx_offset":2,"log_offset":2,"tx_hash":"0x5245d7305b5e41fb56cb5cdfbaf4a3217fecd762dd33ba4e97eff964742ebe74","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000080ae00c22ea21efc19","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2373721476302966291481"}]}},{"block_signed_at":"2021-09-08T09:46:36Z","block_height":69371593,"tx_offset":2,"log_offset":3,"tx_hash":"0x5245d7305b5e41fb56cb5cdfbaf4a3217fecd762dd33ba4e97eff964742ebe74","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T09:46:36Z","block_height":69371593,"tx_offset":2,"log_offset":4,"tx_hash":"0x5245d7305b5e41fb56cb5cdfbaf4a3217fecd762dd33ba4e97eff964742ebe74","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004558544df88187f7000000000000000000000000000000000000000000000000455854f41e75cd25","decoded":null},{"block_signed_at":"2021-09-08T09:46:36Z","block_height":69371593,"tx_offset":2,"log_offset":5,"tx_hash":"0x5245d7305b5e41fb56cb5cdfbaf4a3217fecd762dd33ba4e97eff964742ebe74","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033dad59b32f0368a399b000000000000000000000000000000000000000000003db2bee21592027b65261","decoded":null},{"block_signed_at":"2021-09-08T09:46:36Z","block_height":69371593,"tx_offset":2,"log_offset":6,"tx_hash":"0x5245d7305b5e41fb56cb5cdfbaf4a3217fecd762dd33ba4e97eff964742ebe74","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000080ae00c22ea21efc19","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2373721476302966291481"}]}},{"block_signed_at":"2021-09-08T09:46:36Z","block_height":69371593,"tx_offset":2,"log_offset":7,"tx_hash":"0x5245d7305b5e41fb56cb5cdfbaf4a3217fecd762dd33ba4e97eff964742ebe74","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000080ae00c22ea21efc19","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2373721476302966291481"}]}}]},{"block_signed_at":"2021-09-08T09:47:00Z","block_height":69371617,"tx_hash":"0x6eb619847ce0b032872e2259921f8028c3da191bd73ee5e7468158399b1dd11a","tx_offset":0,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77485,"gas_spent":36657,"gas_price":25000000000,"fees_paid":"916425000000000","gas_quote":0.0013274220914840699,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:47:00Z","block_height":69371617,"tx_offset":0,"log_offset":0,"tx_hash":"0x6eb619847ce0b032872e2259921f8028c3da191bd73ee5e7468158399b1dd11a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000080ae00c22ea21efc19","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2373721476302966291481"}]}}]},{"block_signed_at":"2021-09-08T09:47:14Z","block_height":69371631,"tx_hash":"0xb1a4178eed0ffb372c97297ed763178aa8d3d2166524de346356705472995f79","tx_offset":7,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T09:49:13Z","block_height":69371750,"tx_hash":"0x905351fd055cf5616a08aa9df9a2a2330e89b25f0a78f1c33c70f7b34221e39f","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:49:13Z","block_height":69371750,"tx_offset":1,"log_offset":0,"tx_hash":"0x905351fd055cf5616a08aa9df9a2a2330e89b25f0a78f1c33c70f7b34221e39f","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T09:50:50Z","block_height":69371847,"tx_hash":"0xb2d8ffc7a2b5fa3b2206c5001de14c03ed5a9ca4b1799b52bde406263b747240","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:50:50Z","block_height":69371847,"tx_offset":1,"log_offset":0,"tx_hash":"0xb2d8ffc7a2b5fa3b2206c5001de14c03ed5a9ca4b1799b52bde406263b747240","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007e47ab4894e8f6213d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2329454054489514713405"}]}},{"block_signed_at":"2021-09-08T09:50:50Z","block_height":69371847,"tx_offset":1,"log_offset":1,"tx_hash":"0xb2d8ffc7a2b5fa3b2206c5001de14c03ed5a9ca4b1799b52bde406263b747240","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007e47ab4894e8f6213d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2329454054489514713405"}]}},{"block_signed_at":"2021-09-08T09:50:50Z","block_height":69371847,"tx_offset":1,"log_offset":2,"tx_hash":"0xb2d8ffc7a2b5fa3b2206c5001de14c03ed5a9ca4b1799b52bde406263b747240","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T09:50:50Z","block_height":69371847,"tx_offset":1,"log_offset":3,"tx_hash":"0xb2d8ffc7a2b5fa3b2206c5001de14c03ed5a9ca4b1799b52bde406263b747240","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004558618b5647ac19000000000000000000000000000000000000000000000000455862317baae6a6","decoded":null},{"block_signed_at":"2021-09-08T09:50:50Z","block_height":69371847,"tx_offset":1,"log_offset":4,"tx_hash":"0xb2d8ffc7a2b5fa3b2206c5001de14c03ed5a9ca4b1799b52bde406263b747240","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003458578b78e52d41f699000000000000000000000000000000000000000000003d1ecfe4d4dd5e574bbcd","decoded":null},{"block_signed_at":"2021-09-08T09:50:50Z","block_height":69371847,"tx_offset":1,"log_offset":5,"tx_hash":"0xb2d8ffc7a2b5fa3b2206c5001de14c03ed5a9ca4b1799b52bde406263b747240","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007e47ab4894e8f6213d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2329454054489514713405"}]}},{"block_signed_at":"2021-09-08T09:50:50Z","block_height":69371847,"tx_offset":1,"log_offset":6,"tx_hash":"0xb2d8ffc7a2b5fa3b2206c5001de14c03ed5a9ca4b1799b52bde406263b747240","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd00000000000000000000000000000000000000000000007e47ab4894e8f6213d","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2329454054489514713405"}]}}]},{"block_signed_at":"2021-09-08T09:51:10Z","block_height":69371867,"tx_hash":"0x0d2a74c2c1e162088248356dc1c37582accb9d08cc9347dc84299113ae917474","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:51:10Z","block_height":69371867,"tx_offset":4,"log_offset":6,"tx_hash":"0x0d2a74c2c1e162088248356dc1c37582accb9d08cc9347dc84299113ae917474","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000007e09db4d9f3f340000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2325000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T09:51:28Z","block_height":69371885,"tx_hash":"0x268f5f2448184ed43281befa865ecf143d913d1a55763305c2b0ead8830ec440","tx_offset":7,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","tx_offset":7,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461235,"gas_spent":288094,"gas_price":25000000000,"fees_paid":"7202350000000000","gas_quote":0.01043245055580139,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":7,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dd73d73e86b2213d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000454054489514713405"}]}},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":8,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffce797bfe3ea4cbb1cb45","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563805580250544937987328837"}]}},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":9,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d8dd73d73e86b2213d","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"4000454054489514713405"}]}},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":10,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dd73d73e86b2213d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b9c87db4179ad51094","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000454054489514713405"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3427094554829416370324"}]}},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":11,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005346b3a69f2d9446","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000681081734272070"}]}},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":12,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000005346b3a69f2d9446","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"6000681081734272070"}]}},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":13,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000005346b3a69f2d944600000000000000000000000000000000000000000000000278496781eb649c63000000000000000000000000000000000000000000000002784968cd319dae7d","decoded":null},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":14,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003468a42341c63dbee600f00000000000000000000000000000000000000000003d0bccf2f5edc337e1ed3","decoded":null},{"block_signed_at":"2021-09-08T09:57:38Z","block_height":69372255,"tx_offset":7,"log_offset":15,"tx_hash":"0xfe59299deb1dfa1ca96f8fb61f4967ee0f49dbe78fa1751b0095d058d5eb1598","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d8dd73d73e86b2213d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b9c87db4179ad51094","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"4000454054489514713405"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3427094554829416370324"}]}}]},{"block_signed_at":"2021-09-08T09:58:23Z","block_height":69372300,"tx_hash":"0xa2466fdb9779674283448b940e4a74048df3aebc375c5fd8c6e051953f0b3ad7","tx_offset":2,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3427000000000000000000","value_quote":4963.936500549317,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T10:06:13Z","block_height":69372770,"tx_hash":"0x8e5b91633228cda7d4288055c616bbccd30432542ef96fd5876e4cf63301904a","tx_offset":4,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T10:06:13Z","block_height":69372770,"tx_offset":4,"log_offset":0,"tx_hash":"0x8e5b91633228cda7d4288055c616bbccd30432542ef96fd5876e4cf63301904a","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","tx_offset":12,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":461043,"gas_spent":287966,"gas_price":25000000000,"fees_paid":"7199150000000000","gas_quote":0.010427815423965453,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":90,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":91,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0xffffffffffffffffffffffffffffffffffffffffffffcda0dc5a625beec1cb45","decoded":{"name":"Approval","signature":"Approval(indexed address owner, indexed address spender, uint256 value)","params":[{"name":"owner","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"spender","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"115792089237316195423570985008687907853269984665640563801584250544937987328837"}]}},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":92,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":93,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b532d063b81c5aadbe","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3342522213480881892798"}]}},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":94,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000076f0f12f9e01c819e1ff03fe6db637dcdae65581"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":95,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x00000000000000000000000071b59e4bc2995b57aa03437ed645ada7dd5b1890"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000000532ef73e0fb10000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"5994000000000000000"}]}},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":96,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000000532ef73e0fb1000000000000000000000000000000000000000000000000000278497b72599b5a5300000000000000000000000000000000000000000000000278497cbc0c69aa59","decoded":null},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":97,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033cb5f39a63f7c8c4387900000000000000000000000000000000000000000003dc994b7b0b14f63e439e","decoded":null},{"block_signed_at":"2021-09-08T10:07:03Z","block_height":69372820,"tx_offset":12,"log_offset":98,"tx_hash":"0x9c2c655fe95c2ac891a6c6821a1d1d72255f10a44aa384220a77f021eba3346d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x0000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000d89fa3dc48dcf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b532d063b81c5aadbe","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"3342522213480881892798"}]}}]},{"block_signed_at":"2021-09-08T10:07:26Z","block_height":69372843,"tx_hash":"0x3f99944421dede613d3976039411675c1c035712e7c154aa3a39ce7a4fd1ac99","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x34e79a3a54d5b1295620967468113df95ecccb18","to_address_label":null,"value":"3343000000000000000000","value_quote":4842.264289855958,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T10:12:07Z","block_height":69373124,"tx_hash":"0xe03a9d5720ebc2fe1b0d92c355b02a24e368f4c2b5b939cfaf4d6efc47210b90","tx_offset":1,"successful":true,"from_address":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":1000000,"gas_spent":66137,"gas_price":25000000000,"fees_paid":"1653425000000000","gas_quote":0.0023949508924484253,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T10:12:07Z","block_height":69373124,"tx_offset":1,"log_offset":0,"tx_hash":"0xe03a9d5720ebc2fe1b0d92c355b02a24e368f4c2b5b939cfaf4d6efc47210b90","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000003ca2c2e883d4ef03eee21124edad2dda8e7bb6ce","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000d89fa3dc48dcf00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x3ca2c2e883d4ef03eee21124edad2dda8e7bb6ce"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"3996000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T10:16:10Z","block_height":69373367,"tx_hash":"0x32058023964e8896a2081b044ef7f7e79731862071318d0169457a05075722b3","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":376614,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T10:16:10Z","block_height":69373367,"tx_offset":3,"log_offset":2,"tx_hash":"0x32058023964e8896a2081b044ef7f7e79731862071318d0169457a05075722b3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000082cd921b8224d20740","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2412889661952394135360"}]}},{"block_signed_at":"2021-09-08T10:16:10Z","block_height":69373367,"tx_offset":3,"log_offset":3,"tx_hash":"0x32058023964e8896a2081b044ef7f7e79731862071318d0169457a05075722b3","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000082cd921b8224d20740","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2412889661952394135360"}]}},{"block_signed_at":"2021-09-08T10:16:10Z","block_height":69373367,"tx_offset":3,"log_offset":4,"tx_hash":"0x32058023964e8896a2081b044ef7f7e79731862071318d0169457a05075722b3","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T10:16:10Z","block_height":69373367,"tx_offset":3,"log_offset":5,"tx_hash":"0x32058023964e8896a2081b044ef7f7e79731862071318d0169457a05075722b3","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c00000000000000000000000000000000000000000000000000004558707f1b1bb53300000000000000000000000000000000000000000000000045587123d50883da","decoded":null},{"block_signed_at":"2021-09-08T10:16:10Z","block_height":69373367,"tx_offset":3,"log_offset":6,"tx_hash":"0x32058023964e8896a2081b044ef7f7e79731862071318d0169457a05075722b3","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f800000000000000000000000000000000000000000003370e6900ee0012a48a1900000000000000000000000000000000000000000003e372ed84b3ca42ee0c03","decoded":null},{"block_signed_at":"2021-09-08T10:16:10Z","block_height":69373367,"tx_offset":3,"log_offset":7,"tx_hash":"0x32058023964e8896a2081b044ef7f7e79731862071318d0169457a05075722b3","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000082cd921b8224d20740","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2412889661952394135360"}]}},{"block_signed_at":"2021-09-08T10:16:10Z","block_height":69373367,"tx_offset":3,"log_offset":8,"tx_hash":"0x32058023964e8896a2081b044ef7f7e79731862071318d0169457a05075722b3","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000082cd921b8224d20740","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2412889661952394135360"}]}}]},{"block_signed_at":"2021-09-08T10:16:31Z","block_height":69373388,"tx_hash":"0x94461f4b41a909e1b114de05855fe6bf8d19e52a25edc6d5501a4b76a453f2bf","tx_offset":3,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T10:16:31Z","block_height":69373388,"tx_offset":3,"log_offset":6,"tx_hash":"0x94461f4b41a909e1b114de05855fe6bf8d19e52a25edc6d5501a4b76a453f2bf","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008289b689de84a00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2408000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T10:18:25Z","block_height":69373502,"tx_hash":"0xf28f017994d878b17a85120e0e0eb8f7fcb8ee38388e1aa17a2c10c66923f2b7","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T10:21:51Z","block_height":69373708,"tx_hash":"0x2cc3614f9166686bcb9893351b2885cf3a29a6c0bbaaa92bbde3dcd4310c8dc6","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T10:21:51Z","block_height":69373708,"tx_offset":1,"log_offset":6,"tx_hash":"0x2cc3614f9166686bcb9893351b2885cf3a29a6c0bbaaa92bbde3dcd4310c8dc6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000082863e4bbff2d259b3","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2407749981919664822707"}]}},{"block_signed_at":"2021-09-08T10:21:51Z","block_height":69373708,"tx_offset":1,"log_offset":7,"tx_hash":"0x2cc3614f9166686bcb9893351b2885cf3a29a6c0bbaaa92bbde3dcd4310c8dc6","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000082863e4bbff2d259b3","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2407749981919664822707"}]}},{"block_signed_at":"2021-09-08T10:21:51Z","block_height":69373708,"tx_offset":1,"log_offset":8,"tx_hash":"0x2cc3614f9166686bcb9893351b2885cf3a29a6c0bbaaa92bbde3dcd4310c8dc6","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T10:21:51Z","block_height":69373708,"tx_offset":1,"log_offset":9,"tx_hash":"0x2cc3614f9166686bcb9893351b2885cf3a29a6c0bbaaa92bbde3dcd4310c8dc6","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455871dc2647d52800000000000000000000000000000000000000000000000045587280e034a3cf","decoded":null},{"block_signed_at":"2021-09-08T10:21:51Z","block_height":69373708,"tx_offset":1,"log_offset":10,"tx_hash":"0x2cc3614f9166686bcb9893351b2885cf3a29a6c0bbaaa92bbde3dcd4310c8dc6","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f80000000000000000000000000000000000000000000337ef1e9a10f894de77b100000000000000000000000000000000000000000003e263710f26e170c0da17","decoded":null},{"block_signed_at":"2021-09-08T10:21:51Z","block_height":69373708,"tx_offset":1,"log_offset":11,"tx_hash":"0x2cc3614f9166686bcb9893351b2885cf3a29a6c0bbaaa92bbde3dcd4310c8dc6","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000082863e4bbff2d259b3","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2407749981919664822707"}]}},{"block_signed_at":"2021-09-08T10:21:51Z","block_height":69373708,"tx_offset":1,"log_offset":12,"tx_hash":"0x2cc3614f9166686bcb9893351b2885cf3a29a6c0bbaaa92bbde3dcd4310c8dc6","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000082863e4bbff2d259b3","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2407749981919664822707"}]}}]},{"block_signed_at":"2021-09-08T10:26:38Z","block_height":69373995,"tx_hash":"0x1abc25ffc219cb591727a96ca1816ae1296b099c1b96cf2508afa84669378f91","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T10:26:38Z","block_height":69373995,"tx_offset":1,"log_offset":0,"tx_hash":"0x1abc25ffc219cb591727a96ca1816ae1296b099c1b96cf2508afa84669378f91","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008289b689de84a00000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2408000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T10:29:11Z","block_height":69374148,"tx_hash":"0x53a36d78daf2bdcbf5cc8b70b9f815bd11fc6117bac0ea9760efa258138fdde1","tx_offset":12,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T11:11:54Z","block_height":69376711,"tx_hash":"0x84218fc6dbc25caccf48e53c65c0c7204f82da9d40443bb9a7a677acba0ed8a5","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T11:11:54Z","block_height":69376711,"tx_offset":1,"log_offset":18,"tx_hash":"0x84218fc6dbc25caccf48e53c65c0c7204f82da9d40443bb9a7a677acba0ed8a5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000083ab1a6c1a120452f4","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2428852759445058638580"}]}},{"block_signed_at":"2021-09-08T11:11:54Z","block_height":69376711,"tx_offset":1,"log_offset":19,"tx_hash":"0x84218fc6dbc25caccf48e53c65c0c7204f82da9d40443bb9a7a677acba0ed8a5","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000083ab1a6c1a120452f4","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2428852759445058638580"}]}},{"block_signed_at":"2021-09-08T11:11:54Z","block_height":69376711,"tx_offset":1,"log_offset":20,"tx_hash":"0x84218fc6dbc25caccf48e53c65c0c7204f82da9d40443bb9a7a677acba0ed8a5","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T11:11:54Z","block_height":69376711,"tx_offset":1,"log_offset":21,"tx_hash":"0x84218fc6dbc25caccf48e53c65c0c7204f82da9d40443bb9a7a677acba0ed8a5","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c000000000000000000000000000000000000000000000000000045588a8fa139d7c300000000000000000000000000000000000000000000000045588b340999d876","decoded":null},{"block_signed_at":"2021-09-08T11:11:54Z","block_height":69376711,"tx_offset":1,"log_offset":22,"tx_hash":"0x84218fc6dbc25caccf48e53c65c0c7204f82da9d40443bb9a7a677acba0ed8a5","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033cda4a557c3b880ca0b800000000000000000000000000000000000000000003f11857102bb39df4f994","decoded":null},{"block_signed_at":"2021-09-08T11:11:54Z","block_height":69376711,"tx_offset":1,"log_offset":23,"tx_hash":"0x84218fc6dbc25caccf48e53c65c0c7204f82da9d40443bb9a7a677acba0ed8a5","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000083ab1a6c1a120452f4","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2428852759445058638580"}]}},{"block_signed_at":"2021-09-08T11:11:54Z","block_height":69376711,"tx_offset":1,"log_offset":24,"tx_hash":"0x84218fc6dbc25caccf48e53c65c0c7204f82da9d40443bb9a7a677acba0ed8a5","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd000000000000000000000000000000000000000000000083ab1a6c1a120452f4","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2428852759445058638580"}]}}]},{"block_signed_at":"2021-09-08T11:12:15Z","block_height":69376732,"tx_hash":"0xec58453f828c1ad755bfd46967423495f3d72c98e5d7100d42ce57fd69697db8","tx_offset":1,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T11:12:15Z","block_height":69376732,"tx_offset":1,"log_offset":24,"tx_hash":"0xec58453f828c1ad755bfd46967423495f3d72c98e5d7100d42ce57fd69697db8","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x000000000000000000000000000000000000000000000083e4a86169dd640000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2433000000000000000000"}]}}]},{"block_signed_at":"2021-09-08T11:23:52Z","block_height":69377429,"tx_hash":"0xd23e71c582f4cb34ae051b627a27cca1184aa598237c630cab2702d79db8edbc","tx_offset":2,"successful":true,"from_address":"0xca4753ef46f847d1b8e8c20947f6e2e78bc1145e","from_address_label":null,"to_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":21000,"gas_spent":21000,"gas_price":25000000000,"fees_paid":"525000000000000","gas_quote":7.604513168334961E-4,"gas_quote_rate":1.4484786987304688,"log_events":[]},{"block_signed_at":"2021-09-08T11:28:48Z","block_height":69377725,"tx_hash":"0x044f62b49f88601d5c72365985938561cc35567ed87b772304468de11d47103d","tx_offset":6,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","to_address_label":null,"value":"2000000000000000000000","value_quote":2896.9573974609375,"gas_offered":393598,"gas_spent":258690,"gas_price":25000000000,"fees_paid":"6467250000000000","gas_quote":0.009367673864364623,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T11:28:48Z","block_height":69377725,"tx_offset":6,"log_offset":14,"tx_hash":"0x044f62b49f88601d5c72365985938561cc35567ed87b772304468de11d47103d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000838bb8557114e65202","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2426591364567108309506"}]}},{"block_signed_at":"2021-09-08T11:28:48Z","block_height":69377725,"tx_offset":6,"log_offset":15,"tx_hash":"0x044f62b49f88601d5c72365985938561cc35567ed87b772304468de11d47103d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap LP KLAY-WEMIX","sender_contract_ticker_symbol":"KSLP","sender_address":"0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x917eed7ae9e7d3b0d875dd393af93fff3fc301f8.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000838bb8557114e65202","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2426591364567108309506"}]}},{"block_signed_at":"2021-09-08T11:28:48Z","block_height":69377725,"tx_offset":6,"log_offset":16,"tx_hash":"0x044f62b49f88601d5c72365985938561cc35567ed87b772304468de11d47103d","raw_log_topics":["0x4d6ce1e535dbade1c23defba91e23b8f791ce5edc0cc320257a2b364e4e38426"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x76f0f12f9e01c819e1ff03fe6db637dcdae65581","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x76f0f12f9e01c819e1ff03fe6db637dcdae65581.png","raw_log_data":"0x00000000000000000000000000000000000000000000000029a2241af62c0000","decoded":{"name":"Deposit","signature":"Deposit(uint256 amount)","params":[{"name":"amount","type":"uint256","indexed":false,"decoded":true,"value":"3000000000000000000"}]}},{"block_signed_at":"2021-09-08T11:28:48Z","block_height":69377725,"tx_offset":6,"log_offset":17,"tx_hash":"0x044f62b49f88601d5c72365985938561cc35567ed87b772304468de11d47103d","raw_log_topics":["0x9181d11d0cefdea6375986af545b86f0b46455519be8a436f1c33800fe76bfc9"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x71b59e4bc2995b57aa03437ed645ada7dd5b1890","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x71b59e4bc2995b57aa03437ed645ada7dd5b1890.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a2241af62c0000000000000000000000000000000000000000000000000000455895bf921d80590000000000000000000000000000000000000000000000004558966340b6c1d1","decoded":null},{"block_signed_at":"2021-09-08T11:28:48Z","block_height":69377725,"tx_offset":6,"log_offset":18,"tx_hash":"0x044f62b49f88601d5c72365985938561cc35567ed87b772304468de11d47103d","raw_log_topics":["0xc95e30a514d4115dee44b3ba17b2fc114501726562d4c5f2663c06f42df8f1e7"],"sender_contract_decimals":0,"sender_name":null,"sender_contract_ticker_symbol":null,"sender_address":"0x1289550d988177575154c2ca45c95ccfb32f837d","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x1289550d988177575154c2ca45c95ccfb32f837d.png","raw_log_data":"0x000000000000000000000000917eed7ae9e7d3b0d875dd393af93fff3fc301f8000000000000000000000000000000000000000000033d2cac7b657ee9b084a000000000000000000000000000000000000000000003f08c141504b2c3c3647e","decoded":null},{"block_signed_at":"2021-09-08T11:28:48Z","block_height":69377725,"tx_offset":6,"log_offset":19,"tx_hash":"0x044f62b49f88601d5c72365985938561cc35567ed87b772304468de11d47103d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x0000000000000000000000000000000000000000000000838bb8557114e65202","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2426591364567108309506"}]}},{"block_signed_at":"2021-09-08T11:28:48Z","block_height":69377725,"tx_offset":6,"log_offset":20,"tx_hash":"0x044f62b49f88601d5c72365985938561cc35567ed87b772304468de11d47103d","raw_log_topics":["0x022d176d604c15661a2acf52f28fd69bdd2c755884c08a67132ffeb8098330e0"],"sender_contract_decimals":18,"sender_name":"KlaySwap Protocol","sender_contract_ticker_symbol":"KSP","sender_address":"0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xc6a2ad8cc6e4a7e08fc37cc5954be07d499e7654.png","raw_log_data":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c6b935b8bbd4000000000000000000000000000005096db80b21ef45230c9e423c373f1fc9c0198dd0000000000000000000000000000000000000000000000838bb8557114e65202","decoded":{"name":"ExchangePos","signature":"ExchangePos(address tokenA, uint256 amountA, address tokenB, uint256 amountB)","params":[{"name":"tokenA","type":"address","indexed":false,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"amountA","type":"uint256","indexed":false,"decoded":true,"value":"2000000000000000000000"},{"name":"tokenB","type":"address","indexed":false,"decoded":true,"value":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd"},{"name":"amountB","type":"uint256","indexed":false,"decoded":true,"value":"2426591364567108309506"}]}}]},{"block_signed_at":"2021-09-08T11:31:06Z","block_height":69377863,"tx_hash":"0xb9059ddd23209a88b05d6fe985e5baf7a2bbbddcef06121555185acaacbd7311","tx_offset":4,"successful":true,"from_address":"0x99c839a196497eda48c5dee9545ce10d497fd8f5","from_address_label":null,"to_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":77389,"gas_spent":51593,"gas_price":25000000000,"fees_paid":"1289825000000000","gas_quote":0.001868284037590027,"gas_quote_rate":1.4484786987304688,"log_events":[{"block_signed_at":"2021-09-08T11:31:06Z","block_height":69377863,"tx_offset":4,"log_offset":1,"tx_hash":"0xb9059ddd23209a88b05d6fe985e5baf7a2bbbddcef06121555185acaacbd7311","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000099c839a196497eda48c5dee9545ce10d497fd8f5","0x00000000000000000000000034e79a3a54d5b1295620967468113df95ecccb18"],"sender_contract_decimals":18,"sender_name":"WEMIX TOKEN","sender_contract_ticker_symbol":"WEMIX","sender_address":"0x5096db80b21ef45230c9e423c373f1fc9c0198dd","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0x5096db80b21ef45230c9e423c373f1fc9c0198dd.png","raw_log_data":"0x00000000000000000000000000000000000000000000008359e13e65537c0000","decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, uint256 value)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0x99c839a196497eda48c5dee9545ce10d497fd8f5"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x34e79a3a54d5b1295620967468113df95ecccb18"},{"name":"value","type":"uint256","indexed":false,"decoded":true,"value":"2423000000000000000000"}]}}]},{"block_signed_at":"2022-09-01T02:41:24Z","block_height":100098862,"tx_hash":"0x65ac822f48604ae696d59e7c0f85d55cff44a44beea6ebbd393d5feeca1f211d","tx_offset":5,"successful":true,"from_address":"0xc067a53c91258ba513059919e03b81cf93f57ac7","from_address_label":null,"to_address":"0xd915c8ad3241f459a45adcbbf8af42caa561a154","to_address_label":null,"value":"0","value_quote":0.0,"gas_offered":105850,"gas_spent":88209,"gas_price":50000000000,"fees_paid":"4410450000000000","gas_quote":0.0010263838992856443,"gas_quote_rate":0.232716366648674,"log_events":[{"block_signed_at":"2022-09-01T02:41:24Z","block_height":100098862,"tx_offset":5,"log_offset":2,"tx_hash":"0x65ac822f48604ae696d59e7c0f85d55cff44a44beea6ebbd393d5feeca1f211d","raw_log_topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x000000000000000000000000c067a53c91258ba513059919e03b81cf93f57ac7","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000004e27"],"sender_contract_decimals":0,"sender_name":"STL HQ Door","sender_contract_ticker_symbol":"OFFICE","sender_address":"0xd915c8ad3241f459a45adcbbf8af42caa561a154","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xd915c8ad3241f459a45adcbbf8af42caa561a154.png","raw_log_data":null,"decoded":{"name":"Approval","signature":"Approval(indexed address from, indexed address to, indexed uint256 tokenId)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc067a53c91258ba513059919e03b81cf93f57ac7"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0x0000000000000000000000000000000000000000"},{"name":"tokenId","type":"uint256","indexed":true,"decoded":true,"value":"20007"}]}},{"block_signed_at":"2022-09-01T02:41:24Z","block_height":100098862,"tx_offset":5,"log_offset":3,"tx_hash":"0x65ac822f48604ae696d59e7c0f85d55cff44a44beea6ebbd393d5feeca1f211d","raw_log_topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000c067a53c91258ba513059919e03b81cf93f57ac7","0x000000000000000000000000f9c883c8dca140ebbdc87a225fe6e330be5d25ef","0x0000000000000000000000000000000000000000000000000000000000004e27"],"sender_contract_decimals":0,"sender_name":"STL HQ Door","sender_contract_ticker_symbol":"OFFICE","sender_address":"0xd915c8ad3241f459a45adcbbf8af42caa561a154","sender_address_label":null,"sender_logo_url":"https://logos.covalenthq.com/tokens/8217/0xd915c8ad3241f459a45adcbbf8af42caa561a154.png","raw_log_data":null,"decoded":{"name":"Transfer","signature":"Transfer(indexed address from, indexed address to, indexed uint256 tokenId)","params":[{"name":"from","type":"address","indexed":true,"decoded":true,"value":"0xc067a53c91258ba513059919e03b81cf93f57ac7"},{"name":"to","type":"address","indexed":true,"decoded":true,"value":"0xf9c883c8dca140ebbdc87a225fe6e330be5d25ef"},{"name":"tokenId","type":"uint256","indexed":true,"decoded":true,"value":"20007"}]}}]}],"pagination":{"has_more":true,"page_number":0,"page_size":400,"total_count":null}},"error":false,"error_message":null,"error_code":null} \ No newline at end of file From 19797fdff441fcd070fa556f23c89aaf5552a02a Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 3 Sep 2022 11:12:15 +1000 Subject: [PATCH 085/183] Improve integration test --- .../app/TokenScriptCertificateTest.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java index 4ae079d56a..869505f9c6 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java @@ -1,6 +1,8 @@ package com.alphawallet.app; import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.Espresso.pressBack; +import static androidx.test.espresso.action.ViewActions.replaceText; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; import static com.alphawallet.app.assertions.Should.shouldSee; @@ -8,7 +10,7 @@ import static com.alphawallet.app.steps.Steps.selectTestNet; import static com.alphawallet.app.steps.Steps.switchToWallet; import static com.alphawallet.app.util.Helper.click; -import static com.alphawallet.app.util.Helper.waitUntil; +import static org.hamcrest.Matchers.allOf; import androidx.test.espresso.action.ViewActions; @@ -24,7 +26,7 @@ public class TokenScriptCertificateTest extends BaseE2ETest { private static final String password = "hellohello"; @Test - public void cipher_integrity_test_keystore() { + public void certificate_test() { importKSWalletFromFrontPage(keystore, password); selectTestNet("Kovan"); @@ -33,13 +35,28 @@ public void cipher_integrity_test_keystore() { switchToWallet("0xF9c883c8DcA140EBbdC87a225Fe6E330BE5D25ef"); //Wait for TokensService engine to resolve the STL token - Helper.wait(8); + Helper.wait(1); + + //add the token manually since test doesn't seem to work normally + click(withId(R.id.action_my_wallet)); + click(withSubstring("Add / Hide Tokens")); + Helper.wait(1); + click(withId(R.id.action_add)); + Helper.wait(1); + + onView(allOf(withId(R.id.edit_text))).perform(replaceText("0x9afb1e2822edab926d0dea894f8864368b7bb47a")); + + Helper.wait(15); + + click(withId(R.id.select_token)); + + click(withSubstring("Save")); + + pressBack(); //Swipe up onView(withId(R.id.coordinator)).perform(ViewActions.swipeUp()); - waitUntil(withSubstring("OFFIC"), 600); - //Select token click(withSubstring("OFFIC")); From 1418d2c8d00092edb04ad083ff731abea4c5dbba Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 3 Sep 2022 16:28:21 +1000 Subject: [PATCH 086/183] Update --- app/src/androidTest/java/com/alphawallet/app/steps/Steps.java | 2 ++ app/src/main/res/layout/activity_add_custom_rpc_network.xml | 1 + 2 files changed, 3 insertions(+) diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index d2aba1c16d..1d2f97d546 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -198,6 +198,8 @@ public static void addNewNetwork(String name) input(R.id.input_network_symbol, "ETH"); input(R.id.input_network_explorer_api, url); input(R.id.input_network_block_explorer_url, url); + onView(withId(R.id.network_input_scroll)).perform(ViewActions.swipeUp()); + Helper.wait(1); click(withId(R.id.checkbox_testnet)); click(withId(R.string.action_add_network)); pressBack(); diff --git a/app/src/main/res/layout/activity_add_custom_rpc_network.xml b/app/src/main/res/layout/activity_add_custom_rpc_network.xml index b229c8bfc2..b6c35d629a 100644 --- a/app/src/main/res/layout/activity_add_custom_rpc_network.xml +++ b/app/src/main/res/layout/activity_add_custom_rpc_network.xml @@ -8,6 +8,7 @@ Date: Mon, 5 Sep 2022 10:32:16 +1000 Subject: [PATCH 087/183] Small update to fix Ganache compatibility --- .../app/repository/TokenRepository.java | 47 ++++++++++++++++--- .../app/repository/TokenRepositoryType.java | 17 ++----- .../app/service/TokensService.java | 8 ++-- .../app/viewmodel/AddTokenViewModel.java | 17 ++----- .../app/viewmodel/ImportTokenViewModel.java | 4 +- .../app/viewmodel/SendViewModel.java | 7 +-- 6 files changed, 56 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java index 01e2bff1a0..b8f2e36293 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java @@ -1,6 +1,5 @@ package com.alphawallet.app.repository; -import static com.alphawallet.app.entity.tokenscript.TokenscriptFunction.ZERO_ADDRESS; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; @@ -28,8 +27,8 @@ import com.alphawallet.app.service.AWHttpService; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.TickerService; -import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.util.Utils; +import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.token.entity.ContractAddress; import com.alphawallet.token.entity.MagicLinkData; @@ -99,6 +98,7 @@ public class TokenRepository implements TokenRepositoryType { private final Map web3jNodeServers; private AWEnsResolver ensResolver; + private String currentAddress; public TokenRepository( EthereumNetworkRepositoryType ethereumNetworkRepository, @@ -114,6 +114,7 @@ public TokenRepository( this.tickerService = tickerService; web3jNodeServers = new ConcurrentHashMap<>(); + currentAddress = ethereumNetworkRepository.getCurrentWalletAddress(); } private void buildWeb3jClient(NetworkInfo networkInfo) @@ -192,6 +193,12 @@ public Single checkInterface(Token[] tokens, Wallet wallet) }).flatMap(this::checkTokenData); } + @Override + public void updateLocalAddress(String walletAddress) + { + currentAddress = walletAddress; + } + @Override public TokenCardMeta[] fetchTokenMetasForUpdate(Wallet wallet, List networkFilters) { @@ -371,9 +378,21 @@ public void setVisibilityChanged(Wallet wallet, Token token) } @Override - public Single update(String contractAddr, long chainId) + public Single update(String contractAddr, long chainId, ContractType type) { - return setupTokensFromLocal(contractAddr, chainId); + switch (type) + { + case ERC721: + case ERC875_LEGACY: + case ERC721_LEGACY: + case ERC721_UNDETERMINED: + case ERC1155: + case ERC875: + case ERC721_TICKET: + return setupNFTFromLocal(contractAddr, chainId); + default: + return setupTokensFromLocal(contractAddr, chainId); + } } @Override @@ -531,6 +550,7 @@ private Token wrappedCheckUint256Balance(@NonNull Wallet wallet, @NonNull TokenI NetworkInfo network = ethereumNetworkRepository.getNetworkByChain(tokenInfo.chainId); String responseValue = callSmartContractFunction(function, tokenInfo.address, network, wallet); + if (!TextUtils.isEmpty(responseValue)) { List response = FunctionReturnDecoder.decode(responseValue, function.getOutputParameters()); @@ -660,7 +680,7 @@ public Observable burnListenerObservable(String contr private T getContractData(NetworkInfo network, String address, Function function, T type) throws Exception { - String responseValue = callSmartContractFunction(function, address, network, new Wallet(ZERO_ADDRESS)); + String responseValue = callSmartContractFunction(function, address, network, new Wallet(currentAddress)); if (TextUtils.isEmpty(responseValue)) { @@ -789,7 +809,7 @@ private String filterAscii(String name) private int getDecimals(String address, NetworkInfo network) throws Exception { if (EthereumNetworkRepository.decimalOverride(address, network.chainId) > 0) return EthereumNetworkRepository.decimalOverride(address, network.chainId); Function function = decimalsOf(); - String responseValue = callSmartContractFunction(function, address, network, new Wallet(ZERO_ADDRESS)); + String responseValue = callSmartContractFunction(function, address, network, new Wallet(currentAddress)); if (TextUtils.isEmpty(responseValue)) return 18; List response = FunctionReturnDecoder.decode( @@ -1051,6 +1071,19 @@ private Single setupTokensFromLocal(String address, long chainId) }).onErrorReturnItem(new TokenInfo()); } + private Single setupNFTFromLocal(String address, long chainId) + { + return Single.fromCallable(() -> { + NetworkInfo network = ethereumNetworkRepository.getNetworkByChain(chainId); + return new TokenInfo( + address, + getContractData(network, address, nameOf(), ""), + getContractData(network, address, symbolOf(), ""), + 0, + false, chainId); + }).onErrorReturnItem(new TokenInfo()); + } + private Single checkTokenData(Token[] tokens) { return Single.fromCallable(() -> { @@ -1136,7 +1169,7 @@ else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE catch (Exception e) { isERC875 = false; } try { - responseValue = callSmartContractFunction(balanceOf(ZERO_ADDRESS), tokenInfo.address, network, new Wallet(ZERO_ADDRESS)); + responseValue = callSmartContractFunction(balanceOf(currentAddress), tokenInfo.address, network, new Wallet(currentAddress)); } catch (Exception e) { responseValue = ""; } diff --git a/app/src/main/java/com/alphawallet/app/repository/TokenRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/TokenRepositoryType.java index 164053bc2c..4d7d5c8b95 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokenRepositoryType.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokenRepositoryType.java @@ -4,21 +4,11 @@ import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.ContractType; -import com.alphawallet.app.entity.SubscribeWrapper; -import com.alphawallet.app.entity.tokendata.TokenGroup; -import com.alphawallet.app.entity.tokens.Token; -import com.alphawallet.app.entity.tokens.TokenCardMeta; -import com.alphawallet.app.entity.tokens.TokenInfo; -import com.alphawallet.app.entity.tokendata.TokenTicker; -import com.alphawallet.app.entity.TransferFromEventResponse; -import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.service.AssetDefinitionService; - -import io.reactivex.disposables.Disposable; - import com.alphawallet.app.entity.TransferFromEventResponse; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.nftassets.NFTAsset; +import com.alphawallet.app.entity.tokendata.TokenGroup; +import com.alphawallet.app.entity.tokendata.TokenTicker; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; import com.alphawallet.app.entity.tokens.TokenInfo; @@ -41,7 +31,7 @@ public interface TokenRepositoryType { Single checkInterface(Token[] tokens, Wallet wallet); void setEnable(Wallet wallet, Token token, boolean isEnabled); void setVisibilityChanged(Wallet wallet, Token token); - Single update(String address, long chainId); + Single update(String address, long chainId, ContractType type); Observable burnListenerObservable(String contractAddress); Single getEthTicker(long chainId); TokenTicker getTokenTicker(Token token); @@ -60,6 +50,7 @@ public interface TokenRepositoryType { Single fetchIsRedeemed(Token token, BigInteger tokenId); void addImageUrl(long chainId, String address, String imageUrl); + void updateLocalAddress(String walletAddress); Single fetchTokenMetas(Wallet wallet, List networkFilters, AssetDefinitionService svs); diff --git a/app/src/main/java/com/alphawallet/app/service/TokensService.java b/app/src/main/java/com/alphawallet/app/service/TokensService.java index 29a8a283cb..c76e4b2712 100644 --- a/app/src/main/java/com/alphawallet/app/service/TokensService.java +++ b/app/src/main/java/com/alphawallet/app/service/TokensService.java @@ -131,10 +131,11 @@ private void checkUnknownTokens() { ContractAddress t = unknownTokens.pollFirst(); Token cachedToken = t != null ? getToken(t.chainId, t.address) : null; + ContractType type = cachedToken != null ? cachedToken.getInterfaceSpec() : ContractType.NOT_SET; if (t != null && t.address.length() > 0 && (cachedToken == null || TextUtils.isEmpty(cachedToken.tokenInfo.name))) { - queryUnknownTokensDisposable = tokenRepository.update(t.address, t.chainId).toObservable() //fetch tokenInfo + queryUnknownTokensDisposable = tokenRepository.update(t.address, t.chainId, type).toObservable() //fetch tokenInfo .filter(tokenInfo -> (!TextUtils.isEmpty(tokenInfo.name) || !TextUtils.isEmpty(tokenInfo.symbol)) && tokenInfo.chainId != 0) .map(tokenInfo -> { tokenInfo.isEnabled = false; return tokenInfo; }) //set default visibility to false .flatMap(tokenInfo -> tokenRepository.determineCommonType(tokenInfo).toObservable() @@ -215,6 +216,7 @@ public void setCurrentAddress(String newWalletAddr) stopUpdateCycle(); addLockedTokens(); if (openseaService != null) openseaService.resetOffsetRead(networkFilter); + tokenRepository.updateLocalAddress(newWalletAddr); } } @@ -524,8 +526,8 @@ public void addTokenImageUrl(long networkId, String address, String imageUrl) tokenRepository.addImageUrl(networkId, address, imageUrl); } - public Single update(String address, long chainId) { - return tokenRepository.update(address, chainId) + public Single update(String address, long chainId, ContractType type) { + return tokenRepository.update(address, chainId, type) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/AddTokenViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/AddTokenViewModel.java index 383a8bf583..d9256cd899 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/AddTokenViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/AddTokenViewModel.java @@ -3,7 +3,6 @@ import android.content.Context; import android.content.Intent; -import androidx.annotation.NonNull; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -14,11 +13,9 @@ import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenInfo; -import com.alphawallet.app.interact.FetchTokensInteract; import com.alphawallet.app.interact.FetchTransactionsInteract; import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; -import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.TokensService; import com.alphawallet.app.ui.ImportTokenActivity; @@ -40,7 +37,6 @@ public class AddTokenViewModel extends BaseViewModel { private final MutableLiveData wallet = new MutableLiveData<>(); - private final MutableLiveData tokenInfo = new MutableLiveData<>(); private final MutableLiveData switchNetwork = new MutableLiveData<>(); private final MutableLiveData finalisedToken = new MutableLiveData<>(); private final MutableLiveData tokentype = new MutableLiveData<>(); @@ -52,11 +48,9 @@ public class AddTokenViewModel extends BaseViewModel { private final EthereumNetworkRepositoryType ethereumNetworkRepository; private final GenericWalletInteract genericWalletInteract; - private final FetchTokensInteract fetchTokensInteract; private final FetchTransactionsInteract fetchTransactionsInteract; private final AssetDefinitionService assetDefinitionService; private final TokensService tokensService; - private final PreferenceRepositoryType sharedPreference; private boolean foundNetwork; private int networkCount; @@ -80,19 +74,15 @@ public MutableLiveData wallet() { @Inject AddTokenViewModel( GenericWalletInteract genericWalletInteract, - FetchTokensInteract fetchTokensInteract, EthereumNetworkRepositoryType ethereumNetworkRepository, FetchTransactionsInteract fetchTransactionsInteract, AssetDefinitionService assetDefinitionService, - TokensService tokensService, - PreferenceRepositoryType sharedPreference) { + TokensService tokensService) { this.genericWalletInteract = genericWalletInteract; - this.fetchTokensInteract = fetchTokensInteract; this.ethereumNetworkRepository = ethereumNetworkRepository; this.fetchTransactionsInteract = fetchTransactionsInteract; this.assetDefinitionService = assetDefinitionService; this.tokensService = tokensService; - this.sharedPreference = sharedPreference; } public void saveTokens(List toSave) @@ -131,7 +121,7 @@ private void checkType(Throwable throwable, long chainId, String address, Contra public void fetchToken(long chainId, String addr) { - tokensService.update(addr, chainId) + tokensService.update(addr, chainId, ContractType.NOT_SET) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::gotTokenUpdate, this::onError).isDisposed(); @@ -222,6 +212,7 @@ private List getNetworkIds() { if (!networkIds.contains(networkInfo.chainId)) networkIds.add(networkInfo.chainId); } + return networkIds; } @@ -253,7 +244,7 @@ private void testNetworkResult(final TokenInfo info, final ContractType type) { foundNetwork = true; disposable = tokensService - .update(info.address, info.chainId) + .update(info.address, info.chainId, type) .subscribe(this::onTokensSetup, error -> checkType(error, info.chainId, info.address, type)); } else diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/ImportTokenViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/ImportTokenViewModel.java index d1f77e0345..480c065e0b 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/ImportTokenViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/ImportTokenViewModel.java @@ -45,8 +45,6 @@ import com.alphawallet.token.entity.XMLDsigDescriptor; import com.alphawallet.token.tools.ParseMagicLink; -import org.web3j.protocol.core.methods.response.EthEstimateGas; - import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -249,7 +247,7 @@ private void fetchToken() { private void setupTokenAddr(String contractAddress) { disposable = tokensService - .update(contractAddress, importOrder.chainId) + .update(contractAddress, importOrder.chainId, ContractType.NOT_SET) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(this::getTokenSpec, this::onError); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java index 3ca0f220a6..f5bafdb5dc 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java @@ -8,6 +8,7 @@ import com.alphawallet.app.C; import com.alphawallet.app.entity.AnalyticsProperties; +import com.alphawallet.app.entity.ContractType; import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.TransactionData; @@ -17,20 +18,16 @@ import com.alphawallet.app.interact.CreateTransactionInteract; import com.alphawallet.app.interact.FetchTransactionsInteract; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; -import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.router.MyAddressRouter; import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.GasService; import com.alphawallet.app.service.KeyService; -import com.alphawallet.app.util.RateApp; import com.alphawallet.app.service.TokensService; import com.alphawallet.app.ui.ImportTokenActivity; import com.alphawallet.app.web3.entity.Web3Transaction; -import org.web3j.protocol.core.methods.response.EthEstimateGas; - import java.math.BigDecimal; import java.math.BigInteger; @@ -107,7 +104,7 @@ public void showImportLink(Context context, String importTxt) public void fetchToken(long chainId, String address, String walletAddress) { - tokensService.update(address, chainId) + tokensService.update(address, chainId, ContractType.NOT_SET) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(tokenInfo -> gotTokenUpdate(tokenInfo, walletAddress), this::onError).isDisposed(); From d5e94344b36fd49276809b29e97128f7cf987f6a Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 5 Sep 2022 10:33:07 +1000 Subject: [PATCH 088/183] Move TokenScriptCertificateTest to work on Ganache --- .../app/TokenScriptCertificateTest.java | 95 ++++++++++++-- .../alphawallet/app/resources/Contracts.java | 9 ++ .../java/com/alphawallet/app/steps/Steps.java | 18 ++- .../com/alphawallet/app/util/EthUtils.java | 123 ++++++++++++++++++ 4 files changed, 229 insertions(+), 16 deletions(-) create mode 100644 app/src/androidTest/java/com/alphawallet/app/resources/Contracts.java create mode 100644 app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java diff --git a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java index 869505f9c6..eafcbb4aad 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java @@ -3,38 +3,106 @@ import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.Espresso.pressBack; import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.matcher.ViewMatchers.isRoot; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; import static com.alphawallet.app.assertions.Should.shouldSee; -import static com.alphawallet.app.steps.Steps.importKSWalletFromFrontPage; +import static com.alphawallet.app.steps.Steps.addNewNetwork; +import static com.alphawallet.app.steps.Steps.getWalletAddress; +import static com.alphawallet.app.steps.Steps.importPKWalletFromFrontPage; import static com.alphawallet.app.steps.Steps.selectTestNet; import static com.alphawallet.app.steps.Steps.switchToWallet; +import static com.alphawallet.app.util.EthUtils.GANACHE_URL; import static com.alphawallet.app.util.Helper.click; -import static org.hamcrest.Matchers.allOf; +import static com.alphawallet.app.util.Helper.waitUntil; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.AllOf.allOf; +import static org.junit.Assert.fail; + +import android.os.Build; import androidx.test.espresso.action.ViewActions; +import com.alphawallet.app.resources.Contracts; +import com.alphawallet.app.util.EthUtils; import com.alphawallet.app.util.Helper; import org.junit.Test; +import org.web3j.crypto.Credentials; +import org.web3j.crypto.Keys; +import org.web3j.protocol.Web3j; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; /** * Created by JB on 1/09/2022. */ public class TokenScriptCertificateTest extends BaseE2ETest { - private static final String keystore = "{\"address\":\"f9c883c8dca140ebbdc87a225fe6e330be5d25ef\",\"id\":\"5648908b-1862-4f3e-b425-d1ba0790a601\",\"version\":3,\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"bcbfcffb52f42e9d149b97a8512d4c49\"},\"ciphertext\":\"967d3cd0db82445e4e74a6d5e537c799632e91cf0ca6f9fec17c769812e9454f\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":4096,\"p\":6,\"r\":8,\"salt\":\"084c44b6e76e2b879257520ac00bb59c93e17321ce4a029f9b8294e304defc7a\"},\"mac\":\"0e4a74746d0c3e2739653200bcffb92716e77677d41f84c1184a4eb2054963c6\"}}\n"; - private static final String password = "hellohello"; + + private final String doorContractAddress; + private final String contractOwnerPk = "0x69c22d654be7fe75e31fbe26cb56c93ec91144fab67cb71529c8081971635069"; + private final Web3j web3j; + + private static final Map WALLETS_ON_GANACHE = new HashMap() {{ + put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); + put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); + put("32", new String[]{"0x992b442eaa34de3c6ba0b61c75b2e4e0241d865443e313c4fa6ab8ba488a6957", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); + }}; + + public TokenScriptCertificateTest() + { + int apiLevel = Build.VERSION.SDK_INT; + String[] array = WALLETS_ON_GANACHE.get(String.valueOf(apiLevel)); + if (array == null) { + fail("Please config seed phrase and wallet address for this API level first."); + } + + web3j = EthUtils.buildWeb3j(GANACHE_URL); + + String privateKey = array[0]; + + //create credentials for initial transfer + Credentials credentials = Credentials.create(privateKey); + + //create credentials for contract deployment (fixed so we can link to a tokenscript) + Credentials deployCredentials = Credentials.create(contractOwnerPk); + + //Transfer 1 eth into deployment wallet + EthUtils.transferFunds(web3j, credentials, deployCredentials.getAddress(), BigDecimal.ONE); + + //Deploy door contract + EthUtils.deployContract(web3j, deployCredentials, Contracts.doorContractCode); + + //Always use zero nonce for determining the contract address + doorContractAddress = EthUtils.calculateContractAddress(deployCredentials.getAddress(), 0L); + } @Test - public void certificate_test() { - importKSWalletFromFrontPage(keystore, password); + public void certificate_test() + { + int apiLevel = Build.VERSION.SDK_INT; + String[] array = WALLETS_ON_GANACHE.get(String.valueOf(apiLevel)); + if (array == null) + { + fail("Please config seed phrase and wallet address for this API level first."); + } + + Credentials deployCredentials = Credentials.create(contractOwnerPk); + String ownerAddress = Keys.toChecksumAddress(deployCredentials.getAddress()); - selectTestNet("Kovan"); + importPKWalletFromFrontPage(contractOwnerPk); + + assertThat(getWalletAddress(), equalTo(ownerAddress)); + + addNewNetwork("Ganache"); + selectTestNet("Ganache"); //Ensure we're on the wallet page - switchToWallet("0xF9c883c8DcA140EBbdC87a225Fe6E330BE5D25ef"); + switchToWallet(ownerAddress); - //Wait for TokensService engine to resolve the STL token Helper.wait(1); //add the token manually since test doesn't seem to work normally @@ -44,9 +112,9 @@ public void certificate_test() { click(withId(R.id.action_add)); Helper.wait(1); - onView(allOf(withId(R.id.edit_text))).perform(replaceText("0x9afb1e2822edab926d0dea894f8864368b7bb47a")); + onView(allOf(withId(R.id.edit_text))).perform(replaceText(doorContractAddress)); - Helper.wait(15); + onView(isRoot()).perform(waitUntil(withId(R.id.select_token), 30)); click(withId(R.id.select_token)); @@ -57,11 +125,14 @@ public void certificate_test() { //Swipe up onView(withId(R.id.coordinator)).perform(ViewActions.swipeUp()); + Helper.wait(1); + //Select token click(withSubstring("OFFIC")); //Wait for cert to resolve - Helper.wait(8); + //Helper.wait(8); + onView(isRoot()).perform(waitUntil(withId(R.id.image_lock), 30)); //click certificate click(withId(R.id.image_lock)); diff --git a/app/src/androidTest/java/com/alphawallet/app/resources/Contracts.java b/app/src/androidTest/java/com/alphawallet/app/resources/Contracts.java new file mode 100644 index 0000000000..87ca34788c --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/resources/Contracts.java @@ -0,0 +1,9 @@ +package com.alphawallet.app.resources; + +/** + * Created by JB on 4/09/2022. + */ +public abstract class Contracts +{ + public static String doorContractCode = "0x60806040523480156200001157600080fd5b506040518060400160405280600b81526020016a29aa26102428902237b7b960a91b815250604051806040016040528060068152602001654f464649434560d01b81525081600090816200006691906200042d565b5060016200007582826200042d565b505050620000926200008c620000e460201b60201c565b620000e8565b620000a960076200013a60201b62000e501760201c565b6040518060600160405280603581526020016200218360359139600a90620000d290826200042d565b50620000dd62000143565b5062000521565b3390565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80546001019055565b6006546000906001600160a01b03163314620001a65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b620001bd60076200023860201b62000e591760201c565b90506127108110620002125760405162461bcd60e51b815260206004820152601460248201527f486974207570706572206d696e74206c696d697400000000000000000000000060448201526064016200019d565b6200021e33826200023c565b6200023560076200013a60201b62000e501760201c565b90565b5490565b6001600160a01b038216620002945760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016200019d565b6000818152600260205260409020546001600160a01b031615620002fb5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016200019d565b6001600160a01b038216600090815260036020526040812080546001929062000326908490620004f9565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620003b457607f821691505b602082108103620003d557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200038457600081815260208120601f850160051c81016020861015620004045750805b601f850160051c820191505b81811015620004255782815560010162000410565b505050505050565b81516001600160401b0381111562000449576200044962000389565b62000461816200045a84546200039f565b84620003db565b602080601f831160018114620004995760008415620004805750858301515b600019600386901b1c1916600185901b17855562000425565b600085815260208120601f198616915b82811015620004ca57888601518255948401946001909101908401620004a9565b5085821015620004e95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b808201808211156200051b57634e487b7160e01b600052601160045260246000fd5b92915050565b611c5280620005316000396000f3fe60806040526004361061019c5760003560e01c806384c4bd4b116100ec578063a740fc871161008a578063e67876fe11610064578063e67876fe14610452578063e8a3d48514610469578063e985e9c51461047e578063f2fde38b1461049e57600080fd5b8063a740fc87146103fb578063b88d4fde14610412578063c87b56dd1461043257600080fd5b8063985e49f4116100c6578063985e49f4146103a95780639cb8a26a146103be578063a22cb465146103c6578063a49ff5b2146103e657600080fd5b806384c4bd4b1461035f5780638da5cb5b1461037657806395d89b411461039457600080fd5b80634bb309121161015957806370a082311161013357806370a08231146102e7578063715018a6146103155780637b47ec1a1461032a57806382345f991461034a57600080fd5b80634bb30912146102925780636352211e146102a75780636f3bffd2146102c757600080fd5b806301ffc9a7146101a157806306fdde03146101d6578063081812fc146101f8578063095ea7b31461023057806323b872dd1461025257806342842e0e14610272575b600080fd5b3480156101ad57600080fd5b506101c16101bc366004611585565b6104be565b60405190151581526020015b60405180910390f35b3480156101e257600080fd5b506101eb610510565b6040516101cd91906115ef565b34801561020457600080fd5b50610218610213366004611602565b6105a2565b6040516001600160a01b0390911681526020016101cd565b34801561023c57600080fd5b5061025061024b366004611632565b61063c565b005b34801561025e57600080fd5b5061025061026d36600461165c565b610751565b34801561027e57600080fd5b5061025061028d36600461165c565b6107ac565b34801561029e57600080fd5b506101eb6107c7565b3480156102b357600080fd5b506102186102c2366004611602565b6107d6565b3480156102d357600080fd5b506102506102e2366004611724565b61084d565b3480156102f357600080fd5b5061030761030236600461176d565b6108be565b6040519081526020016101cd565b34801561032157600080fd5b50610250610945565b34801561033657600080fd5b50610250610345366004611602565b61097b565b34801561035657600080fd5b50610307610a15565b34801561036b57600080fd5b506007546103079081565b34801561038257600080fd5b506006546001600160a01b0316610218565b3480156103a057600080fd5b506101eb610ac7565b3480156103b557600080fd5b50610307610ad6565b610250610b67565b3480156103d257600080fd5b506102506103e1366004611788565b610b9f565b3480156103f257600080fd5b50610307610bae565b34801561040757600080fd5b506009546103079081565b34801561041e57600080fd5b5061025061042d3660046117c4565b610c0f565b34801561043e57600080fd5b506101eb61044d366004611602565b610c71565b34801561045e57600080fd5b506008546103079081565b34801561047557600080fd5b506101eb610d6a565b34801561048a57600080fd5b506101c1610499366004611840565b610d8a565b3480156104aa57600080fd5b506102506104b936600461176d565b610db8565b60006001600160e01b031982166380ac58cd60e01b14806104ef57506001600160e01b03198216635b5e139f60e01b145b8061050a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461051f90611873565b80601f016020809104026020016040519081016040528092919081815260200182805461054b90611873565b80156105985780601f1061056d57610100808354040283529160200191610598565b820191906000526020600020905b81548152906001019060200180831161057b57829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166106205760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610647826107d6565b9050806001600160a01b0316836001600160a01b0316036106b45760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610617565b336001600160a01b03821614806106d057506106d08133610d8a565b6107425760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610617565b61074c8383610e5d565b505050565b6006546001600160a01b0316331461077b5760405162461bcd60e51b8152600401610617906118ad565b6107853382610ecb565b6107a15760405162461bcd60e51b8152600401610617906118e2565b61074c838383610fa2565b61074c83838360405180602001604052806000815250610c0f565b6060600a805461051f90611873565b6000818152600260205260408120546001600160a01b03168061050a5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610617565b6006546001600160a01b031633146108775760405162461bcd60e51b8152600401610617906118ad565b600a6108838282611981565b507fd6666840ba3b0939cf78131cb173315c425a3385a30b8921494500ca2b49f34a816040516108b391906115ef565b60405180910390a150565b60006001600160a01b0382166109295760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610617565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b0316331461096f5760405162461bcd60e51b8152600401610617906118ad565b610979600061113e565b565b6006546001600160a01b031633146109a55760405162461bcd60e51b8152600401610617906118ad565b6000818152600260205260409020546001600160a01b0316610a095760405162461bcd60e51b815260206004820152601760248201527f6275726e3a206e6f6e6578697374656e7420746f6b656e0000000000000000006044820152606401610617565b610a1281611190565b50565b6006546000906001600160a01b03163314610a425760405162461bcd60e51b8152600401610617906118ad565b612710610a4e60085490565b610a589190611a57565b9050610a676127106002611a6a565b8110610aac5760405162461bcd60e51b8152602060048201526014602482015273121a5d081d5c1c195c881b5a5b9d081b1a5b5a5d60621b6044820152606401610617565b610ab6338261122b565b610ac4600880546001019055565b90565b60606001805461051f90611873565b6006546000906001600160a01b03163314610b035760405162461bcd60e51b8152600401610617906118ad565b506007546127108110610b4f5760405162461bcd60e51b8152602060048201526014602482015273121a5d081d5c1c195c881b5a5b9d081b1a5b5a5d60621b6044820152606401610617565b610b59338261122b565b610ac4600780546001019055565b6006546001600160a01b03163314610b915760405162461bcd60e51b8152600401610617906118ad565b6006546001600160a01b0316ff5b610baa33838361136d565b5050565b6006546000906001600160a01b03163314610bdb5760405162461bcd60e51b8152600401610617906118ad565b610be86127106002611a6a565b600954610bf59190611a57565b9050610c01338261122b565b610ac4600980546001019055565b6006546001600160a01b03163314610c395760405162461bcd60e51b8152600401610617906118ad565b610c433383610ecb565b610c5f5760405162461bcd60e51b8152600401610617906118e2565b610c6b8484848461143b565b50505050565b6000818152600260205260409020546060906001600160a01b0316610cea5760405162461bcd60e51b815260206004820152602960248201527f746f6b656e5552493a2055524920717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610617565b612710821015610d1357604051806060016040528060358152602001611b496035913992915050565b610d206127106002611a6a565b821015610d4657604051806060016040528060358152602001611b7e6035913992915050565b604051806060016040528060358152602001611bb36035913992915050565b919050565b6060604051806060016040528060358152602001611be860359139905090565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6006546001600160a01b03163314610de25760405162461bcd60e51b8152600401610617906118ad565b6001600160a01b038116610e475760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610617565b610a128161113e565b80546001019055565b5490565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610e92826107d6565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b0316610f445760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610617565b6000610f4f836107d6565b9050806001600160a01b0316846001600160a01b03161480610f765750610f768185610d8a565b80610f9a5750836001600160a01b0316610f8f846105a2565b6001600160a01b0316145b949350505050565b826001600160a01b0316610fb5826107d6565b6001600160a01b0316146110195760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610617565b6001600160a01b03821661107b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610617565b611086600082610e5d565b6001600160a01b03831660009081526003602052604081208054600192906110af908490611a89565b90915550506001600160a01b03821660009081526003602052604081208054600192906110dd908490611a57565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061119b826107d6565b90506111a8600083610e5d565b6001600160a01b03811660009081526003602052604081208054600192906111d1908490611a89565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b0382166112815760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610617565b6000818152600260205260409020546001600160a01b0316156112e65760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610617565b6001600160a01b038216600090815260036020526040812080546001929061130f908490611a57565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b816001600160a01b0316836001600160a01b0316036113ce5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610617565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611446848484610fa2565b6114528484848461146e565b610c6b5760405162461bcd60e51b815260040161061790611a9c565b60006001600160a01b0384163b1561156457604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906114b2903390899088908890600401611aee565b6020604051808303816000875af19250505080156114ed575060408051601f3d908101601f191682019092526114ea91810190611b2b565b60015b61154a573d80801561151b576040519150601f19603f3d011682016040523d82523d6000602084013e611520565b606091505b5080516000036115425760405162461bcd60e51b815260040161061790611a9c565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610f9a565b506001949350505050565b6001600160e01b031981168114610a1257600080fd5b60006020828403121561159757600080fd5b81356115a28161156f565b9392505050565b6000815180845260005b818110156115cf576020818501810151868301820152016115b3565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006115a260208301846115a9565b60006020828403121561161457600080fd5b5035919050565b80356001600160a01b0381168114610d6557600080fd5b6000806040838503121561164557600080fd5b61164e8361161b565b946020939093013593505050565b60008060006060848603121561167157600080fd5b61167a8461161b565b92506116886020850161161b565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156116c9576116c9611698565b604051601f8501601f19908116603f011681019082821181831017156116f1576116f1611698565b8160405280935085815286868601111561170a57600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121561173657600080fd5b813567ffffffffffffffff81111561174d57600080fd5b8201601f8101841361175e57600080fd5b610f9a848235602084016116ae565b60006020828403121561177f57600080fd5b6115a28261161b565b6000806040838503121561179b57600080fd5b6117a48361161b565b9150602083013580151581146117b957600080fd5b809150509250929050565b600080600080608085870312156117da57600080fd5b6117e38561161b565b93506117f16020860161161b565b925060408501359150606085013567ffffffffffffffff81111561181457600080fd5b8501601f8101871361182557600080fd5b611834878235602084016116ae565b91505092959194509250565b6000806040838503121561185357600080fd5b61185c8361161b565b915061186a6020840161161b565b90509250929050565b600181811c9082168061188757607f821691505b6020821081036118a757634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b601f82111561074c57600081815260208120601f850160051c8101602086101561195a5750805b601f850160051c820191505b8181101561197957828155600101611966565b505050505050565b815167ffffffffffffffff81111561199b5761199b611698565b6119af816119a98454611873565b84611933565b602080601f8311600181146119e457600084156119cc5750858301515b600019600386901b1c1916600185901b178555611979565b600085815260208120601f198616915b82811015611a13578886015182559484019460019091019084016119f4565b5085821015611a315787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b8082018082111561050a5761050a611a41565b6000816000190483118215151615611a8457611a84611a41565b500290565b8181038181111561050a5761050a611a41565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611b21908301846115a9565b9695505050505050565b600060208284031215611b3d57600080fd5b81516115a28161156f56fe697066733a2f2f516d57393438614e34546a6834654c6b41416f386f733141634d32464a6a413436717461456646416e794e597a59697066733a2f2f516d523331663241556f6b433551794c587a4459556a7935745669626b6a625734766f56754d425a66724e565538697066733a2f2f516d646153546146365758705957694c35636b3763736d5479354557487a595647796b4a5a4e3754523935645353697066733a2f2f516d5567644c7650766a754847664d73754b3148326a467067357231514e63384a655779587952774b5038705466a2646970667358221220e2ef3122a6cb2d5c73f6e9c50a0261a53c008746506d8db79d5ea5e188d01d8a64736f6c63430008100033697066733a2f2f516d58584c464265536a5841774168626f31333434774a536a4c676f557266554b394c4535376f56756261525270"; +} diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index 1d2f97d546..06e887ca97 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -14,6 +14,7 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.alphawallet.app.assertions.Should.shouldNotSee; import static com.alphawallet.app.assertions.Should.shouldSee; +import static com.alphawallet.app.util.EthUtils.GANACHE_URL; import static com.alphawallet.app.util.Helper.click; import static com.alphawallet.app.util.Helper.waitUntil; import static com.alphawallet.app.util.RootUtil.isDeviceRooted; @@ -150,6 +151,16 @@ public static void importWalletFromSettingsPage(String text) { closeSelectNetworkPage(); } + public static void importPKWalletFromFrontPage(String privateKey) { + click(withText("I already have a Wallet")); + click(withText("Private key")); + Helper.wait(1); + onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_private_key)))))).perform(replaceText(privateKey)); + Helper.wait(1); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis + click(withId(R.id.import_action_pk)); + Helper.wait(5); + } + public static void importKSWalletFromFrontPage(String keystore, String password) { click(withText("I already have a Wallet")); click(withText("Keystore")); @@ -192,12 +203,11 @@ public static void addNewNetwork(String name) selectMenu("Select Active Networks"); click(withId(R.id.action_add)); input(R.id.input_network_name, name); - String url = "http://10.0.2.2:8545"; - input(R.id.input_network_rpc_url, url); + input(R.id.input_network_rpc_url, GANACHE_URL); input(R.id.input_network_chain_id, "2"); input(R.id.input_network_symbol, "ETH"); - input(R.id.input_network_explorer_api, url); - input(R.id.input_network_block_explorer_url, url); + input(R.id.input_network_explorer_api, GANACHE_URL); + input(R.id.input_network_block_explorer_url, GANACHE_URL); onView(withId(R.id.network_input_scroll)).perform(ViewActions.swipeUp()); Helper.wait(1); click(withId(R.id.checkbox_testnet)); diff --git a/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java b/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java new file mode 100644 index 0000000000..246ddd9ac9 --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java @@ -0,0 +1,123 @@ +package com.alphawallet.app.util; + +import com.alphawallet.app.C; +import com.alphawallet.app.service.AWHttpService; + +import org.web3j.crypto.Credentials; +import org.web3j.crypto.Hash; +import org.web3j.crypto.Keys; +import org.web3j.crypto.RawTransaction; +import org.web3j.crypto.TransactionEncoder; +import org.web3j.protocol.Web3j; +import org.web3j.protocol.core.DefaultBlockParameterName; +import org.web3j.protocol.core.methods.response.EthGetTransactionCount; +import org.web3j.protocol.core.methods.response.EthSendTransaction; +import org.web3j.protocol.core.methods.response.TransactionReceipt; +import org.web3j.rlp.RlpEncoder; +import org.web3j.rlp.RlpList; +import org.web3j.rlp.RlpString; +import org.web3j.tx.Transfer; +import org.web3j.utils.Convert; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import okhttp3.OkHttpClient; + +/** + * Created by JB on 4/09/2022. + */ +public abstract class EthUtils +{ + public static final String GANACHE_URL = "http://10.0.2.2:8545"; + + public static Web3j buildWeb3j(String url) + { + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(C.CONNECT_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(C.READ_TIMEOUT, TimeUnit.SECONDS) + .writeTimeout(C.WRITE_TIMEOUT, TimeUnit.SECONDS) + .retryOnConnectionFailure(true) + .build(); + + AWHttpService svs = new AWHttpService(url, "", client, false); + return Web3j.build(svs); + } + + public static String calculateContractAddress(String account, long nonce){ + byte[] addressAsBytes = org.web3j.utils.Numeric.hexStringToByteArray(account); + byte[] calculatedAddressAsBytes = + Hash.sha3(RlpEncoder.encode( + new RlpList( + RlpString.create(addressAsBytes), + RlpString.create((nonce))))); + + calculatedAddressAsBytes = Arrays.copyOfRange(calculatedAddressAsBytes, + 12, calculatedAddressAsBytes.length); + return Keys.toChecksumAddress(org.web3j.utils.Numeric.toHexString(calculatedAddressAsBytes)); + } + + public static Single getLastTransactionNonce(Web3j web3j, String walletAddress) + { + return Single.fromCallable(() -> { + try + { + EthGetTransactionCount ethGetTransactionCount = web3j + .ethGetTransactionCount(walletAddress, DefaultBlockParameterName.PENDING) + .send(); + return ethGetTransactionCount.getTransactionCount(); + } + catch (Exception e) + { + return BigInteger.ZERO; + } + }); + } + + public static void transferFunds(Web3j web3j, Credentials credentials, String targetAddr, BigDecimal ethAmount) + { + try + { + TransactionReceipt transactionReceipt = Transfer.sendFunds( + web3j, credentials, targetAddr, + ethAmount, Convert.Unit.ETHER).send(); + + System.out.println("TX: " + transactionReceipt.getTransactionHash()); + } + catch (Exception e) + { + // + } + } + + public static long deployContract(Web3j web3j, Credentials credentials, String contractCode) + { + long nonceReturn = 0; + try + { + BigInteger nonce = getLastTransactionNonce(web3j, credentials.getAddress()).blockingGet(); + + RawTransaction rawTransaction = RawTransaction.createContractTransaction(nonce, + BigInteger.valueOf(20000000000L), BigInteger.valueOf(6721975), BigInteger.ZERO, + contractCode); + + byte[] signedDeployTransaction = TransactionEncoder.signMessage(rawTransaction, credentials); + + EthSendTransaction raw = web3j + .ethSendRawTransaction(org.web3j.utils.Numeric.toHexString(signedDeployTransaction)).send(); + + System.out.println("Deploy hash: " + raw.getTransactionHash()); + + nonceReturn = nonce.longValue(); + } + catch (Exception e) + { + // + } + + return nonceReturn; + } +} From 4167380173c062a6baf13f89c939602fc5b20e6b Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 5 Sep 2022 13:29:24 +1000 Subject: [PATCH 089/183] Ensure transactions appear correctly for covalent chains --- app/src/main/java/com/alphawallet/app/entity/Transaction.java | 2 +- .../java/com/alphawallet/app/widget/ActivityHistoryList.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/Transaction.java b/app/src/main/java/com/alphawallet/app/entity/Transaction.java index 2108cf9119..91e54e05d6 100644 --- a/app/src/main/java/com/alphawallet/app/entity/Transaction.java +++ b/app/src/main/java/com/alphawallet/app/entity/Transaction.java @@ -165,7 +165,7 @@ public Transaction(CovalentTransaction cTx, long chainId, long transactionTime) else { to = cTx.to_address; - input = ""; + input = "0x"; } this.hash = cTx.tx_hash; diff --git a/app/src/main/java/com/alphawallet/app/widget/ActivityHistoryList.java b/app/src/main/java/com/alphawallet/app/widget/ActivityHistoryList.java index eaaca03c18..75d88c4547 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ActivityHistoryList.java +++ b/app/src/main/java/com/alphawallet/app/widget/ActivityHistoryList.java @@ -176,7 +176,9 @@ private RealmQuery getEthListener(long chainId, Wallet wallet, { return realm.where(RealmTransaction.class) .sort("timeStamp", Sort.DESCENDING) - .equalTo("input", "0x") + .beginGroup() + .equalTo("input", "0x").or().equalTo("input", "") + .endGroup() .beginGroup() .equalTo("to", wallet.address, Case.INSENSITIVE) .or() From 6168c0ba405275f5b2107fbd8d5537e6f06f4f4e Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 5 Sep 2022 13:32:27 +1000 Subject: [PATCH 090/183] Bump gradle for release --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d30edd4cfb..46ced40d1e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -85,8 +85,8 @@ android { } } defaultConfig { - versionCode 201 - versionName "3.58.2" + versionCode 202 + versionName "3.58.3" applicationId "io.stormbird.wallet" minSdkVersion 23 From 9fefbb8e891c5b16b8fb16c8922b0b7f15cb1426 Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 6 Sep 2022 13:24:20 +1000 Subject: [PATCH 091/183] Add Indonesian Translation (#2807) * Add Indonesian Translation * Update translation * Ellipsis --- app/src/main/res/values-fr/strings.xml | 5 - app/src/main/res/values-id/strings.xml | 963 +++++++++++++++++++++++++ 2 files changed, 963 insertions(+), 5 deletions(-) create mode 100644 app/src/main/res/values-id/strings.xml diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 4a6dfe9af4..7cc6446cd2 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -206,10 +206,6 @@ Qu\'est ce qu\'une Phrase Seed? Comment transférer de l\'ETH dans mon portefeuille? Qu\'est ce que TokenScript? - Politique de Confidentialité - Termes de Service - privacyPolicy.html - termsOfService.html tokenscript_explaination.html 24 heures Appréciation @@ -689,7 +685,6 @@ Approuvé Approbation accordé appel de TokenScript: - Testnet Aujourd\'hui Aller au Token Session WalletConnect Invalide diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml new file mode 100644 index 0000000000..020185a802 --- /dev/null +++ b/app/src/main/res/values-id/strings.xml @@ -0,0 +1,963 @@ + + + + Kirim + Send %1$s + Penerima + Bagian ini wajib diisi + Pengaturan + Dompet + Pastikan bahwa Anda memiliki cadangan dompet ini. + salin ke papan klip + kirim + Diterima + OK + Format barcode tidak berlaku: %s + Apakah Anda yakin ingin menghapus dompet? + + Kesalahan mengimpor kata kunci + Kesalahan menghapus dompet + Apakah Anda berhasil membuat cadangan? + Ya, lanjutkan + Tidak, ulangi + Transfer %s + Membeli %s + + Coba lagi + Sudah memiliki dompet? + Membuat dompet Baru + Telah terjadi kesalahan. + Tidak ditemukan token. + + + Alamat Saya + kirim + Konfirmasi + Rincian Transaksi + + + Kesalahan + Penanganan… + Tambahkan dompet + Bagaimana Anda ingin membeli? + + + dompet diimpor + Cadangan telah dibuat + Kode QR tidak berisi alamat yang berlaku + Pemindaian QR memerlukan Android 7.0 (API level 24) atau di atasnya. + + + Dari + Kepada + Batas Gas + Harga Gas + Harga (GWEI) Gas + Biaya Maksimum (GWEI) + Harga Gas Lama + Biaya Jaringan (Maksimum) + OK + + + Dari + Kepada + Biaya Gas + Harga Gas + Gas yang Digunakan + Biaya Jaringan + Transaksi # + Transaksi Hash # + Waktu Transaksi + Blok # + Blok + + + Bagikan + Lebih detail + Tambahkan dompet + Lihat di Blok Penjelajah + Coinbase + LokalEthereum + Changelly (Beli dengan kartu kredit) + + Detail transaksi + Tidak dapat membuat kode QR. + Alamat tidak valid + Jumlah yang tidak valid + Kesalahan transaksi + perangkat mengindikasikan transaksi mungkin gagal. Lanjutkan? + Gagal mengimpor token + harus berupa nilai angka. + Transaksi berhasil + N/A + Dompet tidak dipilih + Aktivitas akan muncul di sini + -- + -- + Mengirim… + Dapatkan alamat dari Kode QR + Semakin tinggi harga Gas, semakin mahal biaya transaksi Anda, tetapi semakin cepat transaksi Anda akan diproses oleh jaringan Ethereum. + Batas Gas mencegah smart contract menghabiskan semua Ethereum Anda. We will try to calculate the gas limit automatically for you, but some smart contracts may require a custom gas limit. + Lanjutan + + Tidak dapat menambahkan token. + Sudah ditambahkan + Gagal mengekspor dompet + Gagal memuat daftar token + Gagal membuat dompet + + AlphaWallet + Semua + Mata Uang + Pilihan Lanjutan + Salin Alamat Dompet + Ubah nama dompet ini + Nama + Lokasi + Tanggal + Harga + + Menukarkan + Menjual + Transfer + alamat + menukarkan + Tiket Ditukarkan + Gunakan Token + %1$s%2$s + + %1$s (%2$s) + Membuat Pesanan Penjualan + Pilih %1$s untuk menjual: + Pilih Tiket untuk Ditukarkan:show + Pembelian + Dompet + Pengaturan + Bantuan \u0026 TANYA JAWAB + Transaksi + Alamat Dompet Saya + Pemberitahuan + Menukarkan Tiket + Menunggu blockchain … + Mendaftar + Saring berdasarkan: + Tanggal + Harga + Jarak + Jangka waktu + Menetapkan Harga: + Pelajari lebih lanjut tentang Ethereum + Harga Per Tiket + Menetapkan harga dalam %1$s (%2$s) + Transfer Tiket + MagicLink akan berlaku sampai %1$s %2$s + Menghasilkan MagicLink + Transfer Sekarang + kepada + + + Paling Terbaru + Tertua + + + Rendah ke Tinggi + Tinggi ke Rendah + + + Apa saja + 1km + 5km + 10km + + + Apa saja + 1 minggu + 1 bulan + 1 tahun + + + Apa saja + 1–64 + + + Apa saja + VIP + + + Apa saja + 2 + 3 + + + HARI/BULAN/TAHUN + + ETH + Jumlah Tiket + Total Biaya: + Setara dalam USD + %1$s %2$s + Pilih Kuantitas of %1$s + Tiket Anda telah ditukarkan + Cari: + Kelas + Nomor. Kursi Bersama + Cocok + Apa itu ETH/Ethereum? + Mengapa aWallet menggunakan Ethereum? + Bagaimana cara mendapatkan uang saya? + Apa yang dimaksud dengan Seed Phrase? + Bagaimana cara mentransfer ETH ke dompet saya? + Apa itu TokenScript? + tokenscript_penjelasan.html + 24 jam + Penghargaan + %1$s/Tiket + Ethereum + Blockchain Ethereum + Penerbit: + KEAMANAN PERANGKAT TERGANGGU + Ponsel Anda di-root tetapi kuncinya masih dilindungi oleh enkripsi enklave Android. Vektor serangan akan berasal dari aplikasi papan ketik atau tampilan papan klip yang mempelajari kunci Anda ketika Anda memasukkannya. AlphaWallet melakukan yang terbaik untuk mengurangi risiko ini dengan mematikan saran otomatis papan ketik. Jika Anda menjalankan root, merekomendasikan Anda hanya menggunakan aplikasi papan ketik arus utama, rjalankan aplikasi anti-virus berkualitas baik dan gunakan pengelola root sumber terbuka yang terpercaya seperti Magisk atau SuperSU untuk membatasi akses ke hak akses root. Pada akhirnya, keselamatan kunci adalah tanggung jawab Anda. + Masih membutuhkan bantuan? Hubungi kami + Konfirmasi Penjualan? + Batalkan dan Kembali + Maksimum + Minimum + $0.00 + Konfirmasi Pembelian + Rincian Tiket Transfer + Tiket Transfer + Pilih Tiket untuk Transfer: + Buka Daftar Saya + Tiket Anda telah disiapkan untuk dijual di Tempat pemasaran + Perdagangan tidak diproses + OK + Dompet + Transaksi + Browser + Pengaturan + Aktivitas + Mengimpor Token + tiket + Tiket + Gagal + Total biaya untuk %1$d %2$s: + Impor Tiket + Batalkan + Konfirmasi Pembelian + Tautan Impor Tidak Valid + Tautan impor mengandung kesalahan; harap minta ulang tautan tersebut + DEPRESIASI + Buat tautan transfer gratis? + Bagikan MagicLink + Hasilkan MagicLink + Daftar di tempat pemasaran + --:-- + MagicLink Waktu Kadaluwarsa + Silakan pilih waktu kadaluwarsa + Silakan pilih tanggal kadaluwarsa + Pemasukan harus lebih besar dari 0 + MagicLink Tanggal Kadaluarsa + Total + Konfirmasi Rincian Transfer + Pengaturan Lanjutan + Konfirmasi + Pindai kode QR atau salin teks di bawah ini: + Alamat Dompet Saya + Disalin ke papan klip + MagicLink kedaluwarsa pada: + jumlah: %s + Set MagicLink Expiry: + %1$s %2$s Terpilih + %1$s %2$s/Tiket + MagicLink akan dibuat untuk memungkinkan pembeli membeli tiket Anda. + HARI/BULAN/TAHUN + Sebelum tautan berakhir, siapa pun yang memiliki MagicLink dapat membeli tiket Anda dengan satu klik. + Penting + 0.00 ETH + Ubah Dompet + Facebook + Twitter + ERC 20 + ERC 875 + ERC 875* + Ethereum adalah sistem yang terbuka, secara umum, platform komputasi terdistribusi berbasis blockchain dan sistem operasi yang menampilkan fungsionalitas Smart Contract (scripting). Ini adalah infrastruktur untuk produk dan layanan blockchain.\n\nETH/Ether adalah mata uang kripto yang blockchain-nya dihasilkan oleh platform Ethereum. Ether dapat ditransfer antar akun dan digunakan untuk mengkompensasi node penambangan peserta untuk perhitungan yang dilakukan. Ethereum menyediakan mesin virtual lengkap yang terdesentralisasi, Mesin Virtual Ethereum (EVM), yang dapat mengeksekusi skrip menggunakan jaringan internasional node publik. "Gas", mekanisme penetapan harga transaksi internal, digunakan untuk mengurangi spam dan mengalokasikan sumber daya pada jaringan. + Saat ini, Ethereum adalah blockchain terbaik dan terbesar untuk mengembangkan aplikasi dan layanan Smart Contract. AlphaWallet dimulai dengan mendukung blockchain Ethereum dan membantu meningkatkan teknologinya. + Anda dapat mengubah Ethereum menjadi uang fiat dan mentransfernya ke rekening bank Anda melalui bursa mata uang kripto apa pun. + Anda bisa memberikan alamat dompet Anda kepada pengirim. Mereka dapat mentransfer ETH kepada Anda melalui alamat dompet Anda. + Tiket Berlaku untuk Impor + Tiket sudah diimpor + Tiket diimpor sebagian + Impor Gratis + Pilih %1$s Kuantitas: + Pilih Metode Transfer: + Tetapkan MagicLink Masa Berlaku: + Masukan Alamat Transfer : + Impor Dompet + Impor + Kata sandi + Masukkan Kata Sandi + Masukkan kata kunci JSON + Seed + Kata Kunci + Kata kunci pribadi + Simbol + Bilangan desimal + Tambahkan Token Khusus + Kata Kunci pribadi harus sepanjang 64 karakter + 15 + 160 + Pendeteksi QR + Pilih Bahasa: + Ubah Bahasa + Tebus + Menerima dari + Transfer + Transfer Dari + Memuat Tiket Baru + Terima dari Magiclink Gratis + Transfer Magiclink + Mengakhiri Kontrak + Kontraktor + Operasi Tidak Berlaku + Administrasi Penukaran + Terima dari Magiclink + Transfer Magiclink + Dijual melalui Magiclink + Pembelian Magiclink + Mint + Bakar + Selanjutnya + Simpan + Info Kontrak + Alamat Kontrak + Alamat Ethereum atau nama ENS + Nama ENS + Nama ENS Anda + Magiclink Kedaluwarsa + Token Tidak Berlaku + Tidak ada kontrak yang berlaku di alamat ini pada jaringan ini. Kontrak bisa saja sudah diputuskan atau mungkin berada di jaringan yang berbeda. Coba ubah ke \'Ropsten (Uji)\'. + Pembaruan Tersedia + Pembaruan versi tersedia di situs web AlphaWallet. + Unduh dan Pasang + Nanti + Pembaruan Alphawallet + Tidak dapat memperbarui Aplikasi + Izin tulis penyimpanan tidak diberikan. + Lewati hingga rilis berikutnya + Aktifkan Pengesampingan XML + Aktifkan XML akan membuat direktori \'AlphaWallet\' di penyimpanan ponsel Anda. File konfigurasi Token (XML) dapat dimasukkan ke dalam direktori ini yang akan mengesampingkan konfigurasi Token default atau jaringan. + Apakah Anda ingin mengaktifkan Token konfigurasi direktori? + Perjanjian + Perambah DApp + Pesan + Alamat + Pemohon + Tandai Pesan + Tandai Pesan Pribadi + Tandai pesan yang diketik + Tolak + Disetujui + Nilai Transaksi + Tanda Transaksi + Lihat Penanda + ERC721 + Tertunda + Data Tidak Lengkap + Rincian Token + Atribut + Atribut-atribut + Buka pada %1$s + Memuat ulang + Impor Gratis (dengan biaya gas) + Konfirmasi transaksi DApp" + Alamat yang Diselesaikan + Konfirmasi Transfer Token + Memeriksa nama blockchain + Alokasikan ke + Menyetujui + Memeriksa layanan bebas Gas + ERC20 Detail + kirim + Tersedia + Dollar America + Transaksi Terkini + Anda belum memiliki transaksi + Tempel + Ketika Anda mengirim atau menerima %1$s,\n transaksi Anda akan muncul di sini + ether + token + Transaksi Tidak Berlaku + Transaksi DApp tidak berisi data + Tidak mencukupi %1$s + Sertifikat SSL Tidak Berlaku. Situs ini mungkin tidak aman. Lanjutkan? + Impor Token + Ambil Penurunan Mata Uang + Impor Mata Uang + Anda akan menerima + + Pindai Kode QR + Hasil Pemindaian Tidak valid + Alamat Ethereum + Baru saja memindai alamat Ethereum. Apakah Anda ingin mencoba mengunggah ini sebagai Token? + Ungu Token + %1$s Blockchain + 0.00 %s + Telegram (Layanan Pelanggan) + Permintaan transfer + Permintaan transfer token: %1$s + Membuat Permintaan Pembayaran + Masukkan jumlah yang diminta: + Layanan Feemaster saat ini tidak tersedia, silakan coba lagi nanti. + Mengimpor Token + Nama Dompet + Dompet %1$d + Token Tidak Ditemukan + Tidak ada kontrak Token yang ditemukan di alamat ini pada Ethereum Chain yang aktif. + Selamat datang di web yang terdesentralisasi + Hapus + Hapus DApp + Hapus %1$s dari DApps Saya? + Hapus Riwayat + Hapus + Apakah Anda yakin telah menghapus riwayat perambah (browser) Anda? + Riwayat perambah (browser) Anda muncul di sini. + Riwayat Perambah (browser) + Anda belum memiliki DApps yang ditampilkan.\n Mulai dengan menjelajahi perambah (browser). + DApps saya + Tambahkan + Edit + Riwayat + Temukan DApps + Tambahkan + Tambahkan ke DApps Saya + Edit DApp + Judul + Alamat + Cari atau ketik alamat situs jaringan + Jaringan + Pilih Jaringan Aktif + Barang Koleksi + Fungsi Token + Saluran pemberitahuan Alphawallet + Izin untuk menggunakan kamera ditolak. + Konfirmasi Transaksi TokenScript + Kirim %1$s %2$s to %3$s (%4$s) + Dana saat ini: %1$s %2$s + %1$s bukan alamat ethereum yang berlaku + Jaringan Aktif + Melakukan pemindaian untuk Token + Pemilihan Token + Fungsi ini memerlukan token %1$s + %1$s Token + Transaksi tidak memiliki penerima + Transaksi DApp tidak mengandung nilai. + Dompet Anda tidak memiliki cadangan! + Anda belum membuat cadangan dompet Anda. Anda memiliki $200 USD. Lakukan sekarang. + BACK UP DOMPET %1$s → + AOtentikasi Dibatalkan + Otentikasi Gagal + Cadangkan dompet Anda dengan seed phrase + Membuat cadangan sangat sederhana dan aman: cukup tuliskan 12 kata dan simpan di tempat rahasia, tanpa koneksi internet. + Cadangkan dompet saya + Tuliskan seed phrase\di atas kertas + OK, Saya akan mencatat ini + Verifikasi Seed Phrase + Lanjutkan + phrase pemulihan tidak valid. Mohon periksa dan coba lagi. + Mengelola Dompet + Tunjukkan Seed Phrase + Dompet ini hilang + Jika Anda kehilangan akses ke perangkat ini, dana Anda akan hilang, kecuali jika Anda mencadangkannya! + Hati-hati saat menghapus dompet Anda. Jika Anda belum mencadangkan dompet Anda, Anda mungkin kehilangan semua dana Anda. + Ekspor JSON Penyimpanan Kunci + Apa itu Penyimpanan Kunci JSON? + Penyimpanan Kunci adalah berkas teks. Anda bisa menyalin kontennya dan menempatkannya ketika Anda ingin mengimpor dompet Anda. + Uji seed phrase saya + Membuat cadangan sangat sederhana dan aman, cukup tuliskan kata %1$s dan simpan di tempat yang aman, tanpa koneksi internet. + Penyimpanan Kunci adalah berkas teks. Anda bisa menyalin kontennya dan menempatkannya ketika Anda ingin mengimpor dompet Anda. Ini adalah cara yang aman untuk mencadangkan dompet. + Atur Kata Sandi Penyimpanan Kunci + CATATAN: Anda harus mengingat kata sandi Anda. Kami tidak menyimpan kata sandi Anda di tempat lain. pemyimpanan kunci selalu dienkripsi, Jika tidak, siapa pun yang memilikinya bisa mendapatkan uangnya. + Simpan Penyimpanan Kunci + Jangan bagikan cadangan Anda. Anggota tim AlphaWallet tidak akan memintanya. + Masukkan seed phrase + Jika seed phrase Anda tidak dalam bahasa Inggris, feel free to convert it to English yourself using tools like these https://iancoleman.io/bip39/ + Phrase pemulihan yang tidak valid. Mohon periksa dan coba lagi. + IMPOR DARI ICLOUD/DROPBOX/GOOGLE DRIVE + Masukkan kunci pribadi + CATATAN: Anda harus mengingat kata sandi Anda. Kami tidak menyimpan kata sandi Anda di tempat lain. KeyStore is always encrypted, Jika tidak, siapa pun yang memilikinya bisa mendapatkan uangnya. + Pkunci pribadi hanya berupa hex: gunakan a-f A-F dan 0-9 + Tidak ada yang perlu dibagikan + Jelajahi DApp untuk membagikannya. + Saatnya membuat cadangan Dompet Anda + Kami sangat menyarankan untuk membuat cadangan dompet Anda setiap bulan. + Gunakan Pin + Sentuh sensor sidik jari + Buka Kunci Pribadi + Perangkat Tidak Aman + Perangkat Anda tidak terkunci oleh Sidik Jari, PIN atau Biometrik lainnya. Tidak dapat membuat kunci pribadi yang aman sampai perangkat memiliki perlindungan. + Ingatkan saya nanti + Ubah Dompet + Dompet Warisan + Pencadangan ditunda. + Kesalahan Kunci + Kata sandi 6 karakter atau lebih + Membuat Dompet baru + Perhatikan + Saya sudah memiliki dompet: + Perhatikan-Dompet saja + Masukkan Alamat Ethereum + Alamat Ethereum: 0x kemudian 40 karakter 0-9 a-f A-F + Perhatikan Dompet + Menerima Pembayaran + Cadangkan Dompet Anda + Dana Anda akan berisiko jika Anda tidak membuat cadangan sebelum menggunakan dompet Anda. + Tutup + Cadangkan Dompet ini + Tidak Terkunci + Cadangkan sekarang! + Jangan bagikan kunci Anda + Kunci Seed Phrase Anda untuk meningkatkan keamanan + Keamanan AlphaWallet sedang ditingkatkan menjadi yang terbaik yang dapat dicapai. Kunci frasa benih Anda dengan biometrik. + Tingkatkan keamanan kunci + Kami sangat menyarankan Anda membuat cadangan dompet Anda. + Lewati Pembaruan + Penyimpanan Kunci Anda untuk meningkatkan keamanan + Penyimpanan kunci JSON Tidak Valid + Kunci pribadi tidak berlaku + Dompet %1$s sudah tersedia, apakah Anda ingin mengimpor kembali dompet? + Mengimpor kembali Dompet? + Menyediakan pengesahan untuk membuat kunci + Kesalahan Impor, Coba impor ulang lagi. + Dompet %1$s sudah diimpor dengan kunci + Selamat datang di AlphaWallet + Kunci Seed Phrase + Tidak ada Kunci yang ditemukan + Transaksi Tertunda … + Skrip Lokal Tidak Diaktifkan + To use local TokenScripts you need to enable TokenScript override. Go to Settings, then click \'Enable TokenScript Override\'. + Terlalu banyak sidik jari yang gagal. Gunakan PIN atau tunggu 30 detik + Tidak ada sidik jari Terdaftar. Gunakan PIN + Tidak dapat memproses sidik jari. Gunakan PIN + Menerima + Kesalahan pada Elemen TokenScript + Kesalahan dalam elemen TokenScript: %1$s + masukan fungsi \'%1$s\' tidak ditemukan dalam elemen HTML. + Nilai yang dimasukkan tidak berlaku: %1$s + Nilai + LinkedIn + Tidak dapat membuat kunci. Coba aktifkan keamanan pada ponsel Anda. + Sebuah Seed Phrase, seed pemulihan phrase atau seed phrase cadangan adalah daftar kata yang menyimpan semua informasi yang diperlukan untuk memulihkan dompet kripto. Perangkat lunak dompet biasanya akan menghasilkan seed phrase dan menginstruksikan pengguna untuk menuliskannya di atas kertas. + Transaksi Terlalu Besar + Jumlah transaksi terlalu besar + Tampilkan Kontrak Token + Rincian tanda tangan + Salin Alamat Kontrak + Diri sendiri + ERC721T + Gagal menandatangani pertukaran pesan + Tipe Token + Reddit + Kecocokan TokenScript + Versi + TokenScript debug + tidak terpercaya + Tunjukkan Kode QR ke Gerai Penukaran: + Kelola Token + Terapkan Filter + Tidak Menampilkan Token Kosong + Saldo token untuk token ini kosong dan tidak akan ditampilkan kecuali Anda mengaktifkan saldo token kosong. Lanjutkan? + Nyalakan + Dompet tidak dapat membaca kunci terenkripsi; diperlukan impor ulang. + Otentikasi untuk membuka kunci tidak disediakan atau waktunya habis. Silakan coba lagi. + Sejak kunci ini dibuat, keamanan perangkat seluler telah berubah dan OS telah membatalkan kunci tersebut. Silakan masukkan kembali kunci Anda. + Pengesahan sidik jari gagal + BATALKAN + tersembunyi + Konfirmasi + Kode QR meminta Chain yang berbeda. Lanjutkan? + Permintaan Perubahan Chain + Transaksi Saldo Nol + Pengesahan + Favorit + Bantuan + Sistem + + + Tampilkan Alamat Dompet Saya + Ubah / Tambahkan Dompet + Buat cadangan dompet ini + Pemberitahuan + Kode sandi / ID Sentuh + Tingkat lanjut + Bantuan + Blog + TANYA JAWAB + Console + Hapus Perambah Cache + Muat Ulang Data Token + TokenScript + Ubah Bahasa + Tambahkan / Sembunyikan Token + Instagram + Ubah Mata Uang + Pilih Mata Uang FIAT + Kesalahan pada berkas TokenScript + Browser cache dihapus + Data Token dihapus + Data token sedang dihapus … Mohon tunggu + Dompet Anda + Salin + Pembaruan Penting + Mulai Versi 3.0, AlphaWallet tidak mendukung perangkat yang berjalan di Android 6.0 dan di bawahnya. + Sembunyikan Pemberitahuan + %1$s tidak ditemukan + Pengelolaan TokenScript + Jaringan + + + Kecepatan (Gas) + Lambat + Cepat + Perkiraan Waktu Transaksi + 0 menit + Membuat Direktori AlphaWallet + Direktori AlphaWallet dibuat. Letakkan skrip ke dalam direktori ini untuk menggunakan skrip Anda. Perhatikan tokenscript.org untuk detail lebih lanjut tentang cara mudah membuat tampilan yang aman dan berguna untuk token Anda. + Sudah Menonton + ETerjadi kesalahan saat menandatangani transaksi. Silakan masukkan kembali kunci untuk dompet ini. + Halaman Tidak Masuk Daftar Putih + TokenScript mencoba mengarahkan ke halaman yang tidak masuk daftar putih %1$s. Jika Anda adalah pemilik situs ini, silakan kirimkan PR ke AlphaWallet repo untuk menambahkan halaman untuk daftar putih. + %1$s (%2$s) + Ketersediaan Fungsi + Parameter tidak valid saat melakukan Transaksi TokenScript . Silakan periksa masukan. + TokenScript diganti oleh%1$s%2$s\n\n + Token Asal:\n\n + %1$s -> %2$s\n\n + (Debug) + Konfirmasi Penghapusan File + Hapus berkas %1$s + Hapus + Perbaharui TokenScripts + Peningkatan kecepatan + Batalkan Transaksi + 1 hari + %s hari + 1 jam + %s jam + 1 menit + %s menit + 1 kedua + %s detik + Tidak diketahui + Transaksi Tertunda untuk %s + Mengajukan Transaksi pengganti dengan harga gas yang lebih tinggi. + Batalkan Transaksi dengan mengganti pending dengan nilai TX nol . + Kesalahan TokenScript : %1$s\n\n + Arahkan kamera Anda pada kode QR + Terang + Kode QR saya + Jelajahi + Perkiraan Gas + Perkiraan Biaya Jaringan + Transaksi sudah ditulis ke blockchain, tidak dapat mengirim ulang atau membatalkan. + Transaksi Sudah Tertulis + Peringatan Kegagalan Transaksi + Node memprediksi transaksi ini akan gagal: %1$s + Gambar yang dipilih tidak mengandung data apa pun. + Token Ditampilkan + Token Tersembunyi + Abaikan + Mencari Token… + Dompet Terhubung + Sesi Berakhir + Kirim Transaksi ETH + Ditolak oleh pengguna + Putuskan Sesi Sambungan + Autentikasi gagal + Transaksi ditolak (coba gunakan lebih banyak gas) + dari: %1$s + dari + %1$s %2$s + kepada: %1$s + disetujui untuk mentransfer token: %1$s + untuk dibelanjakan atas nama: %1$s + Kejadian yang tidak diketahui + Kirim + Diterima + Disetujui + Persetujuan diberikan + TokenScript Hubungi: + Testnet + Hari ini + beralih ke Token + Sesi WalletConnect Tidak Berlaku + Sesi WalletConnect sebelumnya tidak diakhiri dengan benar. Silakan kembali ke halaman web dan putuskan sambungan, kemudian memulai sesi baru. + Data QR WalletConnect tidak berlaku + Waktu untuk koneksi habis. Harap batalkan permintaan dari Dapp dan mulai sesi baru. + Nonce + Beban Pembayaran + Transaksi telah ditandatangani + %1$s + Hapus catatan sesi ini? + Sesi telah dihentikan. Beralih kembali ke Dapp dan memulai sesi WalletConnect baru. + Transaksi tidak terkirim + Token yang Populer + Tidak dapat memperoleh kunci Biometrik + Semua Dana + Alamat Penerima + Konfirmasi Transaksi + Saldo + Rata-rata + Pesat + Cepat + Lambat + Khusus + Terlalu Rendah + Biaya Tinggi + Pengaturan Dapp + (Baru: %1$s %2$s) + Atur Kecepatan + Harga Gas: %1$s + Biaya Maksimum + Biaya Prioritas + Biaya Dasar: %1$s + Biaya didasarkan pada beban jaringan blockchain Ethereum saat ini. Mereka tidak bergantung pada AlphaWallet. AlphaWallet menggunakan oracle langsung %1$s dan memperbarui harga gas setiap 15 detik. + Tetapkan Milik Anda Sendiri + Nonce (pilihan) + Menghitung Batas Gas + Alamat Dompet + Transaksi dalam Proses + Transaksi dikirim ke blockchain Ethereum. Mungkin perlu beberapa menit untuk dikonfirmasi oleh penambang. + Tampilkan Rincian Transaksi + Kirim %1$s %2$s to %3$s + Menerima %1$s %2$s dari %3$s + Anda telah menerima persetujuan untuk memindahkan %1$s %2$s dari %3$s + Menyetujui %2$s untuk memindahkan %1$s + Panggilan kontrak + Gas tidak mencukupi + Kami memperkirakan transaksi ini akan gagal karena dana tidak mencukupi. Apakah Anda ingin mencoba mengirim? + Kirim Eth + Tukar Token + Penarikan + Setoran + Harga gas ditetapkan di bawah kecepatan \'lambat\'.\n Transaksi Anda mungkin membutuhkan waktu lama untuk ditulis atau mungkin tidak pernah ditulis. + Biaya Gas Mungkin Terlalu Rendah + Anda telah menetapkan biaya gas yang sangat tinggi. Tolong pastikan ini bukan kesalahan. AlphaWallet menggunakan gasnow.org live dan memperbarui harga gas setiap 15 detik. + Peringatan Biaya Tinggi! + Saldo Anda memiliki dana yang tidak mencukupi untuk nilai transaksi ditambah biaya transaksi. + Konversi ke xDAI + Kripto + Beli %1$s + Layar Penuh + Pilih Jaringan Browser Dapp baru + Browser terputus dari %1$s, silakan pilih jaringan baru untuk Browser + Apakah Anda ingin memutuskan sambungan dari Jaringan %1$s? + Anda terhubung ke Jaringan %1$s di Browser tetapi Anda baru saja menonaktifkan Jaringan %1$s di Jaringan Aktif. Apakah Anda ingin terhubung ke Jaringan %1$s? + Putuskan hubungan + Tetap Terhubung + Waspadalah terhadap penipu! Jangan membagikan Seed Phrase. + AlphaWallet TIDAK AKAN PERNAH bertanya tentang Seed Phrase Anda (terutama di Telegram). + Seed Phrase Anda (jangan bagikan dengan siapa pun) + OK, Sembunyikan Seed Phrase + Nama ENS tidak cocok dengan alamat dompet + Izinkan + Tolak + %s ingin menggunakan kamera Anda + Jaringan Utama + Apa itu Testnet? + Mengerti, aktifkan Testnet + Token Testnets seperti uang \'Monopoli\'. Mereka tidak memiliki nilai finansial, tetapi digunakan oleh para pengembang untuk mencoba desain baru tanpa perlu mengeluarkan koin yang berharga.. + Terhubung ke Jaringan + Pilih Pilihan Jaringan + Pilih setidaknya satu jaringan. + Portofolio + Masukkan Target Harga + Atur Peringatan Baru + Simpan Peringatan + Peringatan akan muncul di sini + Token + Beli ETH + Setel ulang semua data token yang terlampir (misalnya saldo yang tercatat, dll). AlphaWallet akan memuat ulang status dompet Anda saat ini. Tidak mempengaruhi kunci atau aset. + + Tambahkan Jaringan RPC Khusus + Nama Jaringan + URL RPC + Identitas Chain + Simbol + URL Penelusur Transaksi + Tambahkan Jaringan + Atur ulang + URL tidak berlaku + + Perhatikan bahwa mempercepat transaksi ini tidak menjamin transaksi asli Anda akan dipercepat. Jika upaya Anda berhasil, Anda akan dikenakan biaya penambang seperti di atas. + Perhatikan bahwa transaksi ini tidak menjamin transaksi awal Anda akan dibatalkan. Jika upaya Anda berhasil, Anda akan dikenakan biaya penambang seperti di atas. + Agar transaksi ini berhasil, harga gas harus setidaknya 10% lebih tinggi dari harga gas semula. + Pengaturan Kecepatan + Batalkan Pengaturan + Pilih + %s Terpilih + Situs ini meminta Anda untuk beralih ke Chain %1$s dengan IDENTITAS Chain: %2$s. Ini akan memuat ulang halaman. + Peringatan: Beralih ke jaringan Utama + Peringatan: Beralih ke Uji jaringan + WalletConnect: Jaringan tidak mendukung. Tutup koneksi dan ubah Jaringan DappBrowser + %1$s Aset | %2$s + %1$s Aset | %2$s + Ini adalah Testnet + Tukar dengan Quickswap + Email + Discord + Beri Nama Dompet Ini + Masukkan Nama Dompet + Simpan Nama + Pilih Jumlah + Token yang Terpilih + Kirim Token + Jika Anda senang menggunakan %1$s, tolong bantu kami dengan memberi penilaian. + NANTI + TINGKAT + TIDAK, TERIMA KASIH + Tingkat %1$s + Terpasang: %1$s + Tersedia: %1$s + penjelajah API + Perbarui Jaringan + + Situs ini meminta Anda untuk mengaktifkan dan menambahkan Chain %1$s dengan IDENTITAS Chain: %2$s. Ini akan memuat ulang halaman + Tukar Permintaan Chain + Tambahkan Permintaan Chain + Tidak ada data grafik yang tersedia + %1$s (%2$s%%) Hari ini + Dompet + Rangkuman + Jaringan: %1$s + Tetapkan sebagai Halaman Utama + Jaringan + Tukar dengan 1 inci + Tukar + Kirim ke Alamat ini + Tetap mengikuti perkembangan terbaru + Kami mengirim email yang mengumumkan fitur-fitur utama. Apakah Anda ingin menerima email tersebut? (maksimal 1 email per minggu) + Alamat Email + Saya ingin menerima email seperti itu + Harap berikan alamat email yang berlaku + Github (Mengajukan permasalahan) + Chains untuk memindai + Lihat + Identitas Chain sudah digunakan + Status + Terhubung ke + Tidak Terhubung + Online + %1$s (%2$s) Hari ini + Kinerja + Cari token + Aset + DeFi + Tata Kelola Pemerintahan + Barang Koleksi + Apa yang baru? + Di bawah + Di atas + Tambahkan Peringatan Harga Baru + Harga Saat Ini: + Informasi + Aktivitas + Peringatan + Jaringan Tidak Diketahui + Dapp ini meminta untuk berubah ke Chain yang tidak diketahui: %1$s + + Tidak ada sesi Aktif + Hubungkan Dompet + Seed phrase hanya bisa berisi kata-kata + Token # + Tautan Eksternal + Penjelasan + Rincian + Mode Gelap + Kirim Beberapa Token + Beralih ke Tampilan Grid + Beralih ke Tampilan Daftar + Muat ulang Metadata + Harga Pasar: + Saya sudah memiliki Dompet + Pilih Mode + Info Jaringan + Situs web + Terang + Gelap + Otomatis + Unik + %1$s%% memiliki ciri ini + Gunakan 1559 Transaksi + Percobaan 1559 Transaksi + IDENTITAS Chain: %1d + Dibuat oleh + Standar Token + Jumlah Pasokan + Pemilik + Pemilik + Penjualan Terakhir + Tidak dapat meningkatkan kunci: Aktifkan kunci layar pada ponsel + Tidak dapat meningkatkan kunci: %1$s + Tidak ditemukan Kunci + Tidak dapat menyimpan kunci: %1$s + Peringatan Pencarian ENS + AlphaWallet telah mendeteksi perbedaan antara penanda waktu ethereum dan waktu perangkat Anda saat ini, atau mungkin koneksi blockchain tidak disinkronkan, harap periksa waktu mobile Anda sudah benar, atau abaikan peringatan ini. + 0 + Penurunan + Peningkatan + Transaksi telah habis waktunya. Anda bisa melihat status di halaman aktivitas. + Batas Waktu Transaksi + Slippage (adalah perbedaan harga yang dapat terjadi antara saat order trading berlalu dan eksekusi aktualnya) + Buka Pengaturan + Tidak ada koneksi yang ditemukan untuk Chain ini. + Biaya + Harga Terkini + Minimum Diterima + Saldo: + Status Node + Saldo %1$s tidak mencukupi + Pilih Token + Tidak ada hasil yang ditemukan + Konfirmasi Transaksi + Pengambilan Chains + Pengambilan koneksi + Pengambilan penawaran + Bantuan + Apa yang dimaksud dengan status Node? + Dengan Node Status, Anda dapat mengukur seberapa cepat node merespon transaksi + di bawah 1 detik + lebih dari 1 detik + tidak merespon + Mode Testnet + Di mana Token saya? + Jangan khawatir. Token Anda aman. Anda sedang melihat jaringan Testnet. Mereka digunakan oleh para pengembang untuk mencoba desain baru. Anda bisa beralih ke jaringan utama kapan saja. + Beralih ke Mainnet + Pilih Token + Khusus + Nama + Catatan + URL + Terhubung + Terhubung ke + Tanda tangan + Ini akan menginformasikan situs jarak jauh alamat dompet Anda adalah %s + Harga Dasar + Harga Rata-rata + Penyedia layanan + Hapus Kosong + Hapus Semua + Buy with Coinbase Pay + Buy with Ramp + Buy with Coinbase Pay + Key Status + Fix Key State + Run Key Diagnostic + Key Diagnostic + Key found + Unable to find Key + Seed Phrase detected public key: %1$s + Decoded Keystore public key: %1$s + Locked + Key type in Database + Key Entry in Secure Enclave + From 7be818c0d7c267a496cdf3e3cbf42ca82574d306 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 7 Sep 2022 07:23:04 +0800 Subject: [PATCH 092/183] Fix OOM (#2802) * Fix OOM * Increase e2e timeout * Improve integration test --- .github/workflows/e2e.yml | 2 +- .../alphawallet/app/TokenScriptCertificateTest.java | 13 ++++++++----- build.gradle | 7 +++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index d3ec0e5500..f8b281d7fb 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,7 +7,7 @@ on: jobs: test: runs-on: self-hosted - timeout-minutes: 8 + timeout-minutes: 15 strategy: matrix: api-level: [30] diff --git a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java index eafcbb4aad..6364c0efa1 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java @@ -40,13 +40,14 @@ /** * Created by JB on 1/09/2022. */ -public class TokenScriptCertificateTest extends BaseE2ETest { - +public class TokenScriptCertificateTest extends BaseE2ETest +{ private final String doorContractAddress; private final String contractOwnerPk = "0x69c22d654be7fe75e31fbe26cb56c93ec91144fab67cb71529c8081971635069"; private final Web3j web3j; - private static final Map WALLETS_ON_GANACHE = new HashMap() {{ + private static final Map WALLETS_ON_GANACHE = new HashMap() + {{ put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); put("32", new String[]{"0x992b442eaa34de3c6ba0b61c75b2e4e0241d865443e313c4fa6ab8ba488a6957", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); @@ -56,7 +57,9 @@ public TokenScriptCertificateTest() { int apiLevel = Build.VERSION.SDK_INT; String[] array = WALLETS_ON_GANACHE.get(String.valueOf(apiLevel)); - if (array == null) { + + if (array == null) + { fail("Please config seed phrase and wallet address for this API level first."); } @@ -81,7 +84,7 @@ public TokenScriptCertificateTest() } @Test - public void certificate_test() + public void should_view_signature_details() { int apiLevel = Build.VERSION.SDK_INT; String[] array = WALLETS_ON_GANACHE.get(String.valueOf(apiLevel)); diff --git a/build.gradle b/build.gradle index 8a3dd0c8a4..47a88def1d 100644 --- a/build.gradle +++ b/build.gradle @@ -40,6 +40,13 @@ allprojects { force 'com.google.firebase:firebase-analytics:16.5.0' } } + + tasks.withType(Test) { + maxParallelForks = 2 + forkEvery = 80 + maxHeapSize = "2048m" + minHeapSize = "1024m" + } } task clean(type: Delete) { From 46f6c966d3adbb69250bdc17597b978057be7240 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 7 Sep 2022 15:06:05 +0800 Subject: [PATCH 093/183] Revise i18n and enable Indonesia language & currency (#2813) * Match translations with translatable value * Mark untranslatable fields * Add i18n e2e test * Enable Indonesia language * Add Indonesia currency * Normalise Currency labels --- app/check/lint-baseline.xml | 253 ------------------ .../com/alphawallet/app/CurrencyTest.java | 31 +++ .../java/com/alphawallet/app/I18nTest.java | 45 ++++ .../java/com/alphawallet/app/steps/Steps.java | 38 ++- .../app/repository/CurrencyRepository.java | 9 +- .../app/repository/LocaleRepository.java | 3 +- .../main/res/drawable/ic_flags_indonesia.xml | 14 + app/src/main/res/values-es/strings.xml | 41 +-- app/src/main/res/values-fr/strings.xml | 40 +-- app/src/main/res/values-id/strings.xml | 40 +-- app/src/main/res/values-my/strings.xml | 53 +--- app/src/main/res/values-vi/strings.xml | 49 +--- app/src/main/res/values-zh/strings.xml | 41 +-- app/src/main/res/values/strings.xml | 80 +++--- 14 files changed, 207 insertions(+), 530 deletions(-) create mode 100644 app/src/androidTest/java/com/alphawallet/app/CurrencyTest.java create mode 100644 app/src/androidTest/java/com/alphawallet/app/I18nTest.java create mode 100644 app/src/main/res/drawable/ic_flags_indonesia.xml diff --git a/app/check/lint-baseline.xml b/app/check/lint-baseline.xml index ca22c68748..b099630d8b 100644 --- a/app/check/lint-baseline.xml +++ b/app/check/lint-baseline.xml @@ -2529,259 +2529,6 @@ column="42"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 5e5e9aeff2..e88be926e6 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -21,7 +21,6 @@ No, repetir Transferir %s Comprar %s - Inténtalo de nuevo ¿Ya tienes un monedero? Crear un monedero nuevo @@ -68,8 +67,6 @@ Más detalles Añadir monedero Ver en Block Explorer - Coinbase - LocalEthereum Changelly (compra con tarjeta de crédito) Detalle de la transacción @@ -84,8 +81,6 @@ N/A El monedero no está seleccionado Las actividades aparecerán aquí - -- - -- Enviando... Obtener dirección a partir del código QR Cuanto más alto sea el precio del gas, más cara será la tarifa de tu transacción, pero más rápido se procesará por la red Ethereum. @@ -97,7 +92,6 @@ Error al exportar el monedero Error al cargar la lista de tokens Error al crear un monedero - AlphaWallet Todo Monedas Opciones avanzadas @@ -115,9 +109,7 @@ Canjear Tickets canjeados Usar token - %1$s%2$s - %1$s (%2$s) Crear orden de venta Selecciona %1$s para vender: Selecciona los tickets para canjear: @@ -181,11 +173,9 @@ DD/MM/YY - ETH Cantidad de tickets Coste total: Equivalente en USD - %1s %2s Selecciona la cantidad de %1$s Tu ticket ha sido canjeado Buscar: @@ -198,7 +188,6 @@ ¿Qué es una frase semilla? ¿Cómo transfiero ETH a mi monedero? ¿Qué es TokenScript? - tokenscript_explaination.html 24 horas Valoración %1s/ticket @@ -241,7 +230,6 @@ Compartir MagicLink Generar MagicLink Anunciar en el mercado - --:-- Hora de expiración del MagicLink Selecciona una hora de expiración Selecciona una fecha de expiración @@ -265,11 +253,6 @@ Importante 0,00 ETH Cambiar monedero - Facebook - Twitter - ERC 20 - ERC 875 - ERC 875* Ethereum es una plataforma informática y un sistema operativo de código abierto, público, de distribución basada en las cadenas de bloques, con funcionalidad de contratos inteligentes (scripting). Es la infraestructura de los productos y servicios de cadena de bloques.\n\nEl ETH/Ether es una criptomoneda cuya cadena de bloques la genera la plataforma Ethereum. El Ether se puede transferir entre cuentas y se puede utilizar para compensar a los nodos mineros participantes por los cálculos realizados. Ethereum proporciona una máquina virtual de Turing completo descentralizada, la Ethereum Virtual Machine (EVM), que puede ejecutar scripts usando una red internacional de nodos públicos. El \"gas\", un mecanismo interno de fijación de precios para las transacciones, se emplea para mitigar el spam y asignar los recursos en la red. En la actualidad, Ethereum es la mayor y mejor cadena de bloques para el desarrollo de aplicaciones y servicios de contratos inteligentes. AlphaWallet comienza apoyando la cadena de bloques de Ethereum y ayuda a mejorar su tecnología. Puedes convertir el Ethereum en dinero fíat y transferirlo a tu cuenta bancaria a través de cualquier plataforma de intercambio de criptomonedas. @@ -384,14 +367,12 @@ Reclamar criptomoneda gratuita Importación de monedas recibirás - Escanear código QR Resultado del escaneo no válido Dirección de Ethereum Acabas de escanear una dirección de Ethereum. ¿Quieres probar a cargarla como un token? Cargar token Cadena de bloques de %1$s - 0,00 %s Telegrama (Atención al Cliente) Solicitud de transferencia Solicitud de transferencia de tokens: %1$s @@ -534,7 +515,6 @@ entrada de la función \"%1$s\" no encontrada en los elementos HTML. Valor de entrada no válido: %1$s Valor - LinkedIn No ha sido posible crear la clave. Prueba a activar la seguridad en tu teléfono. Una frase semilla, frase semilla de recuperación o frase semilla de respaldo es una lista de palabras que almacena toda la información necesaria para recuperar un monedero criptográfico. Normalmente, el software del monedero genera una frase semilla e indica al usuario que la escriba en un papel. Transacción demasiado grande @@ -543,10 +523,8 @@ Detalles de la firma Copiar la dirección del contrato Auto - ERC721T Error al firmar el mensaje de canje Tipo de token - Reddit Compatibilidad de TokenScript Versión Depuración de TokenScript @@ -584,10 +562,8 @@ Consola Borrar la caché del navegador Recargar datos del Token - TokenScript Cambiar idioma Añadir / Ocultar tokens - Instagram Cambiar moneda Seleccionar moneda FÍAT Error de archivo de TokenScript @@ -619,7 +595,6 @@ Parámetro no válido durante la llamada a la transacción de TokenScript. Revisa las entradas. TokenScript sustituido por %1$s%2$s\n\n Tokens de origen:\n\n - %1$s -> %2$s\n\n (Depuración) Confirmar la eliminación del archivo Eliminar el archivo %1$s @@ -655,7 +630,6 @@ Tokens ocultos Ignorar Buscar tokens... - WalletConnect Finalizar sesión Enviar transacción ETH Rechazada por el usuario @@ -664,7 +638,6 @@ Transacción rechazada (prueba a utilizar más gas) de: %1$s de - %1$s %2$s a: %1$s aprobado para transferir tokens: %1$s para gastar en nombre de: %1$s @@ -680,10 +653,8 @@ La sesión anterior de WalletConnect no finalizó correctamente. Regrese a la página web y desconéctese, luego inicie una nueva sesión. Datos QR de WalletConnect no válidos Connection attempt timed out. Please cancel the request from the Dapp and start a new session. - Nonce Datos Transacciones Firmadas - %1$s ¿Eliminar este registro de sesión? Session has been terminated. Switch back to Dapp and start a new WalletConnect session. Transaction not sent @@ -769,8 +740,6 @@ In order to speed up this transaction, the gas price must be at least 10% higher than the original gas price. Speed Up Setting Cancel Setting - Email - Discord Select %s Selected This site is requesting you to switch to the %1$s chain with chain ID: %2$s. This will reload the page. @@ -835,7 +804,6 @@ Performance Search token Assets - DeFi Gobernancia Coleccionables ¿Qué hay de nuevo? @@ -852,7 +820,6 @@ No Active sessions Connect Wallet La frase de semillas solo puede contener palabras - Token # External Link Description Details @@ -865,7 +832,6 @@ I already have a Wallet Select Mode Network Info - Testnet Website Light Dark @@ -889,7 +855,6 @@ Unable to store key: %1$s ENS Lookup Warning AlphaWallet has detected a discrepancy between ethereum\'s timestamp and your device\'s current time, or possibly the blockchain connection is not synchronized, please check your phone\'s time is correct, or ignore this warning. - 0 Disminuir Incrementar The transaction has timed out. You can view the status in activity page. @@ -922,7 +887,6 @@ Custom Name Note - URL Connect Connect to Sign @@ -946,4 +910,9 @@ Locked Key type in Database Key Entry in Secure Enclave + Isuficiente %1$s saldo + Transferencia segura + Política de privacidad + Términos de servicio + Billeteras conectadas diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 7cc6446cd2..54b93d97a5 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -22,7 +22,6 @@ Non, recommencer Transférer %s Acheter %s - Essayer encore Avez vous déja un portefeuille? Créer un nouveau portefeuille @@ -75,8 +74,6 @@ Plus de détails Ajouter portefeuille Voir sur Block Explorer - Coinbase - LocalEthereum Changelly (Acheter avec une carte de crédit) Détail de la Transaction Impossible de générer le code QR. @@ -90,8 +87,6 @@ N/A le portefeuille n\'est pas sélectionné Les activités apparaîtront ici - -- - -- Envoi en cours... Obtenir l\'adresse à partir du code QR Plus le prix du gaz est élevé, plus vos frais de transaction seront élevés, mais plus votre transaction sera traitée rapidement par le réseau Ethereum. @@ -104,7 +99,6 @@ Echec du chargement de la liste des tokens Impossible de créer un portefeuille - AlphaWallet Tous Devises Options avancées @@ -122,9 +116,7 @@ Racheter Tickets Rachetés Utiliser Token - %1$s%2$s - %1$s (%2$s) Créer un ordre de vente Selectionner %1$s à vendre: Selectionner les tickets à racheter:montrer @@ -189,11 +181,9 @@ DD/MM/YY - ETH Quantité de Tickets Coût total: Equivalent en USD - %1$s %2$s Selectionner Quantité of %1$s Votre ticket a été racheté Chercher: @@ -206,7 +196,6 @@ Qu\'est ce qu\'une Phrase Seed? Comment transférer de l\'ETH dans mon portefeuille? Qu\'est ce que TokenScript? - tokenscript_explaination.html 24 heures Appréciation %1$s/Ticket @@ -249,7 +238,6 @@ Partager le lien Magique Générer le lien Magique Lister sur la marketplace - --:-- Date d\'expiration du lien Magique Veuillez selectionner l\'heure d\'expiration Veuillez selectionner la date d\'expiration @@ -273,11 +261,6 @@ Important 0.00 ETH Changer de portefeuille - Facebook - Twitter - ERC 20 - ERC 875 - ERC 875* Ethereum est une plate-forme informatique distribuée et un système d\'exploitation open source, public et basé sur la blockchain, avec une fonctionnalité de contrat intelligent (script). C\'est l\'infrastructure des produits et services blockchain.\n\nETH/Ether est une crypto-monnaie dont la blockchain est générée par la plateforme Ethereum. L\'éther peut être transféré entre comptes et utilisé pour compenser les nœuds de minage des participants pour les calculs effectués. Ethereum fournit une machine virtuelle décentralisée complète de Turing, la machine virtuelle Ethereum (EVM), peut exécuter des scripts à l\'aide d\'un réseau international de nœuds publics. «Gas», un mécanisme interne de tarification des transactions, est utilisé pour atténuer le spam et allouer des ressources sur le réseau. Actuellement, Ethereum est la meilleure et la plus grande blockchain pour le développement d\'applications et de services de contrats intelligents. AlphaWallet supporte la blockchain Ethereum et aide à améliorer sa technologie. Vous pouvez convertir votre Ethereum en monnaie fiat et les tranférer sur votre compte bancaire avec n\'importe quel échange crypto. @@ -393,14 +376,12 @@ Accepter baisse de devises Importation Devises vous recevrez - Scannez le code QR Résultat du scan Invalide Adresse Ethereum Vous venez de scanner une adresse Ethereum. Voulez-vous essayer de la charger en tant que token? Chargement de token %1$s Blockchain - 0.00 %s Telegram (Support Client) Demande de transfert Demande de transfert de token: %1$s @@ -543,7 +524,6 @@ entrée de fonction \'%1$s\' introuvable dans les éléments HTML. Valeur d\'Entrée Invalide: %1$s Valeur - LinkedIn Impossible de créer la clé. Essayer d\'activer la sécurité de votre téléphone. Une phrase seed, une phrase de récupération seed ou une phrase seed de sauvegarde est une liste de mots qui stockent toutes les informations nécessaires pour récupérer un portefeuille cryptographique. Le logiciel de portefeuille génère généralement une phrase seed et demande à l\'utilisateur de l\'écrire sur papier. Transaction Trop Grande @@ -552,10 +532,8 @@ Détails Signature Copier l\'adresse du Contrat Soi - ERC721T Échec de la signature du message d\'échange Type de Token - Reddit Comptabilité TokenScript Version TokenScript debug @@ -594,10 +572,8 @@ Console Effacer le Cache du Navigateur Recharger les données du Tokens - TokenScript Changer Langue Ajouter / Cacher Tokens - Instagram Changer Devise Selectionner Devise FIAT TokenScript fichier erreur @@ -630,7 +606,6 @@ Paramètre non valide lors de l\'appel de TokenScript Transaction. Veuillez vérifier les entrées. TokenScript remplacé par %1$s%2$s\n\n Tokens d\'Origine:\n\n - %1$s -> %2$s\n\n (Debug) Confirmer la Suppression du Fichier Supprimer fichier %1$s @@ -666,7 +641,6 @@ Tokens Cachés Ignorer Chercher des Tokens... - WalletConnect Terminer Session Envoyer une Transaction ETH Rejeté par l\'utilisateur @@ -675,7 +649,6 @@ Transaction rejetée (essayer d\'utiliser plus de gas) de: %1$s de - %1$s %2$s à: %1$s Approuvé pour transférer des tokens: %1$s à dépenser au nom de: %1$s @@ -691,10 +664,8 @@ La session précédente de WalletConnect ne s\'est pas correctement terminée. Veuillez retourner à la page Web et vous déconnecter, puis démarrer une nouvelle session. Données QR WalletConnect Invalide Connection attempt timed out. Please cancel the request from the Dapp and start a new session. - Nonce Puissance Transactions Signés - %1$s Supprimer cet enregistrement de session? La session a été terminée. Revenez à Dapp et démarrez une nouvelle session WalletConnect. Transaction pas envoyée @@ -791,8 +762,6 @@ %1$s Assets | %2$s This is Testnet Swap with Quickswap - Email - Discord Name This Wallet Enter Wallet Name Save Name @@ -848,7 +817,6 @@ Performance Search token Assets - DeFi Gouvernance Collectibles Quoi de neuf? @@ -865,7 +833,6 @@ No Active sessions Connect Wallet La phrase de graine ne peut contenir que des mots - Token # External Link Description Details @@ -901,7 +868,6 @@ Unable to store key: %1$s ENS Lookup Warning AlphaWallet has detected a discrepancy between ethereum\'s timestamp and your device\'s current time, or possibly the blockchain connection is not synchronized, please check your phone\'s time is correct, or ignore this warning. - 0 Diminuer Augmenter The transaction has timed out. You can view the status in activity page. @@ -934,7 +900,6 @@ Custom Name Note - URL Connect Connect to Sign @@ -958,4 +923,9 @@ Locked Key type in Database Key Entry in Secure Enclave + Solde de %1$s insuffisant + Transfert de sécurité + Politique de confidentialité + Conditions d\'utilisation + Portefeuilles connectés diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 020185a802..564d4680a3 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -22,7 +22,6 @@ Tidak, ulangi Transfer %s Membeli %s - Coba lagi Sudah memiliki dompet? Membuat dompet Baru @@ -76,8 +75,6 @@ Lebih detail Tambahkan dompet Lihat di Blok Penjelajah - Coinbase - LokalEthereum Changelly (Beli dengan kartu kredit) Detail transaksi @@ -92,8 +89,6 @@ N/A Dompet tidak dipilih Aktivitas akan muncul di sini - -- - -- Mengirim… Dapatkan alamat dari Kode QR Semakin tinggi harga Gas, semakin mahal biaya transaksi Anda, tetapi semakin cepat transaksi Anda akan diproses oleh jaringan Ethereum. @@ -106,7 +101,6 @@ Gagal memuat daftar token Gagal membuat dompet - AlphaWallet Semua Mata Uang Pilihan Lanjutan @@ -124,9 +118,7 @@ menukarkan Tiket Ditukarkan Gunakan Token - %1$s%2$s - %1$s (%2$s) Membuat Pesanan Penjualan Pilih %1$s untuk menjual: Pilih Tiket untuk Ditukarkan:show @@ -191,11 +183,9 @@ HARI/BULAN/TAHUN - ETH Jumlah Tiket Total Biaya: Setara dalam USD - %1$s %2$s Pilih Kuantitas of %1$s Tiket Anda telah ditukarkan Cari: @@ -208,7 +198,6 @@ Apa yang dimaksud dengan Seed Phrase? Bagaimana cara mentransfer ETH ke dompet saya? Apa itu TokenScript? - tokenscript_penjelasan.html 24 jam Penghargaan %1$s/Tiket @@ -251,7 +240,6 @@ Bagikan MagicLink Hasilkan MagicLink Daftar di tempat pemasaran - --:-- MagicLink Waktu Kadaluwarsa Silakan pilih waktu kadaluwarsa Silakan pilih tanggal kadaluwarsa @@ -275,11 +263,6 @@ Penting 0.00 ETH Ubah Dompet - Facebook - Twitter - ERC 20 - ERC 875 - ERC 875* Ethereum adalah sistem yang terbuka, secara umum, platform komputasi terdistribusi berbasis blockchain dan sistem operasi yang menampilkan fungsionalitas Smart Contract (scripting). Ini adalah infrastruktur untuk produk dan layanan blockchain.\n\nETH/Ether adalah mata uang kripto yang blockchain-nya dihasilkan oleh platform Ethereum. Ether dapat ditransfer antar akun dan digunakan untuk mengkompensasi node penambangan peserta untuk perhitungan yang dilakukan. Ethereum menyediakan mesin virtual lengkap yang terdesentralisasi, Mesin Virtual Ethereum (EVM), yang dapat mengeksekusi skrip menggunakan jaringan internasional node publik. "Gas", mekanisme penetapan harga transaksi internal, digunakan untuk mengurangi spam dan mengalokasikan sumber daya pada jaringan. Saat ini, Ethereum adalah blockchain terbaik dan terbesar untuk mengembangkan aplikasi dan layanan Smart Contract. AlphaWallet dimulai dengan mendukung blockchain Ethereum dan membantu meningkatkan teknologinya. Anda dapat mengubah Ethereum menjadi uang fiat dan mentransfernya ke rekening bank Anda melalui bursa mata uang kripto apa pun. @@ -394,14 +377,12 @@ Ambil Penurunan Mata Uang Impor Mata Uang Anda akan menerima - Pindai Kode QR Hasil Pemindaian Tidak valid Alamat Ethereum Baru saja memindai alamat Ethereum. Apakah Anda ingin mencoba mengunggah ini sebagai Token? Ungu Token %1$s Blockchain - 0.00 %s Telegram (Layanan Pelanggan) Permintaan transfer Permintaan transfer token: %1$s @@ -544,7 +525,6 @@ masukan fungsi \'%1$s\' tidak ditemukan dalam elemen HTML. Nilai yang dimasukkan tidak berlaku: %1$s Nilai - LinkedIn Tidak dapat membuat kunci. Coba aktifkan keamanan pada ponsel Anda. Sebuah Seed Phrase, seed pemulihan phrase atau seed phrase cadangan adalah daftar kata yang menyimpan semua informasi yang diperlukan untuk memulihkan dompet kripto. Perangkat lunak dompet biasanya akan menghasilkan seed phrase dan menginstruksikan pengguna untuk menuliskannya di atas kertas. Transaksi Terlalu Besar @@ -553,10 +533,8 @@ Rincian tanda tangan Salin Alamat Kontrak Diri sendiri - ERC721T Gagal menandatangani pertukaran pesan Tipe Token - Reddit Kecocokan TokenScript Versi TokenScript debug @@ -595,10 +573,8 @@ Console Hapus Perambah Cache Muat Ulang Data Token - TokenScript Ubah Bahasa Tambahkan / Sembunyikan Token - Instagram Ubah Mata Uang Pilih Mata Uang FIAT Kesalahan pada berkas TokenScript @@ -631,7 +607,6 @@ Parameter tidak valid saat melakukan Transaksi TokenScript . Silakan periksa masukan. TokenScript diganti oleh%1$s%2$s\n\n Token Asal:\n\n - %1$s -> %2$s\n\n (Debug) Konfirmasi Penghapusan File Hapus berkas %1$s @@ -667,7 +642,6 @@ Token Tersembunyi Abaikan Mencari Token… - Dompet Terhubung Sesi Berakhir Kirim Transaksi ETH Ditolak oleh pengguna @@ -676,7 +650,6 @@ Transaksi ditolak (coba gunakan lebih banyak gas) dari: %1$s dari - %1$s %2$s kepada: %1$s disetujui untuk mentransfer token: %1$s untuk dibelanjakan atas nama: %1$s @@ -686,17 +659,14 @@ Disetujui Persetujuan diberikan TokenScript Hubungi: - Testnet Hari ini beralih ke Token Sesi WalletConnect Tidak Berlaku Sesi WalletConnect sebelumnya tidak diakhiri dengan benar. Silakan kembali ke halaman web dan putuskan sambungan, kemudian memulai sesi baru. Data QR WalletConnect tidak berlaku Waktu untuk koneksi habis. Harap batalkan permintaan dari Dapp dan mulai sesi baru. - Nonce Beban Pembayaran Transaksi telah ditandatangani - %1$s Hapus catatan sesi ini? Sesi telah dihentikan. Beralih kembali ke Dapp dan memulai sesi WalletConnect baru. Transaksi tidak terkirim @@ -803,8 +773,6 @@ %1$s Aset | %2$s Ini adalah Testnet Tukar dengan Quickswap - Email - Discord Beri Nama Dompet Ini Masukkan Nama Dompet Simpan Nama @@ -851,7 +819,6 @@ Kinerja Cari token Aset - DeFi Tata Kelola Pemerintahan Barang Koleksi Apa yang baru? @@ -868,7 +835,6 @@ Tidak ada sesi Aktif Hubungkan Dompet Seed phrase hanya bisa berisi kata-kata - Token # Tautan Eksternal Penjelasan Rincian @@ -902,7 +868,6 @@ Tidak dapat menyimpan kunci: %1$s Peringatan Pencarian ENS AlphaWallet telah mendeteksi perbedaan antara penanda waktu ethereum dan waktu perangkat Anda saat ini, atau mungkin koneksi blockchain tidak disinkronkan, harap periksa waktu mobile Anda sudah benar, atau abaikan peringatan ini. - 0 Penurunan Peningkatan Transaksi telah habis waktunya. Anda bisa melihat status di halaman aktivitas. @@ -936,7 +901,6 @@ Khusus Nama Catatan - URL Terhubung Terhubung ke Tanda tangan @@ -960,4 +924,8 @@ Locked Key type in Database Key Entry in Secure Enclave + Transfer yang aman + Kebijakan pribadi + Ketentuan Layanan + Dompet yang terhubung diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 34a3209552..f52ca143b6 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -24,7 +24,6 @@ မလုပ်ရသေးပါ။ ပြန်လုပ်မည်။ %s ပြောင်းရွှေ့မည် %s ဝယ်မည် - ပြန်လုပ်မည် ဝေါလက် ရှိပြီးဖြစ်ပါသလား။ ဝေါလက် အသစ်တစ်ခုဖန်တီးမည် @@ -77,8 +76,6 @@ ပို၍အသေးစိတ်ပြုလုပ်ရန် ဝေါလက် ထည့်မည် Ethersacan တွင်ကြည့်မည် - Coinbase - LocalEthereum Changelly (ခရစ်ဒစ်ကတ်ဖြင့်ဝယ်မည်) @@ -94,8 +91,6 @@ မရှိပါ ဝေါလက်ကိုမရွေးချယ်ရသေးပါ ဤနေရာတွင်လုပ်ဆောင်မှုများကိုပြထားမည်ဖြစ်သည် - -- - -- ပို့နေပါသည်… လိပ်စာကို QRကုတ်မှတဆင့်ရယူမည် လုပ်ငန်းဆောင်ရွက်ခ ကြီးမြင့်လာသည်နှင့်အမျှ လုပ်ငန်းစဥ်ဆောင်ရွက်ခပို၍ဈေးကြီးလာမည်ဖြစ်သည်။ သို့သော်လည်း Ethereum ကွန်ရက် ပေါ်ရှိသင်၏လုပ်ငန်းစဥ်ကိုပို၍မြန်ဆန်စွာပြီးမြောက်စေမည်ဖြစ်သည်။ @@ -108,7 +103,6 @@ တိုကင်စာရင်းပြလုပ်ခြင်းပျက်ပြယ်ပါသည် ဝေါလက် အသစ်ပြုလုပ်ခြင်းပျက်ပြယ်ပါသည် - AlphaWallet အားလုံး ငွေကြေးများ အသေးစိတ်အဆင့်မြှင့်တင်ခြင်း @@ -127,10 +121,8 @@ ထုတ်ယူမည် ထုတ်ယူပြီးလက်မှတ်များ တိုကင်ကိုအသုံးပြုမည် - %1$s%2$s - %1$s (%2$s) အရောင်းစာရင်းပြုလုပ်မည် %1$s ကိုရောင်းရန်ရွေးချယ်သည်: ထုတ်ယူမည့်လက်မှတ်များကိုရွေးချယ်ပါshow @@ -196,11 +188,9 @@ ရက်/လ/နှစ် - ETH လက်မှတ်အရေအတွက် စုစုပေါင်းကုန်ကျငွေ: USDဖြင့် - %1$s %2$s %1$s ပမာဏာကိုရွေးချယ်ပါ သင်၏လက်မှတ်ကိုထုတ်ယူပြီးပါပြီ ရှာရန် @@ -213,11 +203,7 @@ Seed Phrase ဆိုသည်မှာအဘယ်နည်း။ ETHကိုမိမိ ဝေါလက်အတွင်းသို့မည်ကဲ့သို့လွှဲပြောင်းရမည်နည်း။ Tokenscriptဆိုသည်မှာအဘယ်နည်း။ - ကိုယ်ရေးအချက်အလက်ဆိုင်ရာမူဝါဒ - ဝန်ဆောင်မှုစည်းမျဥ်းများ - ကိုယ်ရေးအချက်အလက်ဆိုင်ရာမူဝါဒ.html - ဝန်ဆောင်မှုစည်းမျဥ်းများ.html - tokenscript_explaination.html + ဝန်ဆောင်မှု၏စည်းကမ်းချက်များ ၂၄နာရီ ကျေးဇူးတင်ရှိခြင်း %1$s/လက်မှတ် @@ -260,7 +246,6 @@ MagicLinkကိုဝေမျှမည် MagicLinkကိုထုတ်ပေးပါ ဈေးကွက်တွင်စာရင်းတင်မည် - --:-- MagicLink သက်တမ်းကုန်ဆုံးချိန် သက်တမ်းကုန်ဆုံးချိန်ကိုရွေးပါ သက်တမ်းကုန်ဆုံးမည့်ရက်ကိုရွေးပါ @@ -284,12 +269,6 @@ အရေးကြီးသောအရာများ 0.00 ETH ဝေါလက်ပြောင်းမည် - Facebook - Twitter - ERC 20 - ERC 875 - ERC 875* - ERC 1155 Ethereum သည် အများသူငှာပါဝင်နိုင်သော open-source နှင့် Blockchain အခြေခံ နည်းပညာပလက်ဖောင်းတစ်ခုဖြစ်ပါသည်။ Ethereum ပေါ်တွင် smart contract ဖြင့်လုပ်ငန်းများကိုလည်ပတ်နိုင်သောစနစ်တစ်ခုပါဝင်ပါသည်။ ၄င်းသည် blockchain နည်းပညာထုတ်ကုန်များနှင့် ဝန်ဆောင်မှုများကိုအတွက်အခြေခံကျသောအဆောက်အဦးတစ်ခုလည်းဖြစ်ပါသည်။ \n\nETH/Ether သည် Ethereum ပလက်ဖောင်းပေါ်ရှိ Blockchain ပေါ်တွင်လည်ပတ်နေသော ခရစ်ပ်တိုငွေကြေးတစ်မျိုးဖြစ်ပါသည်။ Ether ကိုအကောင့်အချင်းချင်းလွှဲပြောင်းပေးပို့မှုများပြုလုပ်နိုင်သလို သက်ဆိုင်ရာNodeများရှိmining လုပ်ငန်းများတွင်ပါဝင်ကူညီတွက်ချက်ပေးခြင်းဖြင့်လည်း ဆုကြေးအဖြစ်ရရှိနိုင်ပါသည်။ Ethereum သည် EVM(Ethereum Virtual Machine) ဟုခေါ်သော လုံးဝဗဟိုချုပ်ကိုင်မှုလုံးဝမရှိသော Turing-virtual machine ကိုထောက်ပံ့ကူညီပေး၍ နိုင်ငံတကာကွန်ရက်ပေါ်ရှိNodeများတွင်scripts များကိုလည်ပတ်ဆောက်ရွက်စေပါသည်။ Gas ဆိုသည်မှာ blockchain ပေါ်တွင်အရောင်းအဝယ်များပြုလုပ်ရန်အတွက်ကုန်ကျစားရိတ်ကိုသတ်မှတ်ပေးသာစနစ်ဖြစ်ပါသည်။ Gasကို network ပေါ်ရှိအရင်းအမြစ်များကို ခွဲဝေနေရာချထားရန်နှင့်အသုံးမဝင်သောအရာများကိုလျှော့ချရန်အတွက်အသုံးပြုပါသည်။ လက်ရှိတွင် Ethereum သည် smart contract အပလီကေးရှင်းများနှင့် ဝန်ဆောင်မှုများကိုပြုလုပ်ရန်အတွက် အကောင်းဆုံးနှင့်အကြီးမားဆုံးသောBlockchain ဖြစ်ပါသည်။ Alphawallet သည် Ethereum Blockchain ကိုစတင်ပံ့ပိုးနေပြီး ၄င်း၏နည်းပညာများကို တိုးတက်အောင်ပြုလုပ်နေပါသည်။ သင်၏Ethereumများကို ငွေကြေးအဖြစ်သို့ပြောင်းလဲနိုင်ပြီး ခရစ်ပ်တိုငွေကြေးလဲလှယ်သည့်ဝန်ဆောင်မှုကုမ္ပဏီများမှတဆင့်သင်၏ဘဏ်အကောင့်သို့ငွေကြေးများကိုပြောင်းရွှေ့နိုင်ပါသည်။ @@ -336,8 +315,6 @@ MagicLinkကိုဝယ်ယူသည် ထုတ်လုပ်သည် ဖျက်ဆီးသည် - ပြန်လည်ရောနှောသည် - NFTပြုလုပ်သည် ရှေ့သို့သွားမည် သိမ်းဆည်းမည် @@ -407,14 +384,12 @@ ငွေကြေးတန်ဖိုးကျနေချိန်တွင်ယူမည် ငွေကြေးများကိုထည့်သွင်းမည် သင်လက်ခံရရှိလိမ့်မည် - QR ကုတ်ကိုဖတ်မည် စကင်ဖတ်ရာတွင်ရလာဒ်များမမှန်ကန်ပါ Ethereum လိပ်စာ Ethereum လိပ်စာကိုဖတ်ပြီးပါပြီ။ တိုကင်အဖြစ်ထည့်သွင်းရန်ကြိုးစားကြည့်ပါမည်လား။ တိုကင်ကိုဖော်ပြမည် %1$s Blockchain - 0.00 %s Telegram အပြောင်းအရွှေ့တောင်းဆိုမှု တိုကင်အပြောင်းအရွှေ့တောင်းဆိုမှု: %1$s @@ -556,7 +531,6 @@ function input \'%1$s\' not found in HTML elements. Invalid input value: %1$s Value - LinkedIn သော့ကိုဖန်တီး၍မရပါ။ သင်၏ဖုန်းတွင်လုံခြုုံရေးခွင့်ပြုချက်ပြုလုပ်ပေးပါ။ Recovery Phrase(သို့) backup Seed Phrase သိမ်းဆည်းခြင်းဆိုသည်မှာ ခရစ်ပ်တိုဝေါလက်တစ်ခုကိုပြန်လည်ရယူရန်အတွက် လိုအပ်သောစကားလုံးများကိုသိမ်းဆည်းသော လုပ်ငန်းစဥ်ဖြစ်ပါသည်။ အသုံးပြုသူများသည်ပုံမှန်အားဖြင့်ဝေါလက်အသုံးပြုရန် seed phrase ကိုထည့်သွင်းရမည်ဖြစ်ပြီး ထို Seed Phrase ကို စာရွက်ပေါ်တွင် မှတ်သားထားရန်ညွှန်ကြားထားလေ့ရှိသည်။ လုပ်ငန်းစဥ်ကြီးမားလွန်းနေသည်။ @@ -565,10 +539,8 @@ လက်မှတ်အသေးစိတ် စာချုပ်လက်မှတ်ကိုကူးယူမည် Self - ERC721T ထုတ်ယူရန်မက်ဆေ့ကိုလက်မှတ်ထိုးခြင်းမအောင်မြင်ပါ။ တိုကင်အမျိုးအစား - Reddit CHANGE: TokenScript Compatibiity TokenScript debug မယုံကြည်ရပါ @@ -606,16 +578,14 @@ ထိန်းချုပ်ခန်း Browser Cacheဖိုင်များကိုရှင်းလင်းမည် တိုကင်အချက်အလက်များကိုပြန်လည်ဖော်ပြပါ - TokenScript ဘာသာစကားပြောင်းမည် တိုကင်များကိုပုန်းကွယ်မည်/ထည့်မည် - Instagram ငွေကြေးအမျိုးအစားပြောင်းမည် တရားဝင်ငွေကြေးအမျိုးအစားကိုရွေးချယ်ပါ TokenScript ဖိုင်အမှားအယွင်းဖြစ်နေပါသည် Browser cache ဖိုင်များကိုရှင်းလင်းမည် တိုကင်အချက်အလက်များကိုရှင်းလင်းပြီးပါပြီ - ချိတ်ဆက်ထားသောဝေါလက်များ + ချိတ်ဆက်ထားသောဝေါလက်များ တိုကင်အချက်လက်များကိုရှင်းလင်းနေပါသည်။ ခေတ္တစောင့်ဆိုင်းပါ။ သင်၏ ဝေါလက်များ ကူးယူမည် @@ -643,7 +613,6 @@ Invalid parameter while calling TokenScript Transaction. Please check inputs. TokenScript overridden by %1$s%2$s\n\n မူလတိုကင်များ:\n\n - %1$s -> %2$s\n\n (Debug) ဖိုင်ဖျက်ရန်အတည်ပြုသည် %1$sဖိုင်ကိုဖျက်မည် @@ -682,7 +651,6 @@ ပုန်းကွယ်ထားသောတိုကင်များ ချန်လှပ်သည် Tokens များကိုရှာရန်.... - WalletConnect လုပ်ငန်းစဥ်ရပ်နားမည် ETH လုပ်ငန်းစဥ်ကိုပေးပို့သည် အသုံးပြုသူမှငြင်းပယ်သည် @@ -691,7 +659,6 @@ လုပ်ငန်းစဥ်ငြင်းပယ်သည် (လုပ်ငန်းဆောင်ရွက်ခ များပိုမိုအသုံးပြု၍ထပ်မံကြိုးစားကြည့်ပါ) မှ: %1$s မှ - %1$s %2$s to: %1$s တိုကင်များကိုပြောင်းရွှေ့ရန်ခွင့်ပြုသည်: %1$s %1$sကိုယ်စားသုံးစွဲရန် @@ -701,8 +668,6 @@ ခွင့်ပြုသည် ခွင့်ပြုချက်ပေးခဲ့ပါသည် TokenScript call: - စမ်းသပ်ကွန်ရက် - ယနေ့ @@ -711,10 +676,8 @@ WalletConnect နှင့်ချိတ်ဆက်ထားသောလုပ်ငန်းစဥ်ကို မှန်ကန်စွာမပိတ်ရသေးပါ။ ကျေးဇူးပြု၍ အင်တာနက်စာမျက်နှာကိုပြန်သွား၍ ချိတ်ဆက်ထားမှုကိုဖြုတ်ပါ။ ထို့နောက် ချိတ်ထားမှုလုပ်ငန်းစဥ်အသစ်ကိုပြန်စပါ။ WalletConnectမှပြထားသောQRကုတ်သည်အသုံးပြု၍မရပါ Connection attempt timed out. Please cancel the request from the Dapp and start a new session. - Nonce ဝန်ချိန် လုပ်ငန်းစဥ်ကိုလက်မှတ်ထိုးပြီးပါပြီ - %1$s ယခုလုပ်ငန်းစဥ်မှတ်တမ်းကိုဖျက်ပစ်ပါမည်လား။ လုပ်ငန်းစဥ်ကိုပိတ်ချပြီးပါပြီ။ Dappကိုပြန်သွား၍ WalletConnectလုပ်ငန်းစဥ်ကိုအသစ်ပြန်စပါ။ လုပ်ငန်းစဥ်မပို့ခဲ့ပါ @@ -828,13 +791,11 @@ %1$s Assets | %2$s စမ်းသပ်ကွန်ရက်သို့ရောက်ရှိနေပါသည် Quickswapဖြင့် ပြောင်းလဲမည် - Email - Discord ယခုဝေါလက်ကိုအမည်ပေးပါ ဝေါလက်အမည်ကိုထည့်သွင်းပါ အမည်ကိုသိမ်းဆည်းမည် ပမာဏကိုရွေးချယ်ပါ - လုံခြုံစွာပြောင်းရွှေ့မည် + လုံခြုံစွာပြောင်းရွှေ့မည် ရွေးချယ်ထားသောတိုကင်များ တိုကင်များကိုပို့မည် အသုံးပြုသည်ကိုကျေနပ်မှုရှိလျှင် ကျေးဇူးပြု၍ ကျွန်တော်တို့အားအဆင့်သတ်မှတ်ပေး၍ကူညီပါ။ @@ -878,7 +839,6 @@ တိုကင်နာမည် ဗားရှင်း မျိုးစေ့ထားသောစကားစုများတွင်စကားလုံးများသာပါ 0 င်နိုင်သည် - Token # External Link Description Details @@ -891,7 +851,6 @@ Select Mode Network Info Assets - DeFi Governance Collectibles Connect Wallet @@ -931,7 +890,6 @@ Unable to store key: %1$s ENS Lookup Warning AlphaWallet has detected a discrepancy between ethereum\'s timestamp and your device\'s current time, or possibly the blockchain connection is not synchronized, please check your phone\'s time is correct, or ignore this warning. - 0 ရုပ်ရည် တိုးမြှင့်လာသည် The transaction has timed out. You can view the status in activity page. @@ -964,7 +922,6 @@ Custom Name Note - URL Connect Connect to Sign @@ -988,4 +945,8 @@ Locked Key type in Database Key Entry in Secure Enclave + ဒီပိုက်ဆံအိတ်အမည်ပြောင်းပါ + %1$s တိုကင် + %1$s ချိန်ခွင်လျှာမလုံလောက် + ကိုယ်ရေးအချက်အလက်မူဝါဒ diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 98cf6ce996..70f0aeb809 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -22,7 +22,6 @@ Không, quay lại Chuyển khoản %s Mua %s - Thử lại Đã có ví? Tạo một ví mới @@ -75,8 +74,6 @@ Chi tiết Thêm ví Xem trên Block Explorer - Coinbase - LocalEthereum Changelly (Mua với thẻ tín dụng) Chi tiết giao dịch @@ -91,8 +88,6 @@ N/A Ví chưa được chọn Các hoạt động sẽ xuất hiện tại đây - -- - -- Đang gửi… Nhận địa chỉ từ Mã QR The higher the gas price, the more expensive your transaction fee will be, but the quicker your transaction will be processed by the Ethereum network. @@ -105,12 +100,11 @@ Không tải được danh sách tiền Không tạo được ví - AlphaWallet Tất cả Tài sản Tùy chọn nâng cao Sao chép địa chỉ ví - Đổi tên Ví này + Đổi tên ví này Tên Venue Ngày @@ -123,9 +117,7 @@ Redeem Tickets Redeemed Use Token - %1$s%2$s - %1$s (%2$s) Create Sales Order Chọn %1$s để bán: Select Tickets to Redeem:show @@ -190,11 +182,9 @@ DD/MM/YY - ETH Quantity of Tickets Total Cost: Equivalent in USD - %1$s %2$s Select Quantity of %1$s Your ticket has been redeemed Tìm kiếm cho: @@ -207,11 +197,8 @@ Cụm từ bí mật là gì? Làm cách nào để chuyển ETH vào ví của tôi? TokenScript là gì? - Chính sách bảo mật - Điều khoản dịch vụ - privacyPolicy.html - termsOfService.html - tokenscript_explaination.html + Chính sách bảo mật + Điều khoản dịch vụ 24 hours Appreciation %1$s/Ticket @@ -254,7 +241,6 @@ Share MagicLink Generate MagicLink Danh sách trên thị trường - --:-- MagicLink Expiry Time Vui lòng chọn thời gian hết hạn Vui lòng chọn ngày hết hạn @@ -278,11 +264,6 @@ Quan trọng 0.00 ETH Thay đổi ví - Facebook - Twitter - ERC 20 - ERC 875 - ERC 875* Ethereum is an open-source, public, blockchain-based distributed computing platform and operating system featuring smart contract (scripting) functionality. It is the infrastructure for blockchain products and services.\n\nETH/Ether is a cryptocurrency whose blockchain is generated by the Ethereum platform. Ether can be transferred between accounts and used to compensate participant mining nodes for computations performed. Ethereum provides a decentralised Turing-complete virtual machine, the Ethereum Virtual Machine (EVM), which can execute scripts using an international network of public nodes. "Gas", an internal transaction pricing mechanism, is used to mitigate spam and allocate resources on the network. Currently, Ethereum is the best and largest blockchain for developing smart contract application and services. AlphaWallet starts with supporting Ethereum blockchain and helps improving its technology. You can convert Ethereum to fiat money and transfer it to your bank account through any cryptocurrency exchange. @@ -329,8 +310,6 @@ Magiclink Purchase Mint Burn - Remix - Commit NFT Tiếp tục Lưu lại @@ -400,14 +379,12 @@ Take Currency Drop Currency Import bạn sẽ nhận - Quét mã QR Kết quả quét không hợp lệ Địa chỉ Ethereum Just scanned an Ethereum address. Do you want to try to load this as a Token? Nạp Token %1$s Blockchain - 0.00 %s Telegram (Hỗ trợ khách hàng) Yêu cầu chuyển Token transfer request: %1$s @@ -550,7 +527,6 @@ function input \'%1$s\' not found in HTML elements. Giá trị đầu vào không hợp lệ: %1$s Value - LinkedIn Không thể tạo khóa. Thử bật bảo mật trên điện thoại của bạn. Cụm từ bí mật, cụm từ khôi phục bí mật hoặc cụm từ bí mật dự phòng là danh sách các từ lưu trữ tất cả thông tin cần thiết để khôi phục ví tiền điện tử. Phần mềm Wallet thường sẽ tạo ra một cụm từ bí mật và hướng dẫn người dùng viết nó ra giấy. Giao dịch quá lớn @@ -559,10 +535,8 @@ Chi tiết chữ ký Sao chép địa chỉ hợp đồng Self - ERC721T Failed to sign redeem message Kiểu Token - Reddit TokenScript Compatibiity Phiên bản TokenScript debug @@ -601,10 +575,8 @@ Bảng điều khiển Xóa bộ nhớ đệm của trình duyệt Tải lại dữ liệu tiền mã hóa - TokenScript Thay đổi ngôn ngữ Thêm / Ẩn Token - Instagram Thay đổi tiền tệ Chọn tiền tệ pháp định TokenScript file error @@ -637,7 +609,6 @@ Tham số không hợp lệ khi gọi Giao dịch TokenScript. Vui lòng kiểm tra đầu vào. TokenScript bị ghi đè bởi %1$s%2$s\n\n Origin Tokens:\n\n - %1$s -> %2$s\n\n (Debug) Xác nhận Xóa tệp Xóa tệp %1$s @@ -673,7 +644,6 @@ Ẩn Tokens Bỏ qua Tìm kiếm Tokens... - WalletConnect Kết thúc kết nối Send ETH Transaction Người dùng từ chối @@ -682,7 +652,6 @@ Giao dịch bị từ chối (thử sử dụng thêm gas) từ: %1$s từ - %1$s %2$s tới: %1$s được chấp thuận để chuyển các Token: %1$s to spend on behalf of: %1$s @@ -692,17 +661,14 @@ Chấp thuận Approval granted TokenScript call: - Mạng thử nghiệm Hôm nay Đi tới Token WalletConnect không hợp lệ Previous WalletConnect session not correctly terminated. Please return to webpage and disconnect, then start a new session. Dữ liệu QR WalletConnect không hợp lệ Connection attempt timed out. Please cancel the request from the Dapp and start a new session. - Nonce Payload Giao dịch đã ký - %1$s Delete this session record? Session has been terminated. Switch back to Dapp and start a new WalletConnect session. Transaction not sent @@ -807,8 +773,6 @@ Cảnh báo: Đang chuyển qua mạng thử nghiệm WalletConnect: Mạng không được hỗ trợ. Đóng kết nối và thay đổi mạng bằng trình duyệt Dapp Hoán đổi bằng Quickswap - Email - Discord Đặt tên cho ví này Nhập Tên Ví Lưu lại @@ -855,7 +819,6 @@ Performance Search token Assets - DeFi Quản trị Sưu tầm Có gì mới? @@ -872,7 +835,6 @@ No Active sessions Connect Wallet Cụm từ hạt giống chỉ có thể chứa từ - Token # External Link Description Details @@ -908,7 +870,6 @@ Unable to store key: %1$s ENS Lookup Warning AlphaWallet has detected a discrepancy between ethereum\'s timestamp and your device\'s current time, or possibly the blockchain connection is not synchronized, please check your phone\'s time is correct, or ignore this warning. - 0 Giảm bớt Tăng lên The transaction has timed out. You can view the status in activity page. @@ -941,7 +902,6 @@ Custom Name Note - URL Connect Connect to Sign @@ -965,4 +925,7 @@ Locked Key type in Database Key Entry in Secure Enclave + Không đủ %1$s cân bằng + Chuyển giao an toàn + Ví kết nối diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 3db506a0a9..31d044f2bc 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -21,7 +21,6 @@ 否,重复 转移%s 购买%s - 重试 已经有钱包了吗? 创建新钱包 @@ -68,8 +67,6 @@ 更多详情 添加钱包 在Block Explorer上查看 - Coinbase - LocalEthereum Changelly 交易详情 @@ -84,8 +81,6 @@ 不适用 未选择钱包 交易活动将出现在这里 - -- - -- 发送中…… 从二维码获取地址 燃料价格越高,您的交易费用就越昂贵,但以太坊网络对交易的处理速度则越快。 @@ -97,7 +92,6 @@ 无法导出钱包 无法加载通证列表 无法创建钱包 - AlphaWallet 全部 币类 高级设置 @@ -115,9 +109,7 @@ 兑换 门票已兑换 使用Token - %1$s%2$s - %1$s (%2$s) 创建卖单 选择要出售的%1$s: 选择要兑换的门票: @@ -181,11 +173,9 @@ DD/MM/YY - 以太币 门票数量 总价: 相当于USD - %1$s %2$s 选择%1$s数量 你的门票已经被兑换 搜索: @@ -198,7 +188,6 @@ 助记词是做什么的? 怎样把以太币转到AlphaWallet内? 什么是 TokenScript? - tokenscript_explaination.html 24小时 升值 %1$s/门票 @@ -241,7 +230,6 @@ 创建链接 创建销售链接 放上市场待售 - --:-- 链接过期时间 请输入有效时间 请输入有效日期 @@ -265,11 +253,6 @@ 重要 0.00 以太币 更换当前钱包 - Facebook - Twitter - ERC 20 - ERC 875 - ERC 875* 以太坊是一个建立在区块链技术之上的开发平台,同时具有智能合约功能的操作系统。它是区块链产品和服务的基础技术。\n\nETH/Ether 是一个加密货币,其区块链由以太坊平台生成。 Ether 可以在在账户中互相转移和用来奖励给挖矿者。以太坊提供了一个“图灵完备”的虚拟机,称为以太坊虚拟机(Ethereum Virtual Machine),简称EVM,用于国际网络中执行交易代码, \"Gas\", 是一种特别的单位用于Ethereum(以太币)里,它用来衡量一个行为或者一系列行为有多少“工作量”。 目前,以太坊是最好区块链技术和开发智能合约应用程序和。AlphaWallet 开发于太坊区块链技术基础上,目前还在不断创新。 您可以将以太币转换为法定货币,并通过任何加密货币市场转移到您的银行账户。 @@ -384,14 +367,12 @@ 领取加密货币 货币导入 您将收到 - 扫描二维码 无效扫描结果 以太坊地址 刚刚扫描了一个以太坊地址。您是否要尝试将此作为通证进行加载? 加载通证 %1$s区块链 - 0.00%s 电报 (客户支持) 转账请求 通证转账请求: %1$s @@ -534,7 +515,6 @@ 在 HTML 元素中找不到函数输入\'%1$s\'。 无效输入值:%1$s - LinkedIn 无法创建密钥。请尝试在手机上启用安全功能。 助记词、恢复助记词或备份助记词均属于词语列表,可存储用于恢复以太坊钱包所需的所有信息。钱包软件通常会生成助记词,并指示用户将其记在纸上。 交易太大 @@ -543,10 +523,8 @@ 签名详细信息 复制合约地址 自己 - ERC721T 无法签署兑换消息 通证类型 - Reddit TokenScript 标准兼容性 版本 TokenScript 调试 @@ -584,10 +562,8 @@ 控制台 清除浏览器缓存 重新加载通证数据 - TokenScript 更换语言 添加/隐藏通证 - Instagram 更改货币 选择法定货币 TokenScript 文件错误 @@ -619,7 +595,6 @@ 调用 TokenScript 交易时参数无效。请检查输入。 TokenScript 被%1$s%2$s覆盖\n\n 原始通证:\n\n - %1$s -> %2$s\n\n (调试) 确认文件删除操作 删除文件 %1$s @@ -655,7 +630,6 @@ 隐藏的通证 忽略 搜索通证... - WalletConnect 结束会话 发送以太币交易 遭到用户拒绝 @@ -664,7 +638,6 @@ 交易被拒绝(尝试使用更多的燃料) 来源地址 %1$s 来源地址 - %1$s %2$s 接收地址 %1$s 批准转让代币了 %1$s 代表地址 %1$s @@ -680,10 +653,8 @@ 先前的WalletConnect会话未正确终止。请返回网页并断开连接,然后开始新的会话。 无效的WalletConnect二维码数据 Connection attempt timed out. Please cancel the request from the Dapp and start a new session. - Nonce 数据 签署的交易 - %1$s 删除此会话记录? Session has been terminated. Switch back to Dapp and start a new WalletConnect session. Transaction not sent @@ -779,8 +750,6 @@ %1$s Assets | %2$s This is Testnet Swap with Quickswap - Email - Discord Name This Wallet Enter Wallet Name Save Name @@ -835,7 +804,6 @@ Performance Search token 资产 - DeFi 治理 NFT 什么是新的? @@ -852,7 +820,6 @@ No Active sessions Connect Wallet 助记符只能包含单词 - Token # External Link Description Details @@ -865,7 +832,6 @@ I already have a Wallet Select Mode Network Info - Testnet Website Light Dark @@ -889,7 +855,6 @@ Unable to store key: %1$s ENS Lookup Warning AlphaWallet has detected a discrepancy between ethereum\'s timestamp and your device\'s current time, or possibly the blockchain connection is not synchronized, please check your phone\'s time is correct, or ignore this warning. - 0 减少 增加 The transaction has timed out. You can view the status in activity page. @@ -922,7 +887,6 @@ Custom Name Note - URL Connect Connect to Sign @@ -946,4 +910,9 @@ Locked Key type in Database Key Entry in Secure Enclave + 余额不足 %1$s + 安全转账 + 隐私政策 + 服务条款 + 已连接的钱包 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a9dda3d53b..bf29fe9c54 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -22,7 +22,7 @@ No, repeat Transfer %s Buy %s - + Try again Already have a wallet? Create a New Wallet @@ -76,8 +76,8 @@ More details Add wallet View in Block Explorer - Coinbase - LocalEthereum + Coinbase + LocalEthereum Changelly (Buy with Credit card) Transaction detail @@ -92,8 +92,8 @@ N/A Wallet is not selected Activities will appear here - -- - -- + -- + -- Sending… Get address from QR Code The higher the gas price, the more expensive your transaction fee will be, but the quicker your transaction will be processed by the Ethereum network. @@ -106,7 +106,7 @@ Failed to load tokens list Failed to create a wallet - AlphaWallet + AlphaWallet All Currencies Advanced Options @@ -124,9 +124,9 @@ Redeem Tickets Redeemed Use Token - %1$s%2$s + %1$s%2$s - %1$s (%2$s) + %1$s (%2$s) Create Sales Order Select %1$s to Sell: Select Tickets to Redeem:show @@ -191,11 +191,10 @@ DD/MM/YY - ETH Quantity of Tickets Total Cost: Equivalent in USD - %1$s %2$s + %1$s %2$s Select Quantity of %1$s Your ticket has been redeemed Search for: @@ -208,11 +207,11 @@ What is a Seed Phrase? How do I transfer ETH into my wallet? What is TokenScript? - Privacy Policy - Terms of Service + Privacy Policy + Terms of Service privacyPolicy.html termsOfService.html - tokenscript_explaination.html + tokenscript_explaination.html 24 hours Appreciation %1$s/Ticket @@ -255,7 +254,7 @@ Share MagicLink Generate MagicLink List on marketplace - --:-- + --:-- MagicLink Expiry Time Please select expiry time Please select expiry date @@ -279,11 +278,11 @@ Important 0.00 ETH Change Wallet - Facebook - Twitter - ERC 20 - ERC 875 - ERC 875* + Facebook + Twitter + ERC 20 + ERC 875 + ERC 875* ERC 1155 Ethereum is an open-source, public, blockchain-based distributed computing platform and operating system featuring smart contract (scripting) functionality. It is the infrastructure for blockchain products and services.\n\nETH/Ether is a cryptocurrency whose blockchain is generated by the Ethereum platform. Ether can be transferred between accounts and used to compensate participant mining nodes for computations performed. Ethereum provides a decentralised Turing-complete virtual machine, the Ethereum Virtual Machine (EVM), which can execute scripts using an international network of public nodes. "Gas", an internal transaction pricing mechanism, is used to mitigate spam and allocate resources on the network. Currently, Ethereum is the best and largest blockchain for developing smart contract application and services. AlphaWallet starts with supporting Ethereum blockchain and helps improving its technology. @@ -402,14 +401,14 @@ Take Currency Drop Currency Import you will receive - + Scan QR Code Invalid Scan Result Ethereum Address Just scanned an Ethereum address. Do you want to try to load this as a Token? Load Token %1$s Blockchain - 0.00 %s + 0.00 %s Telegram (Customer Support) Transfer request Token transfer request: %1$s @@ -552,7 +551,7 @@ function input \'%1$s\' not found in HTML elements. Invalid input value: %1$s Value - LinkedIn + LinkedIn Unable to create key. Try enabling security on your phone. A seed phrase, seed recovery phrase or backup seed phrase is a list of words which store all the information needed to recover a crypto wallet. Wallet software will typically generate a seed phrase and instruct the user to write it down on paper. Transaction Too Large @@ -561,10 +560,10 @@ Signature details Copy Contract Address Self - ERC721T + ERC721T Failed to sign redeem message Token Type - Reddit + Reddit TokenScript Compatibility Version TokenScript debug @@ -603,16 +602,16 @@ Console Clear Browser Cache Reload Token Data - TokenScript + TokenScript Change Language Add / Hide Tokens - Instagram + Instagram Change Currency Select FIAT Currency TokenScript file error Browser cache cleared Token Data cleared - Connected Wallets + Connected Wallets Token data being cleared … Please wait Your Wallets Copy @@ -640,7 +639,7 @@ Invalid parameter while calling TokenScript Transaction. Please check inputs. TokenScript overridden by %1$s%2$s\n\n Origin Tokens:\n\n - %1$s -> %2$s\n\n + %1$s -> %2$s\n\n (Debug) Confirm File Delete Delete file %1$s @@ -676,7 +675,7 @@ Hidden Tokens Ignore Search for Tokens... - WalletConnect + WalletConnect End Session Send ETH Transaction Rejected by the user @@ -685,7 +684,7 @@ Transaction rejected (try using more gas) from: %1$s from - %1$s %2$s + %1$s %2$s to: %1$s %1$s: %2$s approved to transfer tokens: %1$s @@ -696,17 +695,17 @@ Approved Approval granted TokenScript call: - Testnet + Testnet Today Go to Token Invalid WalletConnect Session Previous WalletConnect session not correctly terminated. Please return to webpage and disconnect, then start a new session. Invalid WalletConnect QR data Connection attempt timed out. Please cancel the request from the Dapp and start a new session. - Nonce + Nonce Payload Signed Transactions - %1$s + %1$s Delete this session record? Session has been terminated. Switch back to Dapp and start a new WalletConnect session. Transaction not sent @@ -824,13 +823,13 @@ (max. %1$s) This is Testnet Swap with Quickswap - Email - Discord + Email + Discord Name This Wallet Enter Wallet Name Save Name Select Amount - Safe Transfer + Safe Transfer Safe Batch Transfer #%1$s Selected Tokens @@ -875,7 +874,7 @@ Performance Search token Assets - DeFi + DeFi Governance Collectibles What\'s new? @@ -892,7 +891,7 @@ No Active sessions Connect Wallet Seed phrase can only contain words - Token # + Token # External Link Description Details @@ -926,7 +925,6 @@ Unable to store key: %1$s ENS Lookup Warning AlphaWallet has detected a discrepancy between ethereum\'s timestamp and your device\'s current time, or possibly the blockchain connection is not synchronized, please check your phone\'s time is correct, or ignore this warning. - 0 Decrease Increase The transaction has timed out. You can view the status in activity page. @@ -963,7 +961,7 @@ 0.01 Name Note - URL + URL Connect Connect to Sign @@ -987,4 +985,6 @@ Locked Key type in Database Key Entry in Secure Enclave + ETH + 0 From d7bdd373e2a48cd011255e469470e48a730fac38 Mon Sep 17 00:00:00 2001 From: keval-finimble <110013677+keval-finimble@users.noreply.github.com> Date: Fri, 16 Sep 2022 04:17:14 +0530 Subject: [PATCH 094/183] =?UTF-8?q?Added=20boolean=20to=20TokensAdapter's?= =?UTF-8?q?=20constructor=20to=20handle=20the=20Where=20ar=E2=80=A6=20(#28?= =?UTF-8?q?16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * - Created a function to handle the "Where are my tokens" view from AddTokenActivity. * - Did code formatting to approve the PR. --- .../alphawallet/app/ui/AddTokenActivity.java | 1 + .../app/ui/widget/adapter/TokensAdapter.java | 35 +++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java b/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java index 0a2d589716..deeb21aee1 100644 --- a/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java @@ -125,6 +125,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { adapter = new TokensAdapter(this, viewModel.getAssetDefinitionService(), viewModel.getTokensService(), null); adapter.setHasStableIds(true); + adapter.showTestNetTips(); adapter.setFilterType(TokenFilter.NO_FILTER); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(this)); diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java index a852f4d72f..7d397e65ee 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java @@ -59,6 +59,7 @@ public class TokensAdapter extends RecyclerView.Adapter { private boolean debugView = false; private boolean gridFlag; + private boolean showTestNetTips = false; protected final TokensAdapterCallback tokensAdapterCallback; protected final SortedList items = new SortedList<>(SortedItem.class, new SortedList.Callback() { @@ -122,7 +123,8 @@ protected TokensAdapter(TokensAdapterCallback tokensAdapterCallback, AssetDefini } @Override - public long getItemId(int position) { + public long getItemId(int position) + { Object obj = items.get(position); if (obj instanceof TokenSortedItem) { TokenCardMeta tcm = ((TokenSortedItem) obj).value; @@ -196,7 +198,8 @@ public BinderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int vie } @Override - public void onBindViewHolder(BinderViewHolder holder, int position) { + public void onBindViewHolder(BinderViewHolder holder, int position) + { items.get(position).view = holder; holder.bind(items.get(position).value); } @@ -213,7 +216,8 @@ public void onViewDetachedFromWindow(@NonNull BinderViewHolder holder) } @Override - public int getItemViewType(int position) { + public int getItemViewType(int position) + { if (position < items.size()) { return items.get(position).viewType; @@ -233,7 +237,8 @@ public void setWalletAddress(String walletAddress) { this.walletAddress = walletAddress; } - private void addSearchTokensLayout() { + private void addSearchTokensLayout() + { if (walletAddress != null && !walletAddress.isEmpty()) { items.add(new ManageTokensSearchItem(new ManageTokensData(walletAddress, managementLauncher), -1)); } @@ -246,7 +251,8 @@ private void addHeaderLayout(TokenCardMeta tcm) items.add(new ChainItem(tcm.getChain(), tcm.group)); } - private void addManageTokensLayout() { + private void addManageTokensLayout() + { if (walletAddress != null && !walletAddress.isEmpty() && tokensService.isMainNetActive() && (filterType == TokenFilter.ALL || filterType == TokenFilter.ASSETS)) { //only show buy button if filtering all or assets items.add(new ManageTokensSortedItem(new ManageTokensData(walletAddress, managementLauncher))); @@ -330,7 +336,8 @@ private void removeMatchingTokenDifferentWeight(TokenCardMeta token) } } - public void removeToken(TokenCardMeta token) { + public void removeToken(TokenCardMeta token) + { for (int i = 0; i < items.size(); i++) { Object si = items.get(i); if (si instanceof TokenSortedItem) { @@ -344,7 +351,8 @@ public void removeToken(TokenCardMeta token) { } } - public void removeToken(long chainId, String tokenAddress) { + public void removeToken(long chainId, String tokenAddress) + { String id = TokensRealmSource.databaseKey(chainId, tokenAddress); for (int i = 0; i < items.size(); i++) { Object si = items.get(i); @@ -425,13 +433,12 @@ private void populateTokens(TokenCardMeta[] tokens, boolean clear) private void addTestNetTips() { - if (!tokensService.isMainNetActive()) - { + if (!tokensService.isMainNetActive() && !showTestNetTips) items.add(new TestNetTipsItem(0)); - } } - public void setTotal(BigDecimal totalInCurrency) { + public void setTotal(BigDecimal totalInCurrency) + { total = new TotalBalanceSortedItem(totalInCurrency); //see if we need an update items.beginBatchedUpdates(); @@ -477,6 +484,12 @@ public void setFilterType(TokenFilter filterType) filterAdapterItems(); } + public void showTestNetTips() + { + this.showTestNetTips = true; + notifyDataSetChanged(); + } + public void clear() { items.beginBatchedUpdates(); From b764f4d55304b437941a31d3b11338fe94dab893 Mon Sep 17 00:00:00 2001 From: keval-finimble <110013677+keval-finimble@users.noreply.github.com> Date: Fri, 16 Sep 2022 07:21:53 +0530 Subject: [PATCH 095/183] 2706 feature testnet balance (#2779) * non zero balance Testnet in WalletsActivity when user has selected TestNet. --- .../com/alphawallet/app/entity/Wallet.java | 1 + .../app/entity/tokendata/TokenUpdateType.java | 9 +++ .../alphawallet/app/entity/tokens/Token.java | 17 ++++ .../app/service/TokensService.java | 29 +++++++ .../alphawallet/app/ui/WalletsActivity.java | 31 ++++---- .../adapter/TestNetHorizontalListAdapter.java | 79 +++++++++++++++++++ .../widget/adapter/WalletsSummaryAdapter.java | 53 ++++++++++--- .../ui/widget/holder/WalletSummaryHolder.java | 29 ++++--- .../app/viewmodel/WalletsViewModel.java | 59 +++++++++++--- .../app/widget/TokensBalanceView.java | 36 +++++++++ .../layout/activity_transaction_detail.xml | 10 +-- .../layout/item_horizontal_testnet_list.xml | 24 ++++++ .../layout/item_token_with_balance_view.xml | 23 ++++++ .../res/layout/item_wallet_summary_manage.xml | 33 ++++---- app/src/main/res/values/strings.xml | 1 + .../adapter/WalletsSummaryAdapterTest.java | 76 ------------------ 16 files changed, 365 insertions(+), 145 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/entity/tokendata/TokenUpdateType.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/adapter/TestNetHorizontalListAdapter.java create mode 100644 app/src/main/java/com/alphawallet/app/widget/TokensBalanceView.java create mode 100644 app/src/main/res/layout/item_horizontal_testnet_list.xml create mode 100644 app/src/main/res/layout/item_token_with_balance_view.xml delete mode 100644 app/src/test/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapterTest.java diff --git a/app/src/main/java/com/alphawallet/app/entity/Wallet.java b/app/src/main/java/com/alphawallet/app/entity/Wallet.java index 799c3f499c..83a5990fa6 100644 --- a/app/src/main/java/com/alphawallet/app/entity/Wallet.java +++ b/app/src/main/java/com/alphawallet/app/entity/Wallet.java @@ -22,6 +22,7 @@ public class Wallet implements Parcelable { public String balanceSymbol; public String ENSAvatar; public boolean isSynced; + public Token[] tokens; public Wallet(String address) { this.address = address; diff --git a/app/src/main/java/com/alphawallet/app/entity/tokendata/TokenUpdateType.java b/app/src/main/java/com/alphawallet/app/entity/tokendata/TokenUpdateType.java new file mode 100644 index 0000000000..4f75f70e96 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/tokendata/TokenUpdateType.java @@ -0,0 +1,9 @@ +package com.alphawallet.app.entity.tokendata; + +/** + * Created by JB on 22/08/2022. + */ +public enum TokenUpdateType +{ + ACTIVE_SYNC, STORED +} diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java index ba8c2e4acd..b5c2666648 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java @@ -2,6 +2,8 @@ import static android.text.Html.FROM_HTML_MODE_COMPACT; +import static androidx.core.content.ContextCompat.getColorStateList; + import android.app.Activity; import android.content.Context; import android.os.Build; @@ -9,6 +11,7 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Pair; +import android.view.View; import com.alphawallet.app.R; import com.alphawallet.app.entity.ContractInteract; @@ -20,6 +23,7 @@ import com.alphawallet.app.entity.nftassets.NFTAsset; import com.alphawallet.app.entity.opensea.AssetContract; import com.alphawallet.app.entity.tokendata.TokenGroup; +import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.EventResult; import com.alphawallet.app.repository.entity.RealmToken; @@ -49,6 +53,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -202,6 +207,18 @@ public String getFullName(AssetDefinitionService assetDefinition, int count) } } + public String getTokenSymbol(Token token){ + + if (!TextUtils.isEmpty(token.tokenInfo.symbol) && token.tokenInfo.symbol.length() > 1) + { + return Utils.getIconisedText(token.tokenInfo.symbol); + } + else + { + return Utils.getIconisedText(token.getName()); + } + } + public String getTSName(AssetDefinitionService assetDefinition, int count) { String name = assetDefinition != null ? assetDefinition.getTokenName(tokenInfo.chainId, tokenInfo.address, count) : null; if (name != null) { diff --git a/app/src/main/java/com/alphawallet/app/service/TokensService.java b/app/src/main/java/com/alphawallet/app/service/TokensService.java index c76e4b2712..2bcbd69851 100644 --- a/app/src/main/java/com/alphawallet/app/service/TokensService.java +++ b/app/src/main/java/com/alphawallet/app/service/TokensService.java @@ -21,6 +21,7 @@ import com.alphawallet.app.entity.nftassets.NFTAsset; import com.alphawallet.app.entity.tokendata.TokenGroup; import com.alphawallet.app.entity.tokendata.TokenTicker; +import com.alphawallet.app.entity.tokendata.TokenUpdateType; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; import com.alphawallet.app.entity.tokens.TokenFactory; @@ -585,6 +586,33 @@ public Single getChainBalance(String walletAddress, long chainId) return tokenRepository.fetchChainBalance(walletAddress, chainId); } + // Note that this routine works across different wallets, so there's no usage of currentAddress + public Single syncChainBalances(String walletAddress, TokenUpdateType updateType) + { + //update all chain balances + return Single.fromCallable(() -> { + List baseTokens = new ArrayList<>(); + for (long chainId : networkFilter) + { + Token baseToken = tokenRepository.fetchToken(chainId, walletAddress, walletAddress); + if (baseToken == null) + { + baseToken = ethereumNetworkRepository.getBlankOverrideToken(ethereumNetworkRepository.getNetworkByChain(chainId)); + } + baseToken.setTokenWallet(walletAddress); + BigDecimal balance = baseToken.balance; + if (updateType == TokenUpdateType.ACTIVE_SYNC) balance = tokenRepository.updateTokenBalance(walletAddress, baseToken).blockingGet(); + if (balance.compareTo(BigDecimal.ZERO) > 0) + { + baseToken.balance = balance; + baseTokens.add(baseToken); + } + } + + return baseTokens.toArray(new Token[0]); + }); + } + private void onBalanceChange(BigDecimal newBalance, Token t) { boolean balanceChange = !newBalance.equals(t.balance); @@ -1076,6 +1104,7 @@ public void track(String gasSpeed) } } + @NotNull public Token getTokenOrBase(long chainId, String address) { Token token = getToken(chainId, address); diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java index 6df7564f8d..375243573f 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletsActivity.java @@ -27,6 +27,7 @@ import com.alphawallet.app.entity.SyncCallback; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletConnectActions; +import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.service.KeyService; @@ -40,6 +41,8 @@ import com.google.android.material.bottomsheet.BottomSheetDialog; import com.google.android.material.snackbar.Snackbar; +import java.util.Map; + import javax.inject.Inject; import dagger.hilt.android.AndroidEntryPoint; @@ -56,9 +59,8 @@ public class WalletsActivity extends BaseActivity implements { private final Handler handler = new Handler(); private final long balanceChain = EthereumNetworkRepository.getOverrideToken().chainId; - WalletsViewModel viewModel; + private WalletsViewModel viewModel; private RecyclerView list; - private SwipeRefreshLayout refreshLayout; private SystemView systemView; private Dialog dialog; private AWalletAlertDialog aDialog; @@ -101,7 +103,6 @@ protected void onResume() { super.onResume(); initViewModel(); - initViews(); } private void scrollToDefaultWallet() @@ -109,7 +110,7 @@ private void scrollToDefaultWallet() int position = adapter.getDefaultWalletIndex(); if (position != -1) { - list.smoothScrollToPosition(position); + list.getLayoutManager().scrollToPosition(position); } } @@ -127,9 +128,15 @@ private void initViewModel() viewModel.createdWallet().observe(this, this::onCreatedWallet); viewModel.createWalletError().observe(this, this::onCreateWalletError); viewModel.noWalletsError().observe(this, this::noWallets); + viewModel.baseTokens().observe(this, this::updateBaseTokens); } + viewModel.onPrepare(balanceChain, this); + initViews(); //adjust here to change which chain the wallet show the balance of, eg use CLASSIC_ID for an Eth Classic wallet + } - viewModel.onPrepare(balanceChain, this); //adjust here to change which chain the wallet show the balance of, eg use CLASSIC_ID for an Eth Classic wallet + private void updateBaseTokens(Map walletTokens) + { + adapter.setTokens(walletTokens); } protected Activity getThisActivity() @@ -146,7 +153,7 @@ private void noWallets(Boolean aBoolean) private void initViews() { - refreshLayout = findViewById(R.id.refresh_layout); + SwipeRefreshLayout refreshLayout = findViewById(R.id.refresh_layout); list = findViewById(R.id.list); list.setLayoutManager(new LinearLayoutManager(this)); @@ -172,25 +179,19 @@ private void onCreateWalletError(ErrorEnvelope errorEnvelope) @Override public void syncUpdate(String wallet, Pair value) { - runOnUiThread(() -> { - adapter.updateWalletState(wallet, value); - }); + runOnUiThread(() -> adapter.updateWalletState(wallet, value)); } @Override public void syncCompleted(String wallet, Pair value) { - runOnUiThread(() -> { - adapter.completeWalletSync(wallet, value); - }); + runOnUiThread(() -> adapter.completeWalletSync(wallet, value)); } @Override public void syncStarted(String wallet, Pair value) { - runOnUiThread(() -> { - adapter.setUnsyncedWalletValue(wallet, value); - }); + runOnUiThread(() -> adapter.setUnsyncedWalletValue(wallet, value)); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TestNetHorizontalListAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TestNetHorizontalListAdapter.java new file mode 100644 index 0000000000..6e5fada14a --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TestNetHorizontalListAdapter.java @@ -0,0 +1,79 @@ +package com.alphawallet.app.ui.widget.adapter; + +import android.content.Context; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import com.alphawallet.app.R; +import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.widget.TokenIcon; + +import timber.log.Timber; + +public class TestNetHorizontalListAdapter extends RecyclerView.Adapter +{ + private final Token[] tokens; + private final Context context; + + public TestNetHorizontalListAdapter(Token[] tokens, Context context) + { + this.tokens = tokens; + this.context = context; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) + { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_horizontal_testnet_list, parent, false); + return new TestNetHorizontalListAdapter.ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) + { + holder.tokenIcon.clearLoad(); + try + { + String coinBalance = tokens[position].getStringBalanceForUI(4); + if (!TextUtils.isEmpty(coinBalance)) + { + holder.tokenPrice.setText(context.getString(R.string.valueSymbol, coinBalance, tokens[position].getTokenSymbol(tokens[position]))); + } + holder.tokenIcon.bindData(tokens[position].tokenInfo.chainId); + if (!tokens[position].isEthereum()) + { + holder.tokenIcon.setChainIcon(tokens[position].tokenInfo.chainId); //Add in when we upgrade the design + } + } + catch (Exception e) + { + Timber.e(e); + } + } + + @Override + public int getItemCount() + { + return tokens.length; + } + + static class ViewHolder extends RecyclerView.ViewHolder + { + TokenIcon tokenIcon; + TextView tokenPrice; + ViewHolder(@NonNull View itemView) + { + super(itemView); + tokenIcon = itemView.findViewById(R.id.token_icon); + tokenPrice = itemView.findViewById(R.id.title_set_price); + } + } +} + diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapter.java index e3438e578c..433e7755fe 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapter.java @@ -14,6 +14,7 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletType; +import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.repository.WalletItem; import com.alphawallet.app.ui.widget.entity.WalletClickCallback; @@ -34,7 +35,7 @@ public class WalletsSummaryAdapter extends RecyclerView.Adapter implements WalletClickCallback, Runnable { private final OnSetWalletDefaultListener onSetWalletDefaultListener; - private boolean mainNetActivated; + private final boolean mainNetActivated; private final ArrayList wallets; private final Map> valueMap = new HashMap<>(); private final Handler handler = new Handler(Looper.getMainLooper()); @@ -45,7 +46,8 @@ public class WalletsSummaryAdapter extends RecyclerView.Adapter(); @@ -56,17 +58,19 @@ public WalletsSummaryAdapter(Context ctx, @NotNull @Override - public BinderViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) { + public BinderViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) + { BinderViewHolder binderViewHolder = null; - switch (viewType) { + switch (viewType) + { case WalletHolder.VIEW_TYPE: binderViewHolder = new WalletSummaryHolder(R.layout.item_wallet_summary_manage, parent, this, realm); - break; + break; case TextHolder.VIEW_TYPE: binderViewHolder = new TextHolder(R.layout.item_standard_header, parent); break; case WalletSummaryHeaderHolder.VIEW_TYPE: - binderViewHolder = new WalletSummaryHeaderHolder(R.layout.item_wallet_summary_large_title, parent,this, realm); + binderViewHolder = new WalletSummaryHeaderHolder(R.layout.item_wallet_summary_large_title, parent, this, realm); break; default: break; @@ -75,9 +79,11 @@ public BinderViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewTy } @Override - public void onBindViewHolder(@NotNull BinderViewHolder holder, int position) { + public void onBindViewHolder(@NotNull BinderViewHolder holder, int position) + { Bundle bundle; - switch (getItemViewType(position)) { + switch (getItemViewType(position)) + { case WalletHolder.VIEW_TYPE: Wallet wallet = wallets.get(position); bundle = new Bundle(); @@ -120,12 +126,14 @@ public void onBindViewHolder(@NotNull BinderViewHolder holder, int position) { } @Override - public int getItemCount() { + public int getItemCount() + { return wallets.size(); } @Override - public int getItemViewType(int position) { + public int getItemViewType(int position) + { switch (wallets.get(position).type) { default: @@ -141,7 +149,8 @@ public int getItemViewType(int position) { } } - public void setDefaultWallet(Wallet wallet) { + public void setDefaultWallet(Wallet wallet) + { this.defaultWallet = wallet; notifyDataSetChanged(); } @@ -307,7 +316,7 @@ public void onWalletClicked(Wallet wallet) public void ensAvatar(Wallet wallet) { //update the ENS avatar in the database - walletInteract.updateWalletItem(wallet, WalletItem.ENS_AVATAR, () -> { }); + walletInteract.updateWalletItem(wallet, WalletItem.ENS_AVATAR, () -> {}); } public void onDestroy() @@ -324,7 +333,25 @@ public int getDefaultWalletIndex() return -1; } - public interface OnSetWalletDefaultListener { + public interface OnSetWalletDefaultListener + { void onSetDefault(Wallet wallet); } + + public void setTokens(Map walletTokens) + { + if (walletTokens == null) return; + + for (Token[] token : walletTokens.values()) + { + Token[] t = walletTokens.get(token[0].getAddress()); + String walletAddress = token[0].getAddress(); + int walletIndex = getWalletIndex(walletAddress); + if (walletIndex != -1) + { + this.wallets.get(walletIndex).tokens = t; + notifyItemChanged(walletIndex); + } + } + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/holder/WalletSummaryHolder.java b/app/src/main/java/com/alphawallet/app/ui/widget/holder/WalletSummaryHolder.java index 1d7c275da5..15c79793bb 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/holder/WalletSummaryHolder.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/holder/WalletSummaryHolder.java @@ -12,6 +12,7 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -26,11 +27,13 @@ import com.alphawallet.app.ui.widget.entity.AvatarWriteCallback; import com.alphawallet.app.ui.widget.entity.WalletClickCallback; import com.alphawallet.app.util.Utils; +import com.alphawallet.app.widget.TokensBalanceView; import com.alphawallet.app.widget.UserAvatar; import java.math.BigDecimal; import java.math.RoundingMode; +import io.reactivex.disposables.Disposable; import io.realm.Realm; import io.realm.RealmResults; @@ -45,21 +48,23 @@ public class WalletSummaryHolder extends BinderViewHolder implements Vie private final ImageView defaultWalletIndicator; private final ImageView manageWalletBtn; private final UserAvatar walletIcon; - private final LinearLayout walletClickLayout; + private final RelativeLayout arrowRight; private final TextView walletBalanceText; private final TextView walletNameText; private final TextView walletAddressSeparator; private final TextView walletAddressText; private final TextView wallet24hChange; + private final TokensBalanceView tokensBalanceView; private final Realm realm; private RealmResults realmUpdate; - private final WalletClickCallback clickCallback; private Wallet wallet = null; + protected Disposable disposable; public WalletSummaryHolder(int resId, ViewGroup parent, WalletClickCallback callback, Realm realm) { super(resId, parent); + defaultWalletIndicator = findViewById(R.id.image_default_indicator); manageWalletBtn = findViewById(R.id.manage_wallet_btn); walletIcon = findViewById(R.id.wallet_icon); @@ -67,8 +72,9 @@ public WalletSummaryHolder(int resId, ViewGroup parent, WalletClickCallback call walletNameText = findViewById(R.id.wallet_name); walletAddressSeparator = findViewById(R.id.wallet_address_separator); walletAddressText = findViewById(R.id.wallet_address); - walletClickLayout = findViewById(R.id.wallet_click_layer); + arrowRight = findViewById(R.id.container); wallet24hChange = findViewById(R.id.wallet_24h_change); + tokensBalanceView = findViewById(R.id.token_with_balance_view); clickCallback = callback; manageWalletLayout = findViewById(R.id.layout_manage_wallet); this.realm = realm; @@ -82,8 +88,9 @@ public void bind(@Nullable Wallet data, @NonNull Bundle addition) if (data != null) { + tokensBalanceView.blankView(); wallet = fetchWallet(data); - walletClickLayout.setOnClickListener(this); + arrowRight.setOnClickListener(this); manageWalletLayout.setOnClickListener(this); if (addition.getBoolean(IS_DEFAULT_ADDITION, false)) @@ -141,7 +148,7 @@ else if (wallet.ENSname != null && wallet.ENSname.length() > 0) double oldFiatValue = addition.getDouble(FIAT_CHANGE, 0.00); String balanceTxt = TickerService.getCurrencyString(fiatValue); - + walletBalanceText.setVisibility(View.VISIBLE); walletBalanceText.setText(balanceTxt); setWalletChange(fiatValue != 0 ? ((fiatValue - oldFiatValue) / oldFiatValue) * 100.0 : 0.0); } @@ -183,7 +190,8 @@ private void startRealmListener() { realmUpdate = realm.where(RealmWalletData.class) .equalTo("address", wallet.address).findAllAsync(); - realmUpdate.addChangeListener(realmWallets -> { + realmUpdate.addChangeListener(realmWallets -> + { //update balance if (realmWallets.size() == 0) return; RealmWalletData realmWallet = realmWallets.first(); @@ -211,15 +219,18 @@ private Wallet fetchWallet(Wallet w) RealmWalletData realmWallet = realm.where(RealmWalletData.class) .equalTo("address", w.address) .findFirst(); - if (realmWallet != null) { w.balance = realmWallet.getBalance(); w.ENSname = realmWallet.getENSName(); w.name = realmWallet.getName(); w.ENSAvatar = realmWallet.getENSAvatar(); - } + if (w.tokens != null) + { + tokensBalanceView.bindTokens(w.tokens); + } + } return w; } @@ -264,7 +275,7 @@ public void onClick(View view) //if (wallet == null) { return; } //protect against click between constructor and bind switch (view.getId()) { - case R.id.wallet_click_layer: + case R.id.container: clickCallback.onWalletClicked(wallet); break; diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java index cfca2455a5..b63b939ed6 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletsViewModel.java @@ -19,6 +19,8 @@ import com.alphawallet.app.entity.SyncCallback; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletType; +import com.alphawallet.app.entity.tokendata.TokenUpdateType; +import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.interact.FetchWalletsInteract; import com.alphawallet.app.interact.FindDefaultNetworkInteract; import com.alphawallet.app.interact.GenericWalletInteract; @@ -55,10 +57,7 @@ @HiltViewModel public class WalletsViewModel extends BaseViewModel implements ServiceSyncCallback { - private final static String TAG = WalletsViewModel.class.getSimpleName(); - - private static final int BALANCE_CHECK_INTERVAL_SECONDS = 20; - + private static final int BALANCE_CHECK_INTERVAL_SECONDS = 30; private final SetDefaultWalletInteract setDefaultWalletInteract; private final FetchWalletsInteract fetchWalletsInteract; private final GenericWalletInteract genericWalletInteract; @@ -80,6 +79,7 @@ public class WalletsViewModel extends BaseViewModel implements ServiceSyncCallba private final MutableLiveData createdWallet = new MutableLiveData<>(); private final MutableLiveData createWalletError = new MutableLiveData<>(); private final MutableLiveData noWalletsError = new MutableLiveData<>(); + private final MutableLiveData> baseTokens = new MutableLiveData<>(); private NetworkInfo currentNetwork; private final Map walletBalances = new HashMap<>(); @@ -154,6 +154,7 @@ public LiveData createWalletError() return createWalletError; } public LiveData noWalletsError() { return noWalletsError; } + public LiveData> baseTokens() { return baseTokens; } public void setDefaultWallet(Wallet wallet, boolean isNewWallet) { @@ -176,7 +177,6 @@ private void startWalletUpdate() walletBalances.clear(); progress.postValue(true); - disposable = genericWalletInteract .find() .subscribe(this::onDefaultWallet, @@ -326,7 +326,10 @@ private void updateNextWallet() if (nextWalletToCheck != null) { Wallet w = walletUpdate.get(nextWalletToCheck); - currentWalletUpdates.put(nextWalletToCheck, startWalletSyncProcess(w)); + if (w != null) + { + currentWalletUpdates.put(nextWalletToCheck, startWalletSyncProcess(w)); + } } } @@ -367,6 +370,10 @@ public void newWallet(Activity ctx, CreateWalletCallbackInterface createCallback private void startBalanceUpdateTimer(final Wallet[] wallets) { if (balanceTimerDisposable != null && !balanceTimerDisposable.isDisposed()) balanceTimerDisposable.dispose(); + if (!tokensService.isMainNetActive()) + { + updateAllWallets(wallets, TokenUpdateType.STORED); //initially show values from database, start update 1 second later + } balanceTimerDisposable = Observable.interval(1, BALANCE_CHECK_INTERVAL_SECONDS, TimeUnit.SECONDS) //initial delay 1 second to allow view to stabilise .doOnNext(l -> getWalletsBalance(wallets)).subscribe(); @@ -379,16 +386,42 @@ private void startBalanceUpdateTimer(final Wallet[] wallets) */ private void getWalletsBalance(Wallet[] wallets) { - //loop through wallets and update balance - disposable = Observable.fromArray(wallets) - .forEach(wallet -> walletBalanceUpdate = tokensService.getChainBalance(wallet.address.toLowerCase(), currentNetwork.chainId) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(newBalance -> genericWalletInteract.updateBalanceIfRequired(wallet, newBalance), e -> { })); - + if (tokensService.isMainNetActive()) + { + //loop through wallets and update balance + disposable = Observable.fromArray(wallets) + .forEach(wallet -> walletBalanceUpdate = tokensService.getChainBalance(wallet.address.toLowerCase(), currentNetwork.chainId) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(newBalance -> genericWalletInteract.updateBalanceIfRequired(wallet, newBalance), e -> {})); + } + else + { + //Testnet Mode, need to update chain balances for visible chains + updateAllWallets(wallets, TokenUpdateType.ACTIVE_SYNC); + } progress.postValue(false); } + private void updateAllWallets(Wallet[] wallets, TokenUpdateType updateType) + { + disposable = Single.fromCallable(() -> { + //fetch all wallets in one go + Map walletTokenMap = new HashMap<>(); + for (Wallet wallet : wallets) + { + Token[] walletTokens = tokensService.syncChainBalances(wallet.address.toLowerCase(), updateType).blockingGet(); + if (walletTokens.length > 0) + { + walletTokenMap.put(walletTokens[0].getWallet(), walletTokens); + } + } + return walletTokenMap; + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(baseTokens::postValue, e -> {}); + } + @Override public void onCleared() { diff --git a/app/src/main/java/com/alphawallet/app/widget/TokensBalanceView.java b/app/src/main/java/com/alphawallet/app/widget/TokensBalanceView.java new file mode 100644 index 0000000000..110666343e --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/widget/TokensBalanceView.java @@ -0,0 +1,36 @@ +package com.alphawallet.app.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.LinearLayout; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; +import com.alphawallet.app.R; +import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.ui.widget.adapter.TestNetHorizontalListAdapter; + + +public class TokensBalanceView extends LinearLayout +{ + RecyclerView horizontalListView; + + public TokensBalanceView(Context context, @Nullable AttributeSet attrs) + { + super(context, attrs); + inflate(context, R.layout.item_token_with_balance_view, this); + horizontalListView = findViewById(R.id.horizontal_list); + } + + public void bindTokens(Token[] token) + { + TestNetHorizontalListAdapter testNetHorizontalListAdapter = new TestNetHorizontalListAdapter(token, getContext()); + horizontalListView.setAdapter(testNetHorizontalListAdapter); + } + + public void blankView() + { + //clear adapter + bindTokens(new Token[0]); + } +} + diff --git a/app/src/main/res/layout/activity_transaction_detail.xml b/app/src/main/res/layout/activity_transaction_detail.xml index 4f44f371d2..963af1df85 100644 --- a/app/src/main/res/layout/activity_transaction_detail.xml +++ b/app/src/main/res/layout/activity_transaction_detail.xml @@ -359,11 +359,11 @@ android:id="@+id/layout_1559" android:layout_width="match_parent" android:layout_height="wrap_content" - android:baselineAligned="false" android:layout_marginTop="6dp" + android:baselineAligned="false" + android:orientation="horizontal" android:visibility="gone" - tools:visibility="visible" - android:orientation="horizontal"> + tools:visibility="visible"> @@ -422,9 +422,9 @@ tools:text="1.2" /> diff --git a/app/src/main/res/layout/item_horizontal_testnet_list.xml b/app/src/main/res/layout/item_horizontal_testnet_list.xml new file mode 100644 index 0000000000..d85ec1aaf5 --- /dev/null +++ b/app/src/main/res/layout/item_horizontal_testnet_list.xml @@ -0,0 +1,24 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_token_with_balance_view.xml b/app/src/main/res/layout/item_token_with_balance_view.xml new file mode 100644 index 0000000000..5c92f3cd30 --- /dev/null +++ b/app/src/main/res/layout/item_token_with_balance_view.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_wallet_summary_manage.xml b/app/src/main/res/layout/item_wallet_summary_manage.xml index 96823362e3..e15a9c081f 100644 --- a/app/src/main/res/layout/item_wallet_summary_manage.xml +++ b/app/src/main/res/layout/item_wallet_summary_manage.xml @@ -29,6 +29,7 @@ android:layout_height="@dimen/tiny_8" android:layout_marginStart="@dimen/mini_4" android:src="@drawable/ic_wallet_indicator" + tools:ignore="ContentDescription" android:visibility="invisible" /> @@ -62,7 +63,8 @@ + android:layout_height="wrap_content" + android:orientation="horizontal"> @@ -87,11 +90,23 @@ android:lines="1" android:textColor="@color/positive" android:textIsSelectable="true" + android:visibility="gone" app:autoSizeTextType="uniform" tools:text="+123.45%" /> + + + + + + + android:text="@string/vertical_pipe" /> - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bf29fe9c54..012b7a61bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -985,6 +985,7 @@ Locked Key type in Database Key Entry in Secure Enclave + | ETH 0 diff --git a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapterTest.java b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapterTest.java deleted file mode 100644 index 32471143aa..0000000000 --- a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/WalletsSummaryAdapterTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.alphawallet.app.ui.widget.adapter; - -import static com.alphawallet.app.entity.WalletFactory.createHDKeyWallet; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.doNothing; -import static org.powermock.api.mockito.PowerMockito.doReturn; - -import android.content.Context; - -import androidx.recyclerview.widget.RecyclerView; - -import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.interact.GenericWalletInteract; -import com.alphawallet.app.repository.WalletRepository; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.Arrays; - -@RunWith(PowerMockRunner.class) -@PrepareForTest(RecyclerView.Adapter.class) -public class WalletsSummaryAdapterTest -{ - @Mock - private WalletRepository walletRepository; - - @Mock - private Context context; - - @InjectMocks - private GenericWalletInteract genericWalletInteract; - - private WalletsSummaryAdapter adapter; - - @Before - public void setUp() throws Exception - { - doReturn("Summary").when(context).getString(anyInt()); - WalletsSummaryAdapter raw = new WalletsSummaryAdapter(context, null, genericWalletInteract, false); - adapter = PowerMockito.spy(raw); - doNothing().when(adapter).notifyDataSetChanged(); - } - - @Test - public void should_get_default_wallet_index() - { - Wallet[] wallets = Arrays.asList(createHDKeyWallet("0x1"), createHDKeyWallet("0x2")).toArray(new Wallet[] {}); - adapter.setWallets(wallets); - adapter.setDefaultWallet(createHDKeyWallet("0x2")); - - int index = adapter.getDefaultWalletIndex() - 3; // There are 3 title labels added as Wallet - - assertThat(index, equalTo(1)); - } - - @Test - public void test_getDefaultWalletIndex_should_get_negative_one_when_no_default_wallet() - { - Wallet[] wallets = Arrays.asList(createHDKeyWallet("0x1"), createHDKeyWallet("0x2")).toArray(new Wallet[] {}); - adapter.setWallets(wallets); - - int index = adapter.getDefaultWalletIndex(); - - assertThat(index, equalTo(-1)); - } - -} \ No newline at end of file From 5995e1bae1f53349542e2b302167f6ad281e6117 Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 20 Sep 2022 10:35:27 +1000 Subject: [PATCH 096/183] Temporarily remove codecov fail --- .github/workflows/ci.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0aab75e294..98f4530435 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,8 +27,9 @@ jobs: name: ut-reports path: app/build/reports/tests - - name: Upload coverage reports to Codecov - run: | - curl -Os https://uploader.codecov.io/latest/macos/codecov - chmod +x codecov - ./codecov \ No newline at end of file +# Temporarily remove codecov tests; should not fail, only warn +# - name: Upload coverage reports to Codecov +# run: | +# curl -Os https://uploader.codecov.io/latest/macos/codecov +# chmod +x codecov +# ./codecov \ No newline at end of file From 883014b590b9e78685c6ded2173b5197f92df103 Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 20 Sep 2022 10:36:04 +1000 Subject: [PATCH 097/183] Add ERC721Enumerable handling (#2827) * Add ERC721Enumerable handling --- .../alphawallet/app/entity/ContractType.java | 1 + .../app/entity/nftassets/NFTAsset.java | 3 +- .../app/entity/tokens/ERC721Token.java | 72 +++++++++++++++++++ .../alphawallet/app/entity/tokens/Token.java | 6 +- .../app/entity/tokens/TokenFactory.java | 3 + .../app/repository/TokenRepository.java | 9 ++- .../app/repository/TokensRealmSource.java | 3 + .../alphawallet/app/service/GasService.java | 1 + .../ui/widget/adapter/NFTAssetsAdapter.java | 1 + .../app/viewmodel/WalletViewModel.java | 1 + 10 files changed, 93 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/ContractType.java b/app/src/main/java/com/alphawallet/app/entity/ContractType.java index 8db5c00fd0..178077e490 100644 --- a/app/src/main/java/com/alphawallet/app/entity/ContractType.java +++ b/app/src/main/java/com/alphawallet/app/entity/ContractType.java @@ -25,5 +25,6 @@ public enum ContractType ETHEREUM_INVISIBLE, MAYBE_ERC20, ERC1155, + ERC721_ENUMERABLE, CREATION //Placeholder for generic, should be at end of list } diff --git a/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java b/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java index b461cb184a..02a969d771 100644 --- a/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java +++ b/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java @@ -81,7 +81,8 @@ public NFTAsset(String metaData) public NFTAsset(RealmNFTAsset realmAsset) { - loadFromMetaData(realmAsset.getMetaData()); + String metaData = realmAsset.getMetaData() != null ? realmAsset.getMetaData() : new NFTAsset(new BigInteger(realmAsset.getTokenId())).jsonMetaData(); + loadFromMetaData(metaData); balance = realmAsset.getBalance(); } diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java index 6a3ad167cc..d56bca4f51 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java @@ -1,5 +1,6 @@ package com.alphawallet.app.entity.tokens; +import static com.alphawallet.app.repository.TokensRealmSource.databaseKey; import static com.alphawallet.app.util.Utils.parseTokenId; import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; import static org.web3j.tx.Contract.staticExtractEventParameters; @@ -53,7 +54,9 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import io.realm.Case; import io.realm.Realm; +import io.realm.RealmResults; import timber.log.Timber; /** @@ -340,11 +343,19 @@ public BigDecimal updateBalance(Realm realm) try { final Web3j web3j = TokenRepository.getWeb3jService(tokenInfo.chainId); + if (contractType == ContractType.ERC721_ENUMERABLE) + { + updateEnumerableBalance(web3j, realm); + } + Pair, HashSet>> evRead = eventSync.processTransferEvents(web3j, getTransferEvents(), startBlock, endBlock, realm); eventSync.updateEventReads(realm, sync, currentBlock, evRead.first); //means our event read was fine + //No need to go any further if this is enumerable + if (contractType == ContractType.ERC721_ENUMERABLE) return balance; + HashSet allMovingTokens = new HashSet<>(evRead.second.first); allMovingTokens.addAll(evRead.second.second); @@ -373,6 +384,26 @@ public BigDecimal updateBalance(Realm realm) return balance; } + /*********** + * For ERC721Enumerable interface + **********/ + private void updateEnumerableBalance(Web3j web3j, Realm realm) + { + HashSet tokenIdsHeld = new HashSet<>(); + //get enumerable balance + //find tokenIds held + long currentBalance = balance != null ? balance.longValue() : 0; + for (long tokenIndex = 0; tokenIndex < currentBalance; tokenIndex++) + { + // find tokenId from index + String tokenId = callSmartContractFunction(web3j, tokenOfOwnerByIndex(BigInteger.valueOf(tokenIndex)), getAddress(), getWallet()); + if (tokenId == null) continue; + tokenIdsHeld.add(new BigInteger(tokenId)); + } + + updateRealmForEnumerable(realm, tokenIdsHeld); + } + private void updateRealmBalance(Realm realm, Set tokenIds, Set allMovingTokens) { boolean updated = false; @@ -419,6 +450,40 @@ private void removeRealmBalance(Realm realm, HashSet removedTokens) }); } + private void updateRealmForEnumerable(Realm realm, HashSet currentTokens) + { + HashSet storedBalance = new HashSet<>(); + RealmResults results = realm.where(RealmNFTAsset.class) + .like("tokenIdAddr", databaseKey(this) + "-*", Case.INSENSITIVE) + .findAll(); + + for (RealmNFTAsset t : results) + { + storedBalance.add(new BigInteger(t.getTokenId())); + } + + if (!currentTokens.equals(storedBalance)) + { + realm.executeTransaction(r -> { + results.deleteAllFromRealm(); + for (BigInteger tokenId : currentTokens) + { + String key = RealmNFTAsset.databaseKey(this, tokenId); + RealmNFTAsset realmAsset = realm.where(RealmNFTAsset.class) + .equalTo("tokenIdAddr", key) + .findFirst(); + + if (realmAsset == null) + { + realmAsset = r.createObject(RealmNFTAsset.class, key); //create asset in realm + realmAsset.setMetaData(new NFTAsset(tokenId).jsonMetaData()); + r.insertOrUpdate(realmAsset); + } + } + }); + } + } + private void updateRealmBalances(Realm realm, Set tokenIds) { if (realm == null) return; @@ -700,6 +765,13 @@ private static Function ownerOf(BigInteger token) })); } + private Function tokenOfOwnerByIndex(BigInteger index) + { + return new Function("tokenOfOwnerByIndex", + Arrays.asList(new Address(getWallet()), new Uint256(index)), + Collections.singletonList(new TypeReference() {})); + } + @Override public List getStandardFunctions() { diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java index b5c2666648..65cad77860 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java @@ -2,8 +2,6 @@ import static android.text.Html.FROM_HTML_MODE_COMPACT; -import static androidx.core.content.ContextCompat.getColorStateList; - import android.app.Activity; import android.content.Context; import android.os.Build; @@ -11,7 +9,6 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Pair; -import android.view.View; import com.alphawallet.app.R; import com.alphawallet.app.entity.ContractInteract; @@ -23,7 +20,6 @@ import com.alphawallet.app.entity.nftassets.NFTAsset; import com.alphawallet.app.entity.opensea.AssetContract; import com.alphawallet.app.entity.tokendata.TokenGroup; -import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.EventResult; import com.alphawallet.app.repository.entity.RealmToken; @@ -53,7 +49,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -852,6 +847,7 @@ public boolean needsTransactionCheck() case OTHER: case NOT_SET: case ERC721: + case ERC721_ENUMERABLE: case ERC721_LEGACY: case ERC721_UNDETERMINED: case CREATION: diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/TokenFactory.java b/app/src/main/java/com/alphawallet/app/entity/tokens/TokenFactory.java index b367ac04f5..ad437a4f6a 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/TokenFactory.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/TokenFactory.java @@ -34,6 +34,7 @@ public Token createToken(TokenInfo tokenInfo, BigDecimal balance, List checkInterface(Token[] tokens, Wallet wallet) case ERC1155: break; case ERC721: + case ERC721_ENUMERABLE: case ERC721_LEGACY: Map NFTBalance = t.getTokenAssets(); //add balance from Opensea t.balance = checkUint256Balance(wallet, tInfo.chainId, tInfo.address); //get balance for wallet from contract @@ -383,6 +385,7 @@ public Single update(String contractAddr, long chainId, ContractType switch (type) { case ERC721: + case ERC721_ENUMERABLE: case ERC875_LEGACY: case ERC721_LEGACY: case ERC721_UNDETERMINED: @@ -429,6 +432,7 @@ private Single updateBalance(final Wallet wallet, final Token token) break; case ERC721_LEGACY: case ERC721: + case ERC721_ENUMERABLE: balance = updateERC721Balance(token, wallet); break; case ERC20: @@ -477,12 +481,13 @@ private Single updateBalance(final Wallet wallet, final Token token) private BigDecimal updateERC721Balance(Token token, Wallet wallet) { token.setTokenWallet(wallet.address); + token.balance = checkUint256Balance(wallet, token.tokenInfo.chainId, token.getAddress()); try (Realm realm = getRealmInstance(wallet)) { token.updateBalance(realm); } - return checkUint256Balance(wallet, token.tokenInfo.chainId, token.getAddress()); + return token.balance; } private BigDecimal updateERC1155Balance(Token token, Wallet wallet) @@ -1139,6 +1144,8 @@ public Single determineCommonType(TokenInfo tokenInfo) { if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_BALANCES_721_TICKET), Boolean.TRUE)) returnType = ContractType.ERC721_TICKET; + else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_ERC721_ENUMERABLE), Boolean.TRUE)) + returnType = ContractType.ERC721_ENUMERABLE; else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_OFFICIAL_ERC721), Boolean.TRUE)) returnType = ContractType.ERC721; else if (getContractData(network, tokenInfo.address, supportsInterface(INTERFACE_SUPERRARE), Boolean.TRUE)) diff --git a/app/src/main/java/com/alphawallet/app/repository/TokensRealmSource.java b/app/src/main/java/com/alphawallet/app/repository/TokensRealmSource.java index c5885374d1..d8c78b8ccc 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokensRealmSource.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokensRealmSource.java @@ -174,6 +174,7 @@ private void saveTokenLocal(Realm r, Token token) case MAYBE_ERC20: case ERC721: case ERC721_LEGACY: + case ERC721_ENUMERABLE: case ERC1155: saveToken(r, token); break; @@ -1367,6 +1368,7 @@ public static String convertStringBalance(String balance, ContractType type) case ERC721_UNDETERMINED: case ERC721: case ERC721_LEGACY: + case ERC721_ENUMERABLE: case ERC1155: default: return balance; @@ -1573,6 +1575,7 @@ public TokenGroup getTokenGroup(long chainId, String address, ContractType type) return tg; case ERC721: + case ERC721_ENUMERABLE: case ERC875_LEGACY: case ERC875: case ERC1155: diff --git a/app/src/main/java/com/alphawallet/app/service/GasService.java b/app/src/main/java/com/alphawallet/app/service/GasService.java index 9cd9d142c0..e4f6d03e55 100644 --- a/app/src/main/java/com/alphawallet/app/service/GasService.java +++ b/app/src/main/java/com/alphawallet/app/service/GasService.java @@ -454,6 +454,7 @@ public static BigInteger getDefaultGasLimit(Token token, Web3Transaction tx) case ERC721_LEGACY: case ERC721_TICKET: case ERC721_UNDETERMINED: + case ERC721_ENUMERABLE: return new BigInteger(DEFAULT_GAS_LIMIT_FOR_NONFUNGIBLE_TOKENS); default: //unknown diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java index 0b89d2d424..0db182b9fd 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java @@ -56,6 +56,7 @@ public NFTAssetsAdapter(Activity activity, Token token, OnAssetClickListener lis case ERC721_LEGACY: case ERC721_TICKET: case ERC721_UNDETERMINED: + case ERC721_ENUMERABLE: for (BigInteger i : token.getUniqueTokenIds()) { NFTAsset asset = token.getAssetForToken(i); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java index cfd0aba601..848e236d89 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java @@ -307,6 +307,7 @@ public void showTokenDetail(Activity activity, Token token) case ERC721_LEGACY: case ERC721_TICKET: case ERC721_UNDETERMINED: + case ERC721_ENUMERABLE: tokenDetailRouter.open(activity, token, defaultWallet.getValue(), false); //TODO: Fold this into tokenDetailRouter break; From 3cd16728590a2d761255b5e86197dc71a3dc5bea Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 20 Sep 2022 10:36:28 +1000 Subject: [PATCH 098/183] - Show NFT syncing if required (#2826) - Fix for NFTs not appearing if added manually --- app/build.gradle | 10 +++--- app/src/main/java/com/alphawallet/app/C.java | 2 ++ .../com/alphawallet/app/entity/EventSync.java | 5 +++ .../app/entity/tokens/ERC721Token.java | 11 ++++-- .../alphawallet/app/entity/tokens/Token.java | 2 +- .../com/alphawallet/app/ui/NFTActivity.java | 27 ++++++++++++++ .../app/ui/NFTAssetDetailActivity.java | 1 + .../alphawallet/app/ui/NFTAssetsFragment.java | 24 +++++++++---- .../RedeemSignatureDisplayModel.java | 25 +++++++------ .../app/widget/CertifiedToolbarView.java | 17 +++++++-- .../res/drawable/progress_bar_spinner2.xml | 22 ++++++++++++ .../res/layout/layout_certified_toolbar.xml | 36 +++++++++++-------- build.gradle | 4 +-- 13 files changed, 140 insertions(+), 46 deletions(-) create mode 100644 app/src/main/res/drawable/progress_bar_spinner2.xml diff --git a/app/build.gradle b/app/build.gradle index 46ced40d1e..38be46d0f6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -258,7 +258,7 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' //noinspection GradleDependency,GradleCompatible implementation 'androidx.appcompat:appcompat:1.3.1' //Do not update; next version is incompatible with API30 and below - implementation 'com.google.android.material:material:1.5.0' + implementation 'com.google.android.material:material:1.6.1' implementation 'androidx.vectordrawable:vectordrawable:1.1.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.biometric:biometric:1.1.0' @@ -269,7 +269,7 @@ dependencies { implementation 'com.google.zxing:core:3.4.1' // Sugar - implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.github.apl-devs:appintro:v4.2.2' implementation 'com.github.romandanylyk:PageIndicatorView:v1.0.0' @@ -292,7 +292,7 @@ dependencies { annotationProcessor "com.google.dagger:hilt-compiler:2.40.5" // WebKit - for WebView Dark Mode - implementation 'androidx.webkit:webkit:1.4.0' + implementation 'androidx.webkit:webkit:1.5.0' //Use Leak Canary for debug builds only //debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7' @@ -350,9 +350,9 @@ dependencies { //Analytics analyticsImplementation 'com.google.android.play:core:1.10.3' - analyticsImplementation 'com.google.firebase:firebase-analytics:20.1.2' + analyticsImplementation 'com.google.firebase:firebase-analytics:21.1.1' analyticsImplementation 'com.mixpanel.android:mixpanel-android:5.8.4' - analyticsImplementation 'com.google.firebase:firebase-crashlytics:18.2.9' + analyticsImplementation 'com.google.firebase:firebase-crashlytics:18.2.13' } // WARNING WARNING WARNING diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 1961f6c311..2806a072af 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -208,6 +208,8 @@ public abstract class C { public static final String SETTINGS_INSTANTIATED = "com.stormbird.wallet.SETTINGS_INSTANTIATED"; public static final String APP_FOREGROUND_STATE = "com.alphawallet.APP_FOREGROUND_STATE"; public static final String EXTRA_APP_FOREGROUND = "com.alphawallet.IS_FOREGORUND"; + public static final String SIGNAL_NFT_SYNC = "com.alphawallet.SYNC_NFT"; + public static final String SYNC_STATUS = "com.alphawallet.SYNC_STATUS"; public static final String DEFAULT_GAS_PRICE = "10000000000"; public static final String DEFAULT_XDAI_GAS_PRICE = "1000000000"; diff --git a/app/src/main/java/com/alphawallet/app/entity/EventSync.java b/app/src/main/java/com/alphawallet/app/entity/EventSync.java index 6482a02580..1d600a7617 100644 --- a/app/src/main/java/com/alphawallet/app/entity/EventSync.java +++ b/app/src/main/java/com/alphawallet/app/entity/EventSync.java @@ -310,6 +310,11 @@ public void updateEventReads(Realm realm, SyncDef sync, BigInteger currentBlock, updateEventReads(realm, sync.eventReadEndBlock.longValue(), calcNewIntervalSize(sync, evReads), sync.state); } + public void resetEventReads(Realm realm) + { + updateEventReads(realm, 0, 0, EventSyncState.DOWNWARD_SYNC_START); + } + private void updateEventReads(Realm realm, long lastRead, long readInterval, EventSyncState state) { if (realm == null) return; diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java index d56bca4f51..64e5c934b2 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java @@ -381,6 +381,13 @@ public BigDecimal updateBalance(Realm realm) Timber.w(e); } + //check for possible issues + if (endBlock == DefaultBlockParameterName.LATEST && balance.compareTo(BigDecimal.valueOf(tokenBalanceAssets.size())) != 0) + { + //possible mismatch, scan from beginning again + eventSync.resetEventReads(realm); + } + return balance; } @@ -534,7 +541,7 @@ private HashSet checkBalances(Web3j web3j, HashSet event for (BigInteger tokenId : eventIds) { String owner = callSmartContractFunction(web3j, ownerOf(tokenId), getAddress(), getWallet()); - if (owner == null || owner.toLowerCase().equals(getWallet())) + if (owner == null || owner.equalsIgnoreCase(getWallet())) { heldTokens.add(tokenId); } @@ -689,7 +696,7 @@ public Map queryAssets(Map assetMap) { checkAsset.setBalance(BigDecimal.ONE); } - else if (owner.toLowerCase().equals(getWallet())) + else if (owner.equalsIgnoreCase(getWallet())) { checkAsset.setBalance(BigDecimal.ONE); } diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java index 65cad77860..5eacc601a2 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java @@ -387,7 +387,7 @@ public boolean isBad() public void setTokenWallet(String address) { - this.tokenWallet = address; + this.tokenWallet = address.toLowerCase(Locale.ROOT); } public void setupRealmToken(RealmToken realmToken) diff --git a/app/src/main/java/com/alphawallet/app/ui/NFTActivity.java b/app/src/main/java/com/alphawallet/app/ui/NFTActivity.java index cb359bdd31..08be5959c1 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTActivity.java @@ -1,6 +1,8 @@ package com.alphawallet.app.ui; import static com.alphawallet.app.C.Key.WALLET; +import static com.alphawallet.app.C.SIGNAL_NFT_SYNC; +import static com.alphawallet.app.C.SYNC_STATUS; import android.content.Intent; import android.os.Bundle; @@ -86,9 +88,27 @@ protected void onCreate(@Nullable Bundle savedInstanceState) setupViewPager(); //check NFT events, expedite balance update + syncListener(); viewModel.checkEventsForToken(token); } + private void syncListener() + { + getSupportFragmentManager() + .setFragmentResultListener(SIGNAL_NFT_SYNC, this, (requestKey, b) -> + { + CertifiedToolbarView certificateToolbar = findViewById(R.id.certified_toolbar); + if (!b.getBoolean(SYNC_STATUS, false)) + { + certificateToolbar.nftSyncComplete(); + } + else + { + certificateToolbar.showNFTSync(); + } + }); + } + private boolean hasTokenScriptOverride(Token t) { return viewModel.getAssetDefinitionService().hasTokenView(t.tokenInfo.chainId, t.getAddress(), AssetDefinitionService.ASSET_SUMMARY_VIEW_NAME); @@ -199,6 +219,13 @@ private void setupViewPager() setupTabs(viewPager, pages); } + @Override + public void onResume() + { + super.onResume(); + if (assetsFragment == null) recreate(); + } + private void setupTabs(ViewPager2 viewPager, List> pages) { TabLayout tabLayout = findViewById(R.id.tab_layout); 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 5b411f2220..ea55e0c0c0 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java @@ -484,6 +484,7 @@ public void handleTokenScriptFunction(String function, List selectio { //does the function have a view? If it's transaction only then handle here Map functions = viewModel.getAssetDefinitionService().getTokenFunctionMap(token.tokenInfo.chainId, token.getAddress()); + if (functions == null) return; TSAction action = functions.get(function); token.clearResultMap(); diff --git a/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java index ba72bd56f1..145b653daa 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java @@ -2,6 +2,8 @@ import static android.app.Activity.RESULT_OK; +import static com.alphawallet.app.C.SIGNAL_NFT_SYNC; +import static com.alphawallet.app.C.SYNC_STATUS; import android.content.Intent; import android.os.Bundle; @@ -98,7 +100,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat searchLayout = view.findViewById(R.id.layout_search_tokens); - gridItemDecoration = new ItemOffsetDecoration(recyclerView.getContext(), R.dimen.grid_divider_offset); + gridItemDecoration = new ItemOffsetDecoration(requireContext(), R.dimen.grid_divider_offset); if (hasTokenScriptOverride(token)) { @@ -116,18 +118,18 @@ public void onAssetClicked(Pair item) { if (item.second.isCollection()) { - handleTransactionSuccess.launch(viewModel.showAssetListDetails(getContext(), wallet, token, item.second)); + handleTransactionSuccess.launch(viewModel.showAssetListDetails(requireContext(), wallet, token, item.second)); } else { - handleTransactionSuccess.launch(viewModel.showAssetDetails(getContext(), wallet, token, item.first)); + handleTransactionSuccess.launch(viewModel.showAssetDetails(requireContext(), wallet, token, item.first)); } } @Override public void onTokenClick(View view, Token token, List tokenIds, boolean selected) { - handleTransactionSuccess.launch(viewModel.showAssetDetails(getContext(), wallet, token, tokenIds.get(0))); + handleTransactionSuccess.launch(viewModel.showAssetDetails(requireContext(), wallet, token, tokenIds.get(0))); } @Override @@ -143,15 +145,15 @@ public void updateToken(Token newToken) public void showGridView() { - recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2)); + recyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); recyclerView.addItemDecoration(gridItemDecoration); - recyclerView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.surface)); + recyclerView.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.surface)); initAndAttachAdapter(true); } public void showListView() { - recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); recyclerView.removeItemDecoration(gridItemDecoration); recyclerView.setPadding(0, 0, 0, 0); initAndAttachAdapter(false); @@ -172,6 +174,14 @@ private void initAndAttachAdapter(boolean isGridView) } recyclerView.setAdapter(adapter); + checkSyncStatus(); + } + + private void checkSyncStatus() + { + Bundle result = new Bundle(); + result.putBoolean(SYNC_STATUS, token.getTokenCount() != token.getTokenAssets().size()); + getParentFragmentManager().setFragmentResult(SIGNAL_NFT_SYNC, result); } private boolean hasTokenScriptOverride(Token t) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/RedeemSignatureDisplayModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/RedeemSignatureDisplayModel.java index 0c02ad2755..6653443b1b 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/RedeemSignatureDisplayModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/RedeemSignatureDisplayModel.java @@ -1,27 +1,30 @@ package com.alphawallet.app.viewmodel; import android.app.Activity; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; - import android.os.NetworkOnMainThreadException; + import androidx.annotation.Nullable; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import com.alphawallet.app.entity.MessagePair; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.SignaturePair; -import com.alphawallet.app.entity.tokens.Ticket; -import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.TransferFromEventResponse; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.tokens.Ticket; +import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.interact.CreateTransactionInteract; import com.alphawallet.app.interact.FetchTokensInteract; import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.interact.MemPoolInteract; import com.alphawallet.app.interact.SignatureGenerateInteract; - +import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.KeyService; +import com.alphawallet.app.service.TokensService; +import com.alphawallet.token.entity.TicketRange; + import org.web3j.abi.datatypes.generated.Uint16; import org.web3j.utils.Numeric; @@ -30,6 +33,8 @@ import java.util.List; import java.util.concurrent.TimeUnit; +import javax.inject.Inject; + import dagger.hilt.android.lifecycle.HiltViewModel; import io.reactivex.Observable; import io.reactivex.Single; @@ -37,12 +42,6 @@ import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -import com.alphawallet.app.service.TokensService; -import com.alphawallet.token.entity.TicketRange; -import com.alphawallet.app.service.AssetDefinitionService; - -import javax.inject.Inject; - /** * Created by James on 25/01/2018. */ @@ -171,7 +170,7 @@ private void onToken(Token token) { this.token = token; - if (token != null && token.tokenInfo.address.equals(address) && token.hasArrayBalance()) + if (token != null && token.tokenInfo.address.equalsIgnoreCase(address) && token.hasArrayBalance()) { boolean allBurned = true; List balance = token.getArrayBalance(); diff --git a/app/src/main/java/com/alphawallet/app/widget/CertifiedToolbarView.java b/app/src/main/java/com/alphawallet/app/widget/CertifiedToolbarView.java index f48eb5a960..1bcadfd09c 100644 --- a/app/src/main/java/com/alphawallet/app/widget/CertifiedToolbarView.java +++ b/app/src/main/java/com/alphawallet/app/widget/CertifiedToolbarView.java @@ -2,15 +2,16 @@ import android.app.Activity; import android.content.Context; -import androidx.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; import android.widget.ProgressBar; +import androidx.annotation.Nullable; + +import com.alphawallet.app.R; import com.alphawallet.token.entity.SigReturnType; import com.alphawallet.token.entity.XMLDsigDescriptor; -import com.alphawallet.app.R; import com.google.android.material.appbar.MaterialToolbar; public class CertifiedToolbarView extends MaterialToolbar @@ -18,6 +19,7 @@ public class CertifiedToolbarView extends MaterialToolbar private Activity activity; private AWalletAlertDialog dialog; private final ProgressBar downloadSpinner; + private final ProgressBar syncSpinner; private int lockResource = 0; public CertifiedToolbarView(Context ctx, @Nullable AttributeSet attrs) @@ -25,6 +27,7 @@ public CertifiedToolbarView(Context ctx, @Nullable AttributeSet attrs) super(ctx, attrs); inflate(ctx, R.layout.layout_certified_toolbar, this); downloadSpinner = findViewById(R.id.cert_progress_spinner); + syncSpinner = findViewById(R.id.nft_scan_spinner); } public void onSigData(final XMLDsigDescriptor sigData, final Activity act) @@ -124,4 +127,14 @@ public void stopDownload() { downloadSpinner.setVisibility(View.GONE); } + + public void showNFTSync() + { + syncSpinner.setVisibility(View.VISIBLE); + } + + public void nftSyncComplete() + { + syncSpinner.setVisibility(View.GONE); + } } diff --git a/app/src/main/res/drawable/progress_bar_spinner2.xml b/app/src/main/res/drawable/progress_bar_spinner2.xml new file mode 100644 index 0000000000..944108bffc --- /dev/null +++ b/app/src/main/res/drawable/progress_bar_spinner2.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_certified_toolbar.xml b/app/src/main/res/layout/layout_certified_toolbar.xml index 9249580204..41298e2dcb 100644 --- a/app/src/main/res/layout/layout_certified_toolbar.xml +++ b/app/src/main/res/layout/layout_certified_toolbar.xml @@ -9,21 +9,29 @@ android:layout_width="wrap_content" android:layout_height="wrap_content"> - + - + + + diff --git a/build.gradle b/build.gradle index 47a88def1d..0d5e7e6736 100644 --- a/build.gradle +++ b/build.gradle @@ -13,13 +13,13 @@ buildscript { classpath 'com.android.tools.build:gradle:7.0.3' //NB - there is an issue with newer versions of gradle. The APK balloons out, so far haven't diagnosed why. //If you want to try upgrading gradle plugin past 3.5.4 you will need to also diagnose the APK ballooning issue. - classpath "io.realm:realm-gradle-plugin:10.8.0" + classpath "io.realm:realm-gradle-plugin:10.11.1" // WARNING WARNING WARNING // you are about to add here a dependency to be used in the Android app // don't do that. add that dependency to app/build.gradle classpath 'com.google.gms:google-services:4.3.10' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2' classpath 'com.google.dagger:hilt-android-gradle-plugin:2.40.5' } } From 2685e0b82100d163999851e5b2b39ca993d6e04b Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 20 Sep 2022 11:12:59 +1000 Subject: [PATCH 099/183] Ensure MetaMask addresses are handled correctly (#2829) --- .../com/alphawallet/app/entity/QRResult.java | 9 ++++++++- .../alphawallet/app/entity/tokens/Token.java | 1 + .../com/alphawallet/app/QRExtractorTest.java | 18 +++++++++++------- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/QRResult.java b/app/src/main/java/com/alphawallet/app/entity/QRResult.java index 59b8a94039..50c3f6ed38 100644 --- a/app/src/main/java/com/alphawallet/app/entity/QRResult.java +++ b/app/src/main/java/com/alphawallet/app/entity/QRResult.java @@ -2,7 +2,9 @@ import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.Nullable; + +import com.alphawallet.app.util.Utils; + import java.math.BigDecimal; import java.math.BigInteger; import java.util.List; @@ -161,6 +163,11 @@ else if (params.size() == 2) { type = EIP681Type.OTHER_PROTOCOL; } + else if (isEIP681() && Utils.isAddressValid(address)) //Metamask addresses + { + type = EIP681Type.ADDRESS; + return; + } else { type = EIP681Type.OTHER; diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java index 5eacc601a2..f0164cde88 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java @@ -49,6 +49,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; diff --git a/app/src/test/java/com/alphawallet/app/QRExtractorTest.java b/app/src/test/java/com/alphawallet/app/QRExtractorTest.java index ce78fa35d2..4f90725f53 100644 --- a/app/src/test/java/com/alphawallet/app/QRExtractorTest.java +++ b/app/src/test/java/com/alphawallet/app/QRExtractorTest.java @@ -1,5 +1,10 @@ package com.alphawallet.app; +import static com.alphawallet.app.entity.EIP681Type.OTHER; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.EIP681Type; import com.alphawallet.app.entity.QRResult; @@ -16,12 +21,6 @@ import java.util.Base64; import java.util.Map; -import static org.mockito.Mockito.when; - -import static com.alphawallet.app.entity.EIP681Type.OTHER; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyString; - /** * Example local unit test, which will execute on the development machine (host). * @@ -155,9 +154,14 @@ public byte[] Base64Encode(byte[] data) result = parser.parse("ethereum:0x0000000000000000000000000000000000000XyZ"); assertTrue("ethereum".equals(result.getProtocol())); assertTrue("0x0000000000000000000000000000000000000XyZ".equals(result.getAddress())); - assertTrue(result.getFunction().length() == 0); + // No params, valid address eg MetaMask format + result = parser.parse("ethereum:0x82357f25AD0db74D2e4Cc1a2Ae2803d88B178112"); + assertTrue("ethereum".equals(result.getProtocol())); + assertTrue("0x82357f25AD0db74D2e4Cc1a2Ae2803d88B178112".equals(result.getAddress())); + assertTrue(result.type == EIP681Type.ADDRESS); + // No parameters result = parser.parse("ethereum:0x0000000000000000000000000000000000000XyZ?"); assertTrue("ethereum".equals(result.getProtocol())); From 2896aedfd5cf66dca5b5d323b1f9b1f48f95b574 Mon Sep 17 00:00:00 2001 From: James Brown Date: Wed, 21 Sep 2022 11:24:24 +1000 Subject: [PATCH 100/183] Refactor HomeActivity Fragment Handling (#2834) Refactor Fragment handling --- app/src/main/cpp/keys.c | 6 - .../app/entity/BackupTokenCallback.java | 4 +- .../alphawallet/app/ui/ActivityFragment.java | 7 +- .../com/alphawallet/app/ui/BaseFragment.java | 33 ++++- .../app/ui/DappBrowserFragment.java | 16 ++- .../com/alphawallet/app/ui/HomeActivity.java | 118 ++++++------------ .../app/ui/NewSettingsFragment.java | 5 +- .../app/ui/WalletConnectActivity.java | 8 +- .../alphawallet/app/ui/WalletFragment.java | 9 +- .../ui/widget/holder/TestNetTipsHolder.java | 1 - 10 files changed, 98 insertions(+), 109 deletions(-) diff --git a/app/src/main/cpp/keys.c b/app/src/main/cpp/keys.c index 739761e4aa..8b29b00be5 100644 --- a/app/src/main/cpp/keys.c +++ b/app/src/main/cpp/keys.c @@ -182,9 +182,3 @@ Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getOpenSeaKey( JNIEnv* en return (*env)->NewStringUTF(env, key); #endif } - -JNIEXPORT jstring JNICALL -Java_com_alphawallet_app_util_AWEnsResolver_getOpenSeaKey( JNIEnv* env, jclass thiz ) -{ - return Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getOpenSeaKey(env, thiz); -} \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/entity/BackupTokenCallback.java b/app/src/main/java/com/alphawallet/app/entity/BackupTokenCallback.java index ddca0a6d04..b317a545b6 100644 --- a/app/src/main/java/com/alphawallet/app/entity/BackupTokenCallback.java +++ b/app/src/main/java/com/alphawallet/app/entity/BackupTokenCallback.java @@ -6,6 +6,6 @@ */ public interface BackupTokenCallback { - void backUpClick(Wallet wallet); - void remindMeLater(Wallet wallet); + default void backUpClick(Wallet wallet) { } + default void remindMeLater(Wallet wallet) { }; } diff --git a/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java b/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java index caf5682bae..471e41666a 100644 --- a/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java @@ -21,7 +21,6 @@ import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.TransactionMeta; import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.entity.WalletPage; import com.alphawallet.app.interact.ActivityDataInteract; import com.alphawallet.app.repository.entity.RealmTransaction; import com.alphawallet.app.repository.entity.RealmTransfer; @@ -221,6 +220,7 @@ private void refreshTransactionList() viewModel.prepare(); } + @Override public void resetTokens() { if (adapter != null) @@ -231,6 +231,7 @@ public void resetTokens() } } + @Override public void addedToken(List tokenContracts) { if (adapter != null) adapter.updateItems(tokenContracts); @@ -252,7 +253,7 @@ public void onResume() super.onResume(); if (viewModel == null) { - ((HomeActivity) getActivity()).resetFragment(WalletPage.ACTIVITY); + requireActivity().recreate(); } else { @@ -298,12 +299,14 @@ public void leaveFocus() if (realm != null && !realm.isClosed()) realm.close(); } + @Override public void resetTransactions() { //called when we just refreshed the database refreshTransactionList(); } + @Override public void scrollToTop() { if (listView != null) listView.smoothScrollToPosition(0); diff --git a/app/src/main/java/com/alphawallet/app/ui/BaseFragment.java b/app/src/main/java/com/alphawallet/app/ui/BaseFragment.java index ba903731d8..0cdee524b1 100644 --- a/app/src/main/java/com/alphawallet/app/ui/BaseFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/BaseFragment.java @@ -1,17 +1,28 @@ package com.alphawallet.app.ui; -import androidx.fragment.app.Fragment; -import androidx.appcompat.widget.Toolbar; +import android.content.Intent; import android.view.MenuItem; import android.view.View; import android.widget.TextView; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; + import com.alphawallet.app.R; +import com.alphawallet.app.entity.BackupTokenCallback; +import com.alphawallet.app.entity.ContractLocator; +import com.alphawallet.app.entity.FragmentMessenger; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint -public class BaseFragment extends Fragment implements Toolbar.OnMenuItemClickListener { +public class BaseFragment extends Fragment implements Toolbar.OnMenuItemClickListener, + BackupTokenCallback +{ private Toolbar toolbar; private TextView toolbarTitle; @@ -86,4 +97,20 @@ public void leaveFocus() public void softKeyboardVisible() { } public void softKeyboardGone() { } + public void onItemClick(String url) { } + public void signalUpdate(int updateVersion) { } + public void backupSeedSuccess(boolean hasNoLock) { } + public void storeWalletBackupTime(String backedUpKey) { } + public void resetTokens() { } + public void resetTransactions() { } + public void gotCameraAccess(@NotNull String[] permissions, int[] grantResults) { } + public void gotGeoAccess(@NotNull String[] permissions, int[] grantResults) { } + public void gotFileAccess(@NotNull String[] permissions, int[] grantResults) { } + public void handleQRCode(int resultCode, Intent data, FragmentMessenger messenger) { } + public void pinAuthorisation(boolean gotAuth) { } + public void switchNetworkAndLoadUrl(long chainId, String url) { } + public void scrollToTop() { } + public void addedToken(List tokenContracts) { } + public void setImportFilename(String fName) { } + public void backPressed() { } } diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index 5e22e39c7f..c3e7497efa 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -79,7 +79,6 @@ import com.alphawallet.app.entity.URLLoadInterface; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletConnectActions; -import com.alphawallet.app.entity.WalletPage; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.EthereumNetworkRepository; @@ -315,9 +314,10 @@ public void onResume() homePressed = false; if (currentFragment == null) currentFragment = DAPP_BROWSER; attachFragment(currentFragment); - if ((web3 == null || viewModel == null) && getActivity() != null) //trigger reload + if ((web3 == null || viewModel == null)) //trigger reload { - ((HomeActivity) getActivity()).resetFragment(WalletPage.DAPP_BROWSER); + //reboot + requireActivity().recreate(); } else { @@ -898,6 +898,7 @@ private void onDefaultWallet(Wallet wallet) } } + @Override public void switchNetworkAndLoadUrl(long chainId, String url) { forceChainChange = chainId; //avoid prompt to change chain for 1inch @@ -1487,6 +1488,7 @@ else if (transaction.payload == null && transaction.value == null) resultDialog.show(); } + @Override public void backPressed() { if (web3 == null || back == null || back.getAlpha() == 0.3f) return; @@ -1706,8 +1708,7 @@ public void loadDirect(String urlText) { if (web3 == null) { - if (getActivity() != null) - ((HomeActivity) getActivity()).resetFragment(WalletPage.DAPP_BROWSER); + requireActivity().recreate(); loadOnInit = urlText; } else @@ -1775,6 +1776,7 @@ private void resetDappBrowser() setUrlText(getDefaultDappUrl()); } + @Override public void handleQRCode(int resultCode, Intent data, FragmentMessenger messenger) { //result @@ -1945,6 +1947,7 @@ private void requestCameraPermission(@NotNull PermissionRequest request) } } + @Override public void gotCameraAccess(@NotNull String[] permissions, int[] grantResults) { boolean cameraAccess = false; @@ -1961,6 +1964,7 @@ public void gotCameraAccess(@NotNull String[] permissions, int[] grantResults) Toast.makeText(getContext(), "Permission not given", Toast.LENGTH_SHORT).show(); } + @Override public void gotGeoAccess(@NotNull String[] permissions, int[] grantResults) { boolean geoAccess = false; @@ -1978,6 +1982,7 @@ public void gotGeoAccess(@NotNull String[] permissions, int[] grantResults) geoCallback.invoke(geoOrigin, geoAccess, false); } + @Override public void gotFileAccess(@NotNull String[] permissions, int[] grantResults) { boolean fileAccess = false; @@ -2129,6 +2134,7 @@ public void gotAuthorisationForSigning(boolean gotAuth, Signable messageToSign) * * @param gotAuth */ + @Override public void pinAuthorisation(boolean gotAuth) { if (confirmationDialog != null && confirmationDialog.isShowing()) diff --git a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java index 88dbc77ed5..81e9fb3041 100644 --- a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java @@ -118,10 +118,6 @@ public class HomeActivity extends BaseNavigationActivity implements View.OnClick private LinearLayout successOverlay; private ImageView successImage; private HomeReceiver homeReceiver; - private Fragment settingsFragment; - private Fragment dappBrowserFragment; - private Fragment walletFragment; - private Fragment activityFragment; private String walletTitle; private TutoShowcase backupWalletDialog; private boolean isForeground; @@ -357,7 +353,7 @@ private void setupFragmentListeners() List contractList = b.getParcelableArrayList(ADDED_TOKEN); if (contractList != null) { - ((ActivityFragment) getFragment(ACTIVITY)).addedToken(contractList); + getFragment(ACTIVITY).addedToken(contractList); } }); @@ -493,15 +489,7 @@ private void onWalletName(String name) walletTitle = getString(R.string.toolbar_header_wallet); } - // putting in a try catch to avoid crashing the app - try - { - getFragment(WALLET).setToolbarTitle(walletTitle); - } - catch (Exception e) - { - Timber.e(e); - } + getFragment(WALLET).setToolbarTitle(walletTitle); } private void onError(ErrorEnvelope errorEnvelope) @@ -605,7 +593,7 @@ public boolean onBottomNavigationItemSelected(WalletPage index) public void onBrowserWithURL(String url) { showPage(DAPP_BROWSER); - ((DappBrowserFragment) getFragment(DAPP_BROWSER)).onItemClick(url); + getFragment(DAPP_BROWSER).onItemClick(url); } @Override @@ -725,7 +713,7 @@ public void updateReady(int updateVersion) { //signal to WalletFragment an update is ready //display entry in the WalletView - ((NewSettingsFragment) getFragment(SETTINGS)).signalUpdate(updateVersion); + getFragment(SETTINGS).signalUpdate(updateVersion); } @Override @@ -753,18 +741,18 @@ public void tokenScriptError(String message) void backupWalletFail(String keyBackup, boolean hasNoLock) { //postpone backup until later - ((NewSettingsFragment) getFragment(SETTINGS)).backupSeedSuccess(hasNoLock); + getFragment(SETTINGS).backupSeedSuccess(hasNoLock); if (keyBackup != null) { - ((WalletFragment) getFragment(WALLET)).remindMeLater(new Wallet(keyBackup)); + getFragment(WALLET).remindMeLater(new Wallet(keyBackup)); viewModel.checkIsBackedUp(keyBackup); } } void backupWalletSuccess(String keyBackup) { - ((NewSettingsFragment) getFragment(SETTINGS)).backupSeedSuccess(false); - ((WalletFragment) getFragment(WALLET)).storeWalletBackupTime(keyBackup); + getFragment(SETTINGS).backupSeedSuccess(false); + getFragment(WALLET).storeWalletBackupTime(keyBackup); removeSettingsBadgeKey(C.KEY_NEEDS_BACKUP); if (successImage != null) successImage.setImageResource(R.drawable.big_green_tick); if (successOverlay != null) successOverlay.setVisibility(View.VISIBLE); @@ -805,24 +793,6 @@ public void createdKey(String keyAddress) //viewModel.upgradeWallet(keyAddress); } - /** - * On restarting the wallet, all fragments check they have their viewModels - * If they do not, then the onResume override will call this resetFragment method for that fragment - * Which rebuilds the view and repopulates all the view members required for operation - * - * @param fragmentId - */ - public void resetFragment(WalletPage fragmentId) - { - Fragment fragment = getFragment(fragmentId); - - getSupportFragmentManager() - .beginTransaction() - .detach(fragment) - .attach(fragment) - .commitAllowingStateLoss(); - } - @Override public void loadingComplete() { @@ -853,23 +823,16 @@ else if (lastId >= 0 && lastId < WalletPage.values().length) private BaseFragment getFragment(WalletPage page) { - //build map, return correct fragment. - if (getSupportFragmentManager().getFragments().size() < page.ordinal()) + // if fragment hasn't been created yet, return a blank BaseFragment to avoid crash + if ((page.ordinal() + 1) > getSupportFragmentManager().getFragments().size()) { - switch (page) - { - default: - case WALLET: - return (BaseFragment) walletFragment; - case ACTIVITY: - return (BaseFragment) activityFragment; - case DAPP_BROWSER: - return (BaseFragment) dappBrowserFragment; - case SETTINGS: - return (BaseFragment) settingsFragment; - } + recreate(); //restart activity required + return new BaseFragment(); + } + else + { + return (BaseFragment) getSupportFragmentManager().getFragments().get(page.ordinal()); } - else return (BaseFragment) getSupportFragmentManager().getFragments().get(page.ordinal()); } @Override @@ -887,14 +850,14 @@ public void backupSuccess(String keyAddress) @Override public void resetTokens() { - ((ActivityFragment) getFragment(ACTIVITY)).resetTokens(); - ((WalletFragment) getFragment(WALLET)).resetTokens(); + getFragment(ACTIVITY).resetTokens(); + getFragment(WALLET).resetTokens(); } @Override public void resetTransactions() { - ((ActivityFragment) getFragment(ACTIVITY)).resetTransactions(); + getFragment(ACTIVITY).resetTransactions(); } @Override @@ -948,13 +911,13 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in switch (requestCode) { case DappBrowserFragment.REQUEST_CAMERA_ACCESS: - ((DappBrowserFragment) getFragment(DAPP_BROWSER)).gotCameraAccess(permissions, grantResults); + getFragment(DAPP_BROWSER).gotCameraAccess(permissions, grantResults); break; case DappBrowserFragment.REQUEST_FILE_ACCESS: - ((DappBrowserFragment) getFragment(DAPP_BROWSER)).gotFileAccess(permissions, grantResults); + getFragment(DAPP_BROWSER).gotFileAccess(permissions, grantResults); break; case DappBrowserFragment.REQUEST_FINE_LOCATION: - ((DappBrowserFragment) getFragment(DAPP_BROWSER)).gotGeoAccess(permissions, grantResults); + getFragment(DAPP_BROWSER).gotGeoAccess(permissions, grantResults); break; case RC_ASSET_EXTERNAL_WRITE_PERM: //Can't get here @@ -1000,7 +963,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) switch (requestCode) { case DAPP_BARCODE_READER_REQUEST_CODE: - ((DappBrowserFragment) getFragment(DAPP_BROWSER)).handleQRCode(resultCode, data, this); + getFragment(DAPP_BROWSER).handleQRCode(resultCode, data, this); break; case C.REQUEST_BACKUP_WALLET: String keyBackup = null; @@ -1014,7 +977,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) switch (getSelectedItem()) { case DAPP_BROWSER: - ((DappBrowserFragment) getFragment(DAPP_BROWSER)).pinAuthorisation(resultCode == RESULT_OK); + getFragment(DAPP_BROWSER).pinAuthorisation(resultCode == RESULT_OK); break; default: break; @@ -1042,7 +1005,7 @@ else if (data.hasExtra(C.EXTRA_ACTION_NAME)) case C.TOKEN_SEND_ACTIVITY: if (data != null && resultCode == Activity.RESULT_OK && data.hasExtra(C.DAPP_URL_LOAD)) { - ((DappBrowserFragment) getFragment(DAPP_BROWSER)).switchNetworkAndLoadUrl(data.getLongExtra(C.EXTRA_CHAIN_ID, MAINNET_ID), + getFragment(DAPP_BROWSER).switchNetworkAndLoadUrl(data.getLongExtra(C.EXTRA_CHAIN_ID, MAINNET_ID), data.getStringExtra(C.DAPP_URL_LOAD)); showPage(DAPP_BROWSER); } @@ -1054,7 +1017,7 @@ else if (data != null && resultCode == Activity.RESULT_OK && data.hasExtra(C.EXT case C.TERMINATE_ACTIVITY: if (data != null && resultCode == Activity.RESULT_OK) { - ((ActivityFragment) getFragment(ACTIVITY)).scrollToTop(); + getFragment(ACTIVITY).scrollToTop(); showPage(ACTIVITY); } break; @@ -1062,7 +1025,7 @@ else if (data != null && resultCode == Activity.RESULT_OK && data.hasExtra(C.EXT if (data != null && data.hasExtra(C.EXTRA_TOKENID_LIST)) { List tokenData = data.getParcelableArrayListExtra(C.EXTRA_TOKENID_LIST); - ((ActivityFragment) getFragment(ACTIVITY)).addedToken(tokenData); + getFragment(ACTIVITY).addedToken(tokenData); } break; default: @@ -1106,7 +1069,7 @@ public void onBackPressed() //Check if current page is WALLET or not if (viewPager.getCurrentItem() == DAPP_BROWSER.ordinal()) { - ((DappBrowserFragment) getFragment(DAPP_BROWSER)).backPressed(); + getFragment(DAPP_BROWSER).backPressed(); } else if (viewPager.getCurrentItem() != WALLET.ordinal() && isNavBarVisible()) { @@ -1148,7 +1111,7 @@ private void checkIntents(String importData, String importPath, Intent startInte { importData = importData.substring(NotificationService.AWSTARTUP.length()); //move window to token if found - ((WalletFragment) getFragment(WALLET)).setImportFilename(importData); + getFragment(WALLET).setImportFilename(importData); } else if (startIntent.getStringExtra("url") != null) { @@ -1218,7 +1181,7 @@ else if (importPath != null) } } - private class ScreenSlidePagerAdapter extends FragmentStateAdapter + private static class ScreenSlidePagerAdapter extends FragmentStateAdapter { public ScreenSlidePagerAdapter(@NonNull FragmentActivity fragmentActivity) { @@ -1233,18 +1196,20 @@ public Fragment createFragment(int position) { case WALLET: default: - walletFragment = new WalletFragment(); - return walletFragment; + return new WalletFragment(); case ACTIVITY: - activityFragment = new ActivityFragment(); - return activityFragment; + return new ActivityFragment(); case DAPP_BROWSER: - if (CustomViewSettings.hideDappBrowser()) dappBrowserFragment = new Fragment(); - else dappBrowserFragment = new DappBrowserFragment(); - return dappBrowserFragment; + if (CustomViewSettings.hideDappBrowser()) + { + return new BaseFragment(); + } + else + { + return new DappBrowserFragment(); + } case SETTINGS: - settingsFragment = new NewSettingsFragment(); - return settingsFragment; + return new NewSettingsFragment(); } } @@ -1253,6 +1218,5 @@ public int getItemCount() { return WalletPage.values().length; } - } } \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java index 322b2c2e8c..0c9bcd4e3a 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java @@ -39,7 +39,6 @@ import com.alphawallet.app.entity.BackupOperationType; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.entity.WalletPage; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.util.LocaleUtils; @@ -193,6 +192,7 @@ private void initNotificationView(View view) } } + @Override public void signalUpdate(int updateVersion) { //add wallet update signal to adapter @@ -476,7 +476,7 @@ public void onResume() super.onResume(); if (viewModel == null) { - ((HomeActivity) getActivity()).resetFragment(WalletPage.SETTINGS); + requireActivity().recreate(); } else { @@ -484,6 +484,7 @@ public void onResume() } } + @Override public void backupSeedSuccess(boolean hasNoLock) { if (viewModel != null) viewModel.TestWalletBackup(); diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java index 1c6244e40e..35cbf41159 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java @@ -89,7 +89,7 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa private static final String DEFAULT_IDON = "https://example.walletconnect.org/favicon.ico"; private static final long CONNECT_TIMEOUT = 10 * DateUtils.SECOND_IN_MILLIS; // 10 Seconds timeout private final Handler handler = new Handler(Looper.getMainLooper()); - private final LocalBroadcastManager broadcastManager; + private LocalBroadcastManager broadcastManager; private final long switchChainDialogCallbackId = 1; WalletConnectViewModel viewModel; private WCClient client; @@ -189,11 +189,6 @@ public void onReceive(Context context, Intent intent) } }; - public WalletConnectActivity() - { - broadcastManager = LocalBroadcastManager.getInstance(this); - } - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -590,6 +585,7 @@ private void startMessageCheck() filter.addAction(C.WALLET_CONNECT_CLIENT_TERMINATE); filter.addAction(C.WALLET_CONNECT_SWITCH_CHAIN); filter.addAction(C.WALLET_CONNECT_ADD_CHAIN); + if (broadcastManager == null) broadcastManager = LocalBroadcastManager.getInstance(this); broadcastManager.registerReceiver(walletConnectActionReceiver, filter); } diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java index 44faff12c1..9d9f946406 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java @@ -40,19 +40,16 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.entity.BackupOperationType; -import com.alphawallet.app.entity.BackupTokenCallback; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.ServiceSyncCallback; import com.alphawallet.app.entity.TokenFilter; import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.entity.WalletPage; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; import com.alphawallet.app.interact.GenericWalletInteract; -import com.alphawallet.app.repository.CoinbasePayRepository; import com.alphawallet.app.repository.TokensRealmSource; import com.alphawallet.app.repository.entity.RealmToken; import com.alphawallet.app.service.TickerService; @@ -95,7 +92,6 @@ public class WalletFragment extends BaseFragment implements TokensAdapterCallback, View.OnClickListener, Runnable, - BackupTokenCallback, AvatarWriteCallback, ServiceSyncCallback { @@ -541,7 +537,7 @@ public void onResume() selectedToken = null; if (viewModel == null) { - ((HomeActivity) getActivity()).resetFragment(WalletPage.WALLET); + requireActivity().recreate(); } else if (largeTitleView != null) { @@ -670,6 +666,7 @@ public void onDestroy() if (adapter != null && recyclerView != null) adapter.onDestroy(recyclerView); } + @Override public void resetTokens() { if (viewModel != null && adapter != null) @@ -727,6 +724,7 @@ public void remindMeLater(Wallet wallet) }); } + @Override public void storeWalletBackupTime(String backedUpKey) { handler.post(() -> @@ -736,6 +734,7 @@ public void storeWalletBackupTime(String backedUpKey) }); } + @Override public void setImportFilename(String fName) { importFileName = fName; diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/holder/TestNetTipsHolder.java b/app/src/main/java/com/alphawallet/app/ui/widget/holder/TestNetTipsHolder.java index 6c73899c47..18338a0231 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/holder/TestNetTipsHolder.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/holder/TestNetTipsHolder.java @@ -1,6 +1,5 @@ package com.alphawallet.app.ui.widget.holder; -import android.app.Dialog; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; From 8f1fac27795b61d13075006cb5f988649daaf627 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 21 Sep 2022 09:36:50 +0800 Subject: [PATCH 101/183] Add Lido.fi (#2833) --- app/src/main/assets/dapps_list.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/dapps_list.json b/app/src/main/assets/dapps_list.json index 4c139107da..c640482a17 100644 --- a/app/src/main/assets/dapps_list.json +++ b/app/src/main/assets/dapps_list.json @@ -89,5 +89,6 @@ {"name": "Swapzone", "description": "Swapzone is a custody-free cryptocurrency exchange aggregator with no registration needed.", "url": "https://swapzone.io/", "category": "Exchange"}, {"name": "mail³", "description": "Decentralized mail system for web3 natives.", "url": "https://app.mail3.me/", "category": "Social Media"}, {"name": "ApeNow", "description": "Buy now, pay later marketplace for NFTs.", "url": "https://www.apenowpaylater.com/", "category": "Marketplace"}, - {"name": "AirCash", "description": "AirCash is the first and largest decentralized OTC platform in the galaxy.", "url": "https://aircash.finance", "category": "Exchange"} + {"name": "AirCash", "description": "AirCash is the first and largest decentralized OTC platform in the galaxy.", "url": "https://aircash.finance", "category": "Exchange"}, + {"name": "Lido", "description": "Liquidity for staked assets", "url": "https://lido.fi/", "category": "Finance"} ] From b840ec82b6c2914f34b229ba0d678f433d7a4f5c Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Wed, 21 Sep 2022 16:58:01 +0800 Subject: [PATCH 102/183] Make coverage rate informational (#2838) --- .github/workflows/ci.yml | 11 +++++------ codecov.yml | 8 ++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 codecov.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98f4530435..0aab75e294 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,9 +27,8 @@ jobs: name: ut-reports path: app/build/reports/tests -# Temporarily remove codecov tests; should not fail, only warn -# - name: Upload coverage reports to Codecov -# run: | -# curl -Os https://uploader.codecov.io/latest/macos/codecov -# chmod +x codecov -# ./codecov \ No newline at end of file + - name: Upload coverage reports to Codecov + run: | + curl -Os https://uploader.codecov.io/latest/macos/codecov + chmod +x codecov + ./codecov \ No newline at end of file diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..a793f59195 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,8 @@ +coverage: + status: + project: + default: + informational: true + patch: + default: + informational: true \ No newline at end of file From 239510bf06abe8c9f9c5c3dc12b8bf289df980a5 Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 26 Sep 2022 15:18:18 +1000 Subject: [PATCH 103/183] Fix for payload being null in dapp/walletconnect transactions (#2845) --- .../app/entity/EIP1559FeeOracleResult.java | 7 ------- .../com/alphawallet/app/service/GasService.java | 10 +++++----- .../alphawallet/app/ui/DappBrowserFragment.java | 3 +-- .../com/alphawallet/app/ui/NFTAssetsFragment.java | 1 + .../alphawallet/app/ui/WalletConnectActivity.java | 4 +--- .../app/viewmodel/DappBrowserViewModel.java | 15 ++++++++++++--- .../app/viewmodel/WalletConnectViewModel.java | 13 ++++++++++--- .../app/web3/entity/Web3Transaction.java | 5 +++++ .../alphawallet/app/widget/ActionSheetDialog.java | 14 +++++++++++--- 9 files changed, 46 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/EIP1559FeeOracleResult.java b/app/src/main/java/com/alphawallet/app/entity/EIP1559FeeOracleResult.java index ba1a442fd6..29a9ccaaa6 100644 --- a/app/src/main/java/com/alphawallet/app/entity/EIP1559FeeOracleResult.java +++ b/app/src/main/java/com/alphawallet/app/entity/EIP1559FeeOracleResult.java @@ -8,8 +8,6 @@ import java.math.BigDecimal; import java.math.BigInteger; -import timber.log.Timber; - /** * Created by JB on 20/01/2022. */ @@ -79,11 +77,6 @@ private BigInteger fixGasPriceReturn(BigInteger input) { return BalanceUtils.gweiToWei(BigDecimal.ONE); } - else if (input.equals(BigInteger.ZERO)) - { - Timber.w("Zero gas price detected"); - return input; - } else { return input; diff --git a/app/src/main/java/com/alphawallet/app/service/GasService.java b/app/src/main/java/com/alphawallet/app/service/GasService.java index e4f6d03e55..eec82f2e70 100644 --- a/app/src/main/java/com/alphawallet/app/service/GasService.java +++ b/app/src/main/java/com/alphawallet/app/service/GasService.java @@ -151,7 +151,7 @@ private void fetchCurrentGasPrice() .map(result -> updateEIP1559Realm(result, currentChainId)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(r -> Timber.d(r ? "Updated Fees" : "Fail to update fees"), this::handleError).isDisposed(); + .subscribe(r -> { if (!r) Timber.d("Fail to update fees"); }, this::handleError).isDisposed(); } private Single useNodeFallback(Boolean updated) @@ -279,7 +279,7 @@ private Single updateEtherscanGasPrices(String gasOracleAPI) } catch (Exception e) { - Timber.e(e); + Timber.w(e); } return update; @@ -312,7 +312,7 @@ private void updateRealm(final GasPriceSpread oracleResult, final long chainId) private boolean updateEIP1559Realm(final Map result, final long chainId) { - boolean hasError = false; + boolean succeeded = true; try (Realm realm = realmManager.getRealmInstance(TICKER_DB)) { realm.executeTransaction(r -> { @@ -330,10 +330,10 @@ private boolean updateEIP1559Realm(final Map re } catch (Exception e) { - hasError = true; + succeeded = false; } - return hasError; + return succeeded; } public Single calculateGasEstimate(byte[] transactionBytes, long chainId, String toAddress, diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index c3e7497efa..74cbc04220 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -1387,8 +1387,7 @@ public void onSignTransaction(Web3Transaction transaction, String url) confirmationDialog.show(); confirmationDialog.fullExpand(); - viewModel.calculateGasEstimate(wallet, Numeric.hexStringToByteArray(transaction.payload), - activeNetwork.chainId, transaction.recipient.toString(), new BigDecimal(transaction.value), transaction.gasLimit) + viewModel.calculateGasEstimate(wallet, transaction, activeNetwork.chainId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(estimate -> confirmationDialog.setGasEstimate(estimate), diff --git a/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java index 145b653daa..09b02fb5f7 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java @@ -179,6 +179,7 @@ private void initAndAttachAdapter(boolean isGridView) private void checkSyncStatus() { + if (token == null || token.getTokenAssets() == null) return; Bundle result = new Bundle(); result.putBoolean(SYNC_STATUS, token.getTokenCount() != token.getTokenAssets().size()); getParentFragmentManager().setFragmentResult(SIGNAL_NFT_SYNC, result); diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java index 35cbf41159..be4b655737 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java @@ -69,7 +69,6 @@ import org.jetbrains.annotations.NotNull; import org.web3j.utils.Numeric; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.UUID; @@ -939,8 +938,7 @@ private ActionSheetDialog generateTransactionRequest(Web3Transaction w3Tx, long confDialog.setCanceledOnTouchOutside(false); confDialog.waitForEstimate(); - viewModel.calculateGasEstimate(viewModel.getWallet(), Numeric.hexStringToByteArray(w3Tx.payload), - chainId, w3Tx.recipient.toString(), new BigDecimal(w3Tx.value), w3Tx.gasLimit) + viewModel.calculateGasEstimate(viewModel.getWallet(), w3Tx, chainId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(confDialog::setGasEstimate, diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java index 84978da9ff..6b52a45fe8 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java @@ -43,7 +43,8 @@ import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.token.entity.Signable; -import java.math.BigDecimal; +import org.web3j.utils.Numeric; + import java.math.BigInteger; import java.util.List; import java.util.concurrent.TimeUnit; @@ -320,9 +321,17 @@ public TokensService getTokenService() return tokensService; } - public Single calculateGasEstimate(Wallet wallet, byte[] transactionBytes, long chainId, String sendAddress, BigDecimal sendAmount, BigInteger defaultGasLimit) + public Single calculateGasEstimate(Wallet wallet, Web3Transaction transaction, long chainId) { - return gasService.calculateGasEstimate(transactionBytes, chainId, sendAddress, sendAmount.toBigInteger(), wallet, defaultGasLimit); + if (transaction.isBaseTransfer()) + { + return Single.fromCallable(() -> BigInteger.valueOf(C.GAS_LIMIT_MIN)); + } + else + { + return gasService.calculateGasEstimate(Numeric.hexStringToByteArray(transaction.payload), chainId, + transaction.recipient.toString(), transaction.value, wallet, transaction.gasLimit); + } } public String getNetworkNodeRPC(long chainId) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java index d8bfff3d0e..89a4d7c82e 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java @@ -50,7 +50,6 @@ import com.alphawallet.token.entity.Signable; import com.alphawallet.token.tools.Numeric; -import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; @@ -249,9 +248,17 @@ public void sendTransaction(final Web3Transaction finalTx, long chainId, SendTra } } - public Single calculateGasEstimate(Wallet wallet, byte[] transactionBytes, long chainId, String sendAddress, BigDecimal sendAmount, BigInteger defaultLimit) + public Single calculateGasEstimate(Wallet wallet, Web3Transaction transaction, long chainId) { - return gasService.calculateGasEstimate(transactionBytes, chainId, sendAddress, sendAmount.toBigInteger(), wallet, defaultLimit); + if (transaction.isBaseTransfer()) + { + return Single.fromCallable(() -> BigInteger.valueOf(C.GAS_LIMIT_MIN)); + } + else + { + return gasService.calculateGasEstimate(org.web3j.utils.Numeric.hexStringToByteArray(transaction.payload), chainId, + transaction.recipient.toString(), transaction.value, wallet, transaction.gasLimit); + } } public void resetSignDialog() diff --git a/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java b/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java index 719430f7ee..68a046275b 100644 --- a/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java +++ b/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java @@ -234,6 +234,11 @@ public boolean isConstructor() return (recipient.equals(Address.EMPTY) && payload != null); } + public boolean isBaseTransfer() + { + return payload == null || payload.equals("0x"); + } + /** * Can be used anywhere to generate an 'instant' human readable transaction dump * @param ctx diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java index b0f057ae5d..d6a950eeaf 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java @@ -405,8 +405,8 @@ public void setURL(String url) { AddressDetailView requester = findViewById(R.id.requester); requester.setupRequester(url); - detailWidget.setupTransaction(candidateTransaction, token.tokenInfo.chainId, tokensService.getCurrentAddress(), - tokensService.getNetworkSymbol(token.tokenInfo.chainId), this); + setupTransactionDetails(); + if (candidateTransaction.isConstructor()) { addressDetail.setVisibility(View.GONE); @@ -427,7 +427,15 @@ private void setupTransactionDetails() { detailWidget.setupTransaction(candidateTransaction, token.tokenInfo.chainId, tokensService.getCurrentAddress(), tokensService.getNetworkSymbol(token.tokenInfo.chainId), this); - detailWidget.setVisibility(View.VISIBLE); + + if (candidateTransaction.isBaseTransfer()) + { + detailWidget.setVisibility(View.GONE); + } + else + { + detailWidget.setVisibility(View.VISIBLE); + } } public void setCurrentGasIndex(ActivityResult result) From a8a4cb6216e89ad847c0374de984d41d0f08bf90 Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 27 Sep 2022 22:10:08 +1000 Subject: [PATCH 104/183] Improve NFT display and syncing (#2846) --- .../app/entity/nftassets/NFTAsset.java | 5 +- .../app/entity/opensea/OpenSeaAsset.java | 24 +++ .../app/entity/tokens/ERC721Token.java | 26 +++- .../app/repository/EthereumNetworkBase.java | 4 +- .../app/ui/DappBrowserFragment.java | 29 ++-- .../com/alphawallet/app/ui/NFTActivity.java | 2 - .../java/com/alphawallet/app/util/Utils.java | 27 +++- .../app/viewmodel/TokenFunctionViewModel.java | 2 +- .../alphawallet/app/widget/NFTImageView.java | 144 +++++++++++++++--- .../main/res/drawable/masking_rectangle.xml | 22 +++ app/src/main/res/layout/item_asset_image.xml | 8 + app/src/main/res/raw/token_anim.data | 28 ++++ app/src/main/res/raw/token_model.data | 28 ++++ 13 files changed, 301 insertions(+), 48 deletions(-) create mode 100644 app/src/main/res/drawable/masking_rectangle.xml create mode 100644 app/src/main/res/raw/token_anim.data create mode 100644 app/src/main/res/raw/token_model.data diff --git a/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java b/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java index 02a969d771..30fa7cb5dd 100644 --- a/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java +++ b/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java @@ -170,10 +170,9 @@ public String getName() return assetMap.get(NAME); } - public boolean isAnimation() + public String getAnimation() { - String anim = assetMap.get(IMAGE_ANIMATION); - return anim != null; + return assetMap.get(IMAGE_ANIMATION); } public String getImage() diff --git a/app/src/main/java/com/alphawallet/app/entity/opensea/OpenSeaAsset.java b/app/src/main/java/com/alphawallet/app/entity/opensea/OpenSeaAsset.java index 9280fb2109..954e2fdb27 100644 --- a/app/src/main/java/com/alphawallet/app/entity/opensea/OpenSeaAsset.java +++ b/app/src/main/java/com/alphawallet/app/entity/opensea/OpenSeaAsset.java @@ -40,6 +40,10 @@ public class OpenSeaAsset @Expose public String animationUrl; + @SerializedName("animation_url") + @Expose + public String animation_url; + @SerializedName("name") @Expose public String name; @@ -323,6 +327,22 @@ else if (totalPrice.length() <= decimals) return result; } + public String getAnimationUrl() + { + if (animationUrl != null) + { + return animationUrl; + } + else if (animation_url != null) + { + return animation_url; + } + else + { + return null; + } + } + public String getImageUrl() { if (image != null) @@ -345,6 +365,10 @@ else if (imagePreviewUrl != null) { return imagePreviewUrl; } + else if (animation_url != null) + { + return animation_url; + } else { return ""; diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java index 64e5c934b2..780840a40a 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java @@ -16,6 +16,7 @@ import com.alphawallet.app.entity.TransactionInput; import com.alphawallet.app.entity.nftassets.NFTAsset; import com.alphawallet.app.entity.tokendata.TokenGroup; +import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EventResult; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.repository.entity.RealmNFTAsset; @@ -66,6 +67,7 @@ public class ERC721Token extends Token { private final Map tokenBalanceAssets; + private static final Map balanceChecks = new ConcurrentHashMap<>(); public ERC721Token(TokenInfo tokenInfo, Map balanceList, BigDecimal balance, long blancaTime, String networkName, ContractType type) { @@ -329,6 +331,11 @@ private Event getTransferEvents() @Override public BigDecimal updateBalance(Realm realm) { + if (balanceChecks.containsKey(tokenInfo.address)) + { + return balance; + } + //first get current block SyncDef sync = eventSync.getSyncDef(realm); if (sync == null) return balance; @@ -342,6 +349,7 @@ public BigDecimal updateBalance(Realm realm) try { + balanceChecks.put(tokenInfo.address, true); //set checking final Web3j web3j = TokenRepository.getWeb3jService(tokenInfo.chainId); if (contractType == ContractType.ERC721_ENUMERABLE) { @@ -351,7 +359,7 @@ public BigDecimal updateBalance(Realm realm) Pair, HashSet>> evRead = eventSync.processTransferEvents(web3j, getTransferEvents(), startBlock, endBlock, realm); - eventSync.updateEventReads(realm, sync, currentBlock, evRead.first); //means our event read was fine + eventSync.updateEventReads(realm, sync, currentBlock, evRead.first); //means our event read was fine //No need to go any further if this is enumerable if (contractType == ContractType.ERC721_ENUMERABLE) return balance; @@ -364,8 +372,12 @@ public BigDecimal updateBalance(Realm realm) allMovingTokens.addAll(tokenBalanceAssets.keySet()); } - HashSet tokenIdsHeld = checkBalances(web3j, allMovingTokens); - updateRealmBalance(realm, tokenIdsHeld, allMovingTokens); + //no need to check balances if this chain is supported by OpenSea + if (allMovingTokens.size() < 10 || !EthereumNetworkBase.hasOpenseaAPI(tokenInfo.chainId)) + { + HashSet tokenIdsHeld = checkBalances(web3j, allMovingTokens); + updateRealmBalance(realm, tokenIdsHeld, allMovingTokens); + } } catch (LogOverflowException e) { @@ -380,6 +392,10 @@ public BigDecimal updateBalance(Realm realm) { Timber.w(e); } + finally + { + balanceChecks.remove(tokenInfo.address); + } //check for possible issues if (endBlock == DefaultBlockParameterName.LATEST && balance.compareTo(BigDecimal.valueOf(tokenBalanceAssets.size())) != 0) @@ -753,6 +769,10 @@ private String callSmartContractFunction(Web3j web3j, { return responseValues.get(0).getValue().toString(); } + else if (response.hasError() && response.getError().getCode() == 3) //reverted + { + return ""; + } } catch (Exception e) { diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 1d92f0add0..ea325f21ff 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -316,11 +316,11 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(KLAYTN_ID, new NetworkInfo(C.KLAYTN_NAME, C.KLAYTN_SYMBOL, USE_KLAYTN_RPC, - "https://scope.klaytn.com/tx/", KLAYTN_ID, "", + "https://scope.klaytn.com/tx/", KLAYTN_ID, KLAYTN_RPC, "https://api.covalenthq.com/v1/" + COVALENT)); put(KLAYTN_BAOBAB_ID, new NetworkInfo(C.KLAYTN_BAOBAB_NAME, C.KLAYTN_SYMBOL, USE_KLAYTN_BAOBAB_RPC, - "https://baobab.scope.klaytn.com/tx/", KLAYTN_BAOBAB_ID, "", + "https://baobab.scope.klaytn.com/tx/", KLAYTN_BAOBAB_ID, KLAYTN_BAOBAB_RPC, "")); put(IOTEX_MAINNET_ID, new NetworkInfo(C.IOTEX_NAME, C.IOTEX_SYMBOL, IOTEX_MAINNET_RPC_URL, diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index 74cbc04220..df3471244d 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -1178,14 +1178,6 @@ protected boolean requestUpload() return true; } - public void setCurrentGasIndex(int gasSelectionIndex, BigDecimal customGasPrice, BigDecimal customGasLimit, long expectedTxTime, long customNonce) - { - /*if (confirmationDialog != null && confirmationDialog.isShowing()) - { - confirmationDialog.setCurrentGasIndex(gasSelectionIndex, customGasPrice, customGasLimit, expectedTxTime, customNonce); - }*/ - } - @Override public void onSignMessage(final EthereumMessage message) { @@ -2232,7 +2224,6 @@ private String determineMimeType(@NotNull WebChromeClient.FileChooserParams file } else { - //TODO: Resolve types switch (firstType) { case "png": @@ -2240,16 +2231,25 @@ private String determineMimeType(@NotNull WebChromeClient.FileChooserParams file case "svg": case "jpg": case "jpeg": - case "image/*": - mime = "image/*"; + case "bmp": + mime = "image/" + firstType; break; case "mp4": case "x-msvideo": case "x-ms-wmv": case "mpeg4-generic": + case "webm": + case "avi": + case "mpg": + case "m2v": + mime = "video/" + firstType; + break; + + case "image/*": + case "audio/*": case "video/*": - mime = "video/*"; + mime = firstType; break; case "mpeg": @@ -2258,8 +2258,7 @@ private String determineMimeType(@NotNull WebChromeClient.FileChooserParams file case "ogg": case "midi": case "x-ms-wma": - case "audio/*": - mime = "audio/*"; + mime = "audio/" + firstType; break; case "pdf": @@ -2268,7 +2267,7 @@ private String determineMimeType(@NotNull WebChromeClient.FileChooserParams file case "xml": case "csv": - mime = "text/*"; + mime = "text/" + firstType; break; default: diff --git a/app/src/main/java/com/alphawallet/app/ui/NFTActivity.java b/app/src/main/java/com/alphawallet/app/ui/NFTActivity.java index 08be5959c1..08cfa6517f 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTActivity.java @@ -235,8 +235,6 @@ private void setupTabs(ViewPager2 viewPager, List> pages) TabUtils.decorateTabLayout(this, tabLayout); -// viewPager.setCurrentItem(1, true); - tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index ced009f77d..169aeb9076 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -3,11 +3,11 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.AVALANCHE_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.CLASSIC_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import android.app.Activity; import android.content.Context; @@ -805,24 +805,41 @@ public static boolean isContractCall(Context context, String operationName) } private static final String IPFS_PREFIX = "ipfs://"; + private static final String IPFS_DESIGNATOR = "/ipfs/"; + private static final String IPFS_INFURA_RESOLVER = "https://alphawallet.infura-ipfs.io"; + private static final String IPFS_IO_RESOLVER = "https://ipfs.io"; + + public static boolean isIPFS(String url) + { + return url.contains(IPFS_DESIGNATOR) || url.startsWith(IPFS_PREFIX); + } public static String parseIPFS(String URL) { if (TextUtils.isEmpty(URL)) return URL; String parsed = URL; - int ipfsIndex = URL.lastIndexOf("/ipfs/"); + int ipfsIndex = URL.lastIndexOf(IPFS_DESIGNATOR); if (ipfsIndex >= 0) { - parsed = "https://alphawallet.infura-ipfs.io" + URL.substring(ipfsIndex); + parsed = IPFS_INFURA_RESOLVER + URL.substring(ipfsIndex); } else if (URL.startsWith(IPFS_PREFIX)) { - parsed = "https://alphawallet.infura-ipfs.io/ipfs/" + URL.substring(IPFS_PREFIX.length()); + parsed = IPFS_INFURA_RESOLVER + IPFS_DESIGNATOR + URL.substring(IPFS_PREFIX.length()); + } + else if (shouldBeIPFS(URL)) //have seen some NFTs designating only the IPFS hash + { + parsed = IPFS_INFURA_RESOLVER + IPFS_DESIGNATOR + URL; } return parsed; } + private static boolean shouldBeIPFS(String url) + { + return url.startsWith("Qm") && url.length() == 46 && !url.contains(".") && !url.contains("/"); + } + public static String loadFile(Context context, @RawRes int rawRes) { byte[] buffer = new byte[0]; try { 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 aabc6fb675..2bcbc4ea20 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java @@ -870,7 +870,7 @@ private void onAsset(String result, Token token, BigInteger tokenId) } else { - storeAsset(token, tokenId, new NFTAsset(result), oldAsset); + storeAsset(token, tokenId, asset, oldAsset); asset.attachOpenSeaAssetData(osAsset); nftAsset.postValue(asset); } diff --git a/app/src/main/java/com/alphawallet/app/widget/NFTImageView.java b/app/src/main/java/com/alphawallet/app/widget/NFTImageView.java index c306619edd..f5985c3926 100644 --- a/app/src/main/java/com/alphawallet/app/widget/NFTImageView.java +++ b/app/src/main/java/com/alphawallet/app/widget/NFTImageView.java @@ -3,6 +3,7 @@ import static com.alphawallet.app.util.Utils.loadFile; import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; @@ -13,9 +14,9 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.Base64; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.webkit.MimeTypeMap; import android.webkit.WebView; import android.widget.ImageView; import android.widget.ProgressBar; @@ -52,7 +53,9 @@ public class NFTImageView extends RelativeLayout private final RelativeLayout fallbackLayout; private final TokenIcon fallbackIcon; private final ProgressBar progressBar; + private final ImageView overlay; private final Handler handler = new Handler(Looper.getMainLooper()); + /** * Prevent glide dumping log errors - it is expected that load will fail */ @@ -65,7 +68,7 @@ public boolean onLoadFailed(@Nullable GlideException e, Object model, Target { + this.imageUrl = imageUrl; image.setVisibility(View.GONE); webLayout.setVisibility(View.VISIBLE); webView.setVisibility(View.VISIBLE); - webView.loadData(base64, "text/html; charset=utf-8", "base64"); + overlay.setVisibility(View.VISIBLE); + + if (useType.getImageType() == ImageType.WEB) + { + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); + webView.loadUrl(imageUrl); + } + else if (useType.getImageType() == ImageType.ANIM) + { + String loaderAnim = loadFile(getContext(), R.raw.token_anim).replace("[URL]", imageUrl).replace("[MIME]", useType.getMimeType()); + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); + webView.getSettings().setMediaPlaybackRequiresUserGesture(false); + String base64 = android.util.Base64.encodeToString(loaderAnim.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); + webView.loadData(base64, "text/html; charset=utf-8", "base64"); + } + else if (useType.getImageType() == ImageType.MODEL) + { + String loader = loadFile(getContext(), R.raw.token_model).replace("[URL]", imageUrl); + String base64 = android.util.Base64.encodeToString(loader.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); + webView.loadData(base64, "text/html; charset=utf-8", "base64"); + } + else + { + String loader = loadFile(getContext(), R.raw.token_graphic).replace("[URL]", imageUrl); + String base64 = android.util.Base64.encodeToString(loader.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); + webView.loadData(base64, "text/html; charset=utf-8", "base64"); + } }); } @@ -210,15 +253,9 @@ public boolean hasContent() return hasContent; } - public void showLoadingProgress(boolean showProgress) + public void showLoadingProgress() { - this.showProgress = showProgress; - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) - { - return true; + this.showProgress = true; } public boolean shouldLoad(String url) @@ -249,4 +286,77 @@ public boolean isDisplayingImage() { return !TextUtils.isEmpty(imageUrl); } + + private boolean isGlb(String url) + { + return (url != null && MimeTypeMap.getFileExtensionFromUrl(url).equals("glb")); + } + + private static class DisplayType + { + private final ImageType type; + private final String mimeStr; + + // Should handle most cases; this is a handler for anim or drop through cases, + // Previously these were not handled so this is a big improvement in display handling + public DisplayType(String url, ImageType hint) + { + if (url == null || url.length() < 5) + { + type = hint; + mimeStr = ""; + return; + } + + String extension = MimeTypeMap.getFileExtensionFromUrl(url); + + switch (extension) + { + case "": + mimeStr = ""; + if (hint == ImageType.IMAGE) + { + type = hint; + } + else + { + type = ImageType.WEB; + } + break; + case "mp4": + case "webm": + case "avi": + case "mpeg": + case "mpg": + case "m2v": + type = ImageType.ANIM; + mimeStr = "video/" + extension; + break; + case "bmp": + case "png": + case "jpg": + case "svg": + case "glb": //currently avoid handling these + default: + type = ImageType.IMAGE; + mimeStr = "image/" + extension; + break; + } + } + + public String getMimeType() + { + return mimeStr; + } + + public ImageType getImageType() + { + return type; + } + } + + private enum ImageType + { + IMAGE, ANIM, WEB, MODEL + } } diff --git a/app/src/main/res/drawable/masking_rectangle.xml b/app/src/main/res/drawable/masking_rectangle.xml new file mode 100644 index 0000000000..d5db0da32d --- /dev/null +++ b/app/src/main/res/drawable/masking_rectangle.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_asset_image.xml b/app/src/main/res/layout/item_asset_image.xml index 4d67d1eede..55384c05d0 100644 --- a/app/src/main/res/layout/item_asset_image.xml +++ b/app/src/main/res/layout/item_asset_image.xml @@ -46,6 +46,13 @@ android:src="@drawable/masking_circle" android:visibility="gone" /> + + + diff --git a/app/src/main/res/raw/token_anim.data b/app/src/main/res/raw/token_anim.data new file mode 100644 index 0000000000..4dce3e0bd9 --- /dev/null +++ b/app/src/main/res/raw/token_anim.data @@ -0,0 +1,28 @@ + + + + + +

+ +
+ + \ No newline at end of file diff --git a/app/src/main/res/raw/token_model.data b/app/src/main/res/raw/token_model.data new file mode 100644 index 0000000000..8ab106b939 --- /dev/null +++ b/app/src/main/res/raw/token_model.data @@ -0,0 +1,28 @@ + + + + + +
+ + +
+ + \ No newline at end of file From 278da3c8aa1e1c8cf1023dbe1319229563c77805 Mon Sep 17 00:00:00 2001 From: James Brown Date: Wed, 28 Sep 2022 08:29:24 +1000 Subject: [PATCH 105/183] Setup Phi v2 network (#2848) --- app/src/main/java/com/alphawallet/app/C.java | 1 + .../app/entity/ContractInteract.java | 4 +- .../app/repository/EthereumNetworkBase.java | 25 ++++++--- .../app/service/OpenSeaService.java | 12 ++++- .../app/service/TickerService.java | 51 ++++++++++++++++++- .../ethereum/EthereumNetworkBase.java | 9 ++-- 6 files changed, 85 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 2806a072af..8c39765503 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -58,6 +58,7 @@ public abstract class C { public static final String MILKOMEDA_NAME = "Milkomeda Cardano"; public static final String MILKOMEDA_TESTNET_NAME = "Milkomeda Cardano (Test)"; public static final String PHI_NETWORK_NAME = "PHI"; + public static final String PHI_V2_NETWORK_NAME = "PHI v2"; public static final String ETHEREUM_TICKER_NAME = "ethereum"; public static final String CLASSIC_TICKER_NAME = "ethereum-classic"; diff --git a/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java b/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java index 679a1b33ef..9bc532e363 100644 --- a/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java +++ b/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java @@ -113,8 +113,8 @@ private static void setupClient() if (client == null) { client = new OkHttpClient.Builder() - .connectTimeout(C.CONNECT_TIMEOUT, TimeUnit.SECONDS) - .connectTimeout(C.READ_TIMEOUT, TimeUnit.SECONDS) + .connectTimeout(C.CONNECT_TIMEOUT*4, TimeUnit.SECONDS) + .readTimeout(C.READ_TIMEOUT*4, TimeUnit.SECONDS) .writeTimeout(C.WRITE_TIMEOUT, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index ea325f21ff..6219475e05 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -33,6 +33,9 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_NETWORK_V2_RPC; +import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; @@ -43,7 +46,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_NETWORK_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; @@ -192,8 +194,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy //Then xDai would appear as the first token at the top of the wallet private static final List hasValue = new ArrayList<>(Arrays.asList( MAINNET_ID, GNOSIS_ID, POLYGON_ID, CLASSIC_ID, POA_ID, ARTIS_SIGMA1_ID, BINANCE_MAIN_ID, HECO_ID, AVALANCHE_ID, - FANTOM_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID, - PHI_NETWORK_MAIN_ID)); + FANTOM_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID, PHI_V2_MAIN_ID, + PHI_MAIN_ID)); // for reset built-in network private static final LongSparseArray builtinNetworkMap = new LongSparseArray() { @@ -345,10 +347,14 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy MILKOMEDA_C1_TEST_RPC, "https://explorer-devnet-cardano-evm.c1.milkomeda.com/tx/", MILKOMEDA_C1_TEST_ID, "", "https://explorer-devnet-cardano-evm.c1.milkomeda.com/api?")); - put(PHI_NETWORK_MAIN_ID, new NetworkInfo(C.PHI_NETWORK_NAME, C.PHI_NETWORK_SYMBOL, + put(PHI_MAIN_ID, new NetworkInfo(C.PHI_NETWORK_NAME, C.PHI_NETWORK_SYMBOL, PHI_NETWORK_RPC, - "https://explorer.phi.network/tx/", PHI_NETWORK_MAIN_ID, "https://rpc2.phi.network", + "https://explorer.phi.network/tx/", PHI_MAIN_ID, "https://rpc2.phi.network", "")); + put(PHI_V2_MAIN_ID, new NetworkInfo(C.PHI_V2_NETWORK_NAME, C.PHI_NETWORK_SYMBOL, + PHI_NETWORK_V2_RPC, + "https://phiscan.com/tx/", PHI_V2_MAIN_ID, "", + "https://phiscan.com/api?")); } }; @@ -395,7 +401,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(AURORA_TESTNET_ID, R.drawable.ic_aurora_test); put(MILKOMEDA_C1_ID, R.drawable.ic_milkomeda); put(MILKOMEDA_C1_TEST_ID, R.drawable.ic_milkomeda_test); - put(PHI_NETWORK_MAIN_ID, R.drawable.ic_phi_network); + put(PHI_MAIN_ID, R.drawable.ic_phi_network); + put(PHI_V2_MAIN_ID, R.drawable.ic_phi_network); } }; @@ -438,7 +445,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(AURORA_TESTNET_ID, R.drawable.ic_aurora_test); put(MILKOMEDA_C1_ID, R.drawable.ic_milkomeda); put(MILKOMEDA_C1_TEST_ID, R.drawable.ic_milkomeda_test); - put(PHI_NETWORK_MAIN_ID, R.drawable.ic_phi_network); + put(PHI_MAIN_ID, R.drawable.ic_phi_network); + put(PHI_V2_MAIN_ID, R.drawable.ic_phi_network); } }; @@ -481,7 +489,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(AURORA_TESTNET_ID, R.color.aurora_testnet); put(MILKOMEDA_C1_ID, R.color.milkomeda); put(MILKOMEDA_C1_TEST_ID, R.color.milkomeda_test); - put(PHI_NETWORK_MAIN_ID, R.color.phi_network); + put(PHI_MAIN_ID, R.color.phi_network); + put(PHI_V2_MAIN_ID, R.color.phi_network); } }; diff --git a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java index 9b11004fa8..376ae9e317 100644 --- a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java +++ b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java @@ -334,8 +334,16 @@ public boolean canCheckChain(long networkId) public Single getAsset(Token token, BigInteger tokenId) { - return Single.fromCallable(() -> - fetchAsset(token.tokenInfo.chainId, token.tokenInfo.address, tokenId.toString())); + if (!com.alphawallet.app.repository.EthereumNetworkBase.hasOpenseaAPI(token.tokenInfo.chainId)) + { + return Single.fromCallable(() -> ""); + } + else + { + return Single.fromCallable(() -> + fetchAsset(token.tokenInfo.chainId, token.tokenInfo.address, tokenId.toString())); + } + } public Single getCollection(Token token, String slug) diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index c134f9b83b..eda5013178 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -9,16 +9,17 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.CLASSIC_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.CRONOS_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.FANTOM_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; import android.text.TextUtils; @@ -86,6 +87,7 @@ public class TickerService private static final String COINGECKO_CHAIN_CALL = "https://api.coingecko.com/api/v3/simple/price?ids=" + CHAIN_IDS + "&vs_currencies=" + CURRENCY_TOKEN + "&include_24hr_change=true"; private static final String COINGECKO_API = "https://api.coingecko.com/api/v3/simple/token_price/" + CHAIN_IDS + "?contract_addresses=" + CONTRACT_ADDR + "&vs_currencies=" + CURRENCY_TOKEN + "&include_24hr_change=true"; private static final String DEXGURU_API = "https://api.dex.guru/v1/tokens/" + CONTRACT_ADDR + "-" + CHAIN_IDS; + private static final String PHI_TICKER_API = "https://price.phi.network/api/ticker?filter=WPHI"; private static final String CURRENCY_CONV = "currency"; private static final boolean ALLOW_UNVERIFIED_TICKERS = false; //allows verified:false tickers from DEX.GURU. Not recommended public static final long TICKER_TIMEOUT = DateUtils.WEEK_IN_MILLIS; //remove ticker if not seen in one week @@ -140,6 +142,7 @@ private void tickerUpdate() .flatMap(this::updateTickersFromOracle) .flatMap(this::fetchTickersSeparatelyIfRequired) .flatMap(this::addArtisTicker) + .map(this::addPhiTickers) .map(this::checkTickers) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -491,6 +494,50 @@ private TokenTicker addArtisTickers(TokenTicker tokenTicker) return tokenTicker; } + private int addPhiTickers(int tickerCount) + { + //fetch phi price + Request request = new Request.Builder() + .url(PHI_TICKER_API) + .get() + .build(); + + try (okhttp3.Response response = httpClient.newCall(request) + .execute()) + { + if ((response.code() / 100) == 2 && response.body() != null) + { + String result = response.body() + .string(); + JSONObject data = new JSONObject(result); + JSONObject tickerData = (JSONObject) data.get("data"); + JSONObject quoteData = (JSONObject) tickerData.get("quotes"); + JSONObject usdQuote = (JSONObject) quoteData.get("USD"); + + double priceChange = usdQuote.getDouble("price_change_24h"); + double price = usdQuote.getDouble("price"); + double percentChange = (priceChange / price) * 100.0; + + String currentPrice = String.valueOf(price * currentConversionRate); + + TokenTicker phiTicker = new TokenTicker(currentPrice, + String.valueOf(percentChange), + currentCurrencySymbolTxt, + "", + System.currentTimeMillis()); + + ethTickers.put(PHI_V2_MAIN_ID, phiTicker); + return tickerCount + 1; + } + } + catch (Exception e) + { + Timber.e(e); + } + + return tickerCount; + } + private TokenTicker decodeCoinGeckoTicker(JSONObject eth) { TokenTicker tTicker; diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index dadfb333ca..835cee2d0c 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -45,8 +45,8 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final long AURORA_TESTNET_ID = 1313161555; public static final long MILKOMEDA_C1_ID = 2001; public static final long MILKOMEDA_C1_TEST_ID = 200101; - public static final long PHI_NETWORK_MAIN_ID = 4181; public static final long PHI_MAIN_ID = 4181; + public static final long PHI_V2_MAIN_ID = 144; public static final String MAINNET_RPC_URL = "https://mainnet.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; @@ -85,6 +85,7 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final String MILKOMEDA_C1_RPC = "https://rpc-mainnet-cardano-evm.c1.milkomeda.com"; public static final String MILKOMEDA_C1_TEST_RPC = "https://rpc-devnet-cardano-evm.c1.milkomeda.com"; public static final String PHI_MAIN_RPC_URL = "https://rpc1.phi.network"; + public static final String PHI_NETWORK_V2_RPC = "https://connect.phi.network"; static Map networkMap = new LinkedHashMap() { { @@ -163,8 +164,10 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit MILKOMEDA_C1_ID, false)); put(MILKOMEDA_C1_TEST_ID, new NetworkInfo("Milkomeda Cardano (Test)","milktADA", MILKOMEDA_C1_TEST_RPC, "https://explorer-devnet-cardano-evm.c1.milkomeda.com/tx/", MILKOMEDA_C1_TEST_ID, false)); - put(PHI_NETWORK_MAIN_ID, new NetworkInfo("PHI", "\u03d5", PHI_MAIN_RPC_URL, "https://explorer.phi.network/tx/", - PHI_NETWORK_MAIN_ID, false)); + put(PHI_MAIN_ID, new NetworkInfo("PHI", "\u03d5", PHI_MAIN_RPC_URL, "https://explorer.phi.network/tx/", + PHI_MAIN_ID, false)); + put(PHI_V2_MAIN_ID, new NetworkInfo("PHI v2", "\u03d5", PHI_NETWORK_V2_RPC, "https://phiscan.com/tx/", + PHI_V2_MAIN_ID, false)); } }; From da76c74dc0f9e192133e0d965706435f6f76e01a Mon Sep 17 00:00:00 2001 From: James Brown Date: Wed, 28 Sep 2022 13:27:13 +1000 Subject: [PATCH 106/183] Bump gradle version --- app/build.gradle | 8 ++++---- .../java/com/alphawallet/app/walletconnect/WCClient.kt | 1 + build.gradle | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 38be46d0f6..7f86bd208c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -85,8 +85,8 @@ android { } } defaultConfig { - versionCode 202 - versionName "3.58.3" + versionCode 204 + versionName "3.60" applicationId "io.stormbird.wallet" minSdkVersion 23 @@ -245,8 +245,8 @@ dependencies { // Ethereum client //implementation "org.web3j:core:4.8.8-android" implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.fasterxml.jackson.core:jackson-core:2.13.2' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' + implementation 'com.fasterxml.jackson.core:jackson-core:2.13.3' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3' implementation 'org.slf4j:slf4j-api:2.0.0-alpha7' // Http client diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/WCClient.kt b/app/src/main/java/com/alphawallet/app/walletconnect/WCClient.kt index 0eb706ad90..53ac1bfd10 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/WCClient.kt +++ b/app/src/main/java/com/alphawallet/app/walletconnect/WCClient.kt @@ -408,6 +408,7 @@ open class WCClient : WebSocketListener() { WCMethod.ADD_ETHEREUM_CHAIN -> { handleAddChain(request) } + else -> {} } } diff --git a/build.gradle b/build.gradle index 0d5e7e6736..90dbf107e1 100644 --- a/build.gradle +++ b/build.gradle @@ -17,8 +17,8 @@ buildscript { // WARNING WARNING WARNING // you are about to add here a dependency to be used in the Android app // don't do that. add that dependency to app/build.gradle - classpath 'com.google.gms:google-services:4.3.10' - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10' + classpath 'com.google.gms:google-services:4.3.14' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2' classpath 'com.google.dagger:hilt-android-gradle-plugin:2.40.5' } From 2dc21ba870860747c512c959ecf6bbc7e8ebbee4 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 29 Sep 2022 06:58:20 +0800 Subject: [PATCH 107/183] 2808 add code format pass to github test (#2847) * Add checkstyle plugin * Config checkstyle rules * Add CheckStyle workflow * Upload reports * Add configuration and fail the build if has violation * Debug env variables * Simulate modification * Format file --- .github/workflows/checkstyle.yml | 26 + .github/workflows/lint-pr.yml | 4 +- .github/workflows/lint.yml | 4 +- app/build.gradle | 2 - .../alphawallet/app/entity/Transaction.java | 1276 +++++++++-------- build.gradle | 2 + build.sh | 8 +- checkstyle.xml | 342 +++++ codestyle.gradle | 90 ++ 9 files changed, 1113 insertions(+), 641 deletions(-) create mode 100644 .github/workflows/checkstyle.yml create mode 100644 checkstyle.xml create mode 100644 codestyle.gradle diff --git a/.github/workflows/checkstyle.yml b/.github/workflows/checkstyle.yml new file mode 100644 index 0000000000..f873d426f3 --- /dev/null +++ b/.github/workflows/checkstyle.yml @@ -0,0 +1,26 @@ +name: Check Style +on: + pull_request: +jobs: + lint: + name: Run CheckStyle + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up JDK + uses: actions/setup-java@v3 + with: + distribution: zulu + java-version: 11 + cache: gradle + - name: Run + run: ./gradlew --no-daemon checkStyleChanged + - name: Upload report + uses: actions/upload-artifact@v2 + if: ${{ always() }} # IMPORTANT: Upload reports regardless of status + with: + name: checkstyle-reports + path: build/reports/checkstyle/ diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index 11a6b1b8a6..d30d46fc52 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -6,6 +6,8 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: set up JDK uses: actions/setup-java@v3 with: @@ -16,7 +18,7 @@ jobs: run: ./gradlew :app:detekt continue-on-error: true - name: Run Android Lint - run: ./gradlew :app:lintAnalyticsDebug + run: ./gradlew :app:lintAnalyticsDebug -x checkStyleMain -x checkStyleTest - name: Run Android Lint Reporter to report Lint and Detekt result to PR env: PR_NUMBER: ${{ github.event.number }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1d79fa0a64..d771eb99c0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,6 +10,8 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Set up JDK uses: actions/setup-java@v3 with: @@ -19,4 +21,4 @@ jobs: - name: Run Kotlin lint run: ./gradlew :app:detekt - name: Run Android Lint - run: ./gradlew :app:lintAnalyticsDebug \ No newline at end of file + run: ./gradlew :app:lintAnalyticsDebug -x checkStyleMain -x checkStyleTest \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 7f86bd208c..cc1f2ee95f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -270,8 +270,6 @@ dependencies { // Sugar implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'com.github.apl-devs:appintro:v4.2.2' - implementation 'com.github.romandanylyk:PageIndicatorView:v1.0.0' //coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5' diff --git a/app/src/main/java/com/alphawallet/app/entity/Transaction.java b/app/src/main/java/com/alphawallet/app/entity/Transaction.java index 91e54e05d6..49524e68e5 100644 --- a/app/src/main/java/com/alphawallet/app/entity/Transaction.java +++ b/app/src/main/java/com/alphawallet/app/entity/Transaction.java @@ -28,14 +28,13 @@ import java.util.Map; /** - * * This is supposed to be a generic transaction class which can * contain all of 3 stages of a transaction: - * + *

* 1. being compiled, in progress, or ready to be signed; * 2. compiled and signed, or ready to be broadcasted; - * 2. already broadcasted, obtained in its raw format from a node, - * including the signatures in it; + * 2. already broadcasted, obtained in its raw format from a node, + * including the signatures in it; * 4. already included in a blockchain. */ public class Transaction implements Parcelable @@ -61,654 +60,665 @@ public class Transaction implements Parcelable public TransactionInput transactionInput = null; public static final String CONSTRUCTOR = "Constructor"; - public static final TransactionDecoder decoder = new TransactionDecoder(); - public static ParseMagicLink parser = null; - - //placeholder for error - public Transaction() - { - //blank transaction - hash = ""; - blockNumber = ""; - timeStamp = 0; - nonce = 0; - from = ""; - to = ""; - value = ""; - gas = ""; - gasPrice = ""; - gasUsed = ""; - input = ""; - error = ""; - chainId = 0; - maxFeePerGas = ""; - maxPriorityFee = ""; - } - - public boolean isPending() - { - return TextUtils.isEmpty(blockNumber) || blockNumber.equals("0") || blockNumber.equals("-2"); - } - - public boolean hasError() - { - return !TextUtils.isEmpty(error) && error.equals("1"); - } - - public boolean hasData() - { - return !TextUtils.isEmpty(input) && input.length() > 2; - } + public static final TransactionDecoder decoder = new TransactionDecoder(); + public static ParseMagicLink parser = null; + + //placeholder for error + public Transaction() + { + //blank transaction + hash = ""; + blockNumber = ""; + timeStamp = 0; + nonce = 0; + from = ""; + to = ""; + value = ""; + gas = ""; + gasPrice = ""; + gasUsed = ""; + input = ""; + error = ""; + chainId = 0; + maxFeePerGas = ""; + maxPriorityFee = ""; + } + + public boolean isPending() + { + return TextUtils.isEmpty(blockNumber) || blockNumber.equals("0") || blockNumber.equals("-2"); + } + + public boolean hasError() + { + return !TextUtils.isEmpty(error) && error.equals("1"); + } + + public boolean hasData() + { + return !TextUtils.isEmpty(input) && input.length() > 2; + } public Transaction( String hash, String error, String blockNumber, long timeStamp, - int nonce, - String from, - String to, - String value, - String gas, - String gasPrice, - String input, - String gasUsed, + int nonce, + String from, + String to, + String value, + String gas, + String gasPrice, + String input, + String gasUsed, long chainId, - boolean isConstructor) { + boolean isConstructor) + { this.hash = hash; this.error = error; this.blockNumber = blockNumber; this.timeStamp = timeStamp; - this.nonce = nonce; - this.from = from; - this.to = to; - this.value = value; - this.gas = gas; - this.gasPrice = gasPrice; - this.input = input; - this.gasUsed = gasUsed; - this.chainId = chainId; - this.isConstructor = isConstructor; - this.maxFeePerGas = ""; - this.maxPriorityFee = ""; - } - - public Transaction(Web3Transaction tx, long chainId, String wallet) - { - this.hash = null; - this.error = null; - this.blockNumber = null; - this.timeStamp = System.currentTimeMillis()/1000; - this.nonce = -1; - this.from = wallet; - this.to = tx.recipient.toString(); - this.value = tx.value.toString(); - this.gas = tx.gasLimit.toString(); - this.gasPrice = tx.gasPrice.toString(); - this.input = tx.payload; - this.gasUsed = tx.gasLimit.toString(); - this.chainId = chainId; - this.isConstructor = tx.isConstructor(); - this.maxFeePerGas = tx.maxFeePerGas.toString(); - this.maxPriorityFee = tx.maxPriorityFeePerGas.toString(); - } - - public Transaction(CovalentTransaction cTx, long chainId, long transactionTime) - { - if (cTx.to_address == null || cTx.to_address.equals("null")) - { - isConstructor = true; - input = CONSTRUCTOR; - //determine creation address from events - to = cTx.determineContractAddress(); - } - else - { - to = cTx.to_address; - input = "0x"; - } - - this.hash = cTx.tx_hash; - this.blockNumber = cTx.block_height; - this.timeStamp = transactionTime; - this.error = cTx.successful ? "0" : "1"; - this.nonce = 0; //don't know this - this.from = cTx.from_address; - this.value = cTx.value; - this.gas = String.valueOf(cTx.gas_offered); - this.gasPrice = cTx.gas_price; - this.gasUsed = cTx.gas_spent; - this.chainId = chainId; - this.maxFeePerGas = ""; - this.maxPriorityFee = ""; - } - - public Transaction(org.web3j.protocol.core.methods.response.Transaction ethTx, long chainId, boolean isSuccess, long timeStamp) - { - // Get contract address if constructor - String contractAddress = ethTx.getCreates() != null ? ethTx.getCreates() : ""; - int nonce = ethTx.getNonceRaw() != null ? Numeric.toBigInt(ethTx.getNonceRaw()).intValue() : 0; - - if (!TextUtils.isEmpty(contractAddress)) //must be a constructor - { - to = contractAddress; - isConstructor = true; - input = CONSTRUCTOR; - } - else if (ethTx.getTo() == null && ethTx.getInput() != null && ethTx.getInput().startsWith("0x60")) - { - // some clients don't populate the 'creates' data for constructors. Note: Ethereum constructor always starts with a 'PUSH' 0x60 instruction - input = CONSTRUCTOR; - isConstructor = true; - to = calculateContractAddress(ethTx.getFrom(), nonce); - } - else - { - this.to = ethTx.getTo() != null ? ethTx.getTo() : ""; - this.input = ethTx.getInput(); - } - - this.hash = ethTx.getHash(); - this.blockNumber = ethTx.getBlockNumber().toString(); - this.timeStamp = timeStamp; - this.error = isSuccess ? "0" : "1"; - this.nonce = nonce; - this.from = ethTx.getFrom(); - this.value = ethTx.getValue().toString(); - this.gas = ethTx.getGas().toString(); - this.gasPrice = ethTx.getGasPrice().toString(); - this.gasUsed = ethTx.getGas().toString(); - this.chainId = chainId; - this.maxFeePerGas = ethTx.getMaxFeePerGas(); - this.maxPriorityFee = ethTx.getMaxPriorityFeePerGas(); - } - - public Transaction(String hash, String isError, String blockNumber, long timeStamp, int nonce, String from, String to, - String value, String gas, String gasPrice, String input, String gasUsed, long chainId, String contractAddress) - { - //Is it a constructor? - if (!TextUtils.isEmpty(contractAddress)) - { - String testContractDeploymentAddress = Utils.calculateContractAddress(from, nonce); - if (testContractDeploymentAddress.equalsIgnoreCase(contractAddress)) - { - to = contractAddress; - isConstructor = true; - input = CONSTRUCTOR; - } - } - - this.to = to; - this.hash = hash; - this.error = isError; - this.blockNumber = blockNumber; - this.timeStamp = timeStamp; - this.nonce = nonce; - this.from = from; - this.value = value; - this.gas = gas; - this.gasPrice = gasPrice; - this.input = input; - this.gasUsed = gasUsed; - this.chainId = chainId; - this.maxFeePerGas = ""; - this.maxPriorityFee = ""; - } - - public Transaction(String hash, String isError, String blockNumber, long timeStamp, int nonce, String from, String to, - String value, String gas, String gasPrice, String maxFeePerGas, String maxPriorityFee, String input, String gasUsed, long chainId, String contractAddress) - { - if (!TextUtils.isEmpty(contractAddress)) - { - String testContractDeploymentAddress = Utils.calculateContractAddress(from, nonce); - if (testContractDeploymentAddress.equalsIgnoreCase(contractAddress)) - { - to = contractAddress; - isConstructor = true; - input = CONSTRUCTOR; - } - } - - this.to = to; - this.hash = hash; - this.error = isError; - this.blockNumber = blockNumber; - this.timeStamp = timeStamp; - this.nonce = nonce; - this.from = from; - this.value = value; - this.gas = gas; - this.maxFeePerGas = maxFeePerGas; - this.maxPriorityFee = maxPriorityFee; - this.gasPrice = gasPrice; - this.input = input; - this.gasUsed = gasUsed; - this.chainId = chainId; - } - - protected Transaction(Parcel in) - { - hash = in.readString(); - error = in.readString(); - blockNumber = in.readString(); - timeStamp = in.readLong(); - nonce = in.readInt(); - from = in.readString(); - to = in.readString(); - value = in.readString(); - gas = in.readString(); - gasPrice = in.readString(); - input = in.readString(); - gasUsed = in.readString(); - chainId = in.readLong(); - maxFeePerGas = in.readString(); - maxPriorityFee = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override - public Transaction createFromParcel(Parcel in) { - return new Transaction(in); - } - - @Override - public Transaction[] newArray(int size) { - return new Transaction[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { + this.nonce = nonce; + this.from = from; + this.to = to; + this.value = value; + this.gas = gas; + this.gasPrice = gasPrice; + this.input = input; + this.gasUsed = gasUsed; + this.chainId = chainId; + this.isConstructor = isConstructor; + this.maxFeePerGas = ""; + this.maxPriorityFee = ""; + } + + public Transaction(Web3Transaction tx, long chainId, String wallet) + { + this.hash = null; + this.error = null; + this.blockNumber = null; + this.timeStamp = System.currentTimeMillis() / 1000; + this.nonce = -1; + this.from = wallet; + this.to = tx.recipient.toString(); + this.value = tx.value.toString(); + this.gas = tx.gasLimit.toString(); + this.gasPrice = tx.gasPrice.toString(); + this.input = tx.payload; + this.gasUsed = tx.gasLimit.toString(); + this.chainId = chainId; + this.isConstructor = tx.isConstructor(); + this.maxFeePerGas = tx.maxFeePerGas.toString(); + this.maxPriorityFee = tx.maxPriorityFeePerGas.toString(); + } + + public Transaction(CovalentTransaction cTx, long chainId, long transactionTime) + { + if (cTx.to_address == null || cTx.to_address.equals("null")) + { + isConstructor = true; + input = CONSTRUCTOR; + //determine creation address from events + to = cTx.determineContractAddress(); + } + else + { + to = cTx.to_address; + input = "0x"; + } + + this.hash = cTx.tx_hash; + this.blockNumber = cTx.block_height; + this.timeStamp = transactionTime; + this.error = cTx.successful ? "0" : "1"; + this.nonce = 0; //don't know this + this.from = cTx.from_address; + this.value = cTx.value; + this.gas = String.valueOf(cTx.gas_offered); + this.gasPrice = cTx.gas_price; + this.gasUsed = cTx.gas_spent; + this.chainId = chainId; + this.maxFeePerGas = ""; + this.maxPriorityFee = ""; + } + + public Transaction(org.web3j.protocol.core.methods.response.Transaction ethTx, long chainId, boolean isSuccess, long timeStamp) + { + // Get contract address if constructor + String contractAddress = ethTx.getCreates() != null ? ethTx.getCreates() : ""; + int nonce = ethTx.getNonceRaw() != null ? Numeric.toBigInt(ethTx.getNonceRaw()).intValue() : 0; + + if (!TextUtils.isEmpty(contractAddress)) //must be a constructor + { + to = contractAddress; + isConstructor = true; + input = CONSTRUCTOR; + } + else if (ethTx.getTo() == null && ethTx.getInput() != null && ethTx.getInput().startsWith("0x60")) + { + // some clients don't populate the 'creates' data for constructors. Note: Ethereum constructor always starts with a 'PUSH' 0x60 instruction + input = CONSTRUCTOR; + isConstructor = true; + to = calculateContractAddress(ethTx.getFrom(), nonce); + } + else + { + this.to = ethTx.getTo() != null ? ethTx.getTo() : ""; + this.input = ethTx.getInput(); + } + + this.hash = ethTx.getHash(); + this.blockNumber = ethTx.getBlockNumber().toString(); + this.timeStamp = timeStamp; + this.error = isSuccess ? "0" : "1"; + this.nonce = nonce; + this.from = ethTx.getFrom(); + this.value = ethTx.getValue().toString(); + this.gas = ethTx.getGas().toString(); + this.gasPrice = ethTx.getGasPrice().toString(); + this.gasUsed = ethTx.getGas().toString(); + this.chainId = chainId; + this.maxFeePerGas = ethTx.getMaxFeePerGas(); + this.maxPriorityFee = ethTx.getMaxPriorityFeePerGas(); + } + + public Transaction(String hash, String isError, String blockNumber, long timeStamp, int nonce, String from, String to, + String value, String gas, String gasPrice, String input, String gasUsed, long chainId, String contractAddress) + { + //Is it a constructor? + if (!TextUtils.isEmpty(contractAddress)) + { + String testContractDeploymentAddress = Utils.calculateContractAddress(from, nonce); + if (testContractDeploymentAddress.equalsIgnoreCase(contractAddress)) + { + to = contractAddress; + isConstructor = true; + input = CONSTRUCTOR; + } + } + + this.to = to; + this.hash = hash; + this.error = isError; + this.blockNumber = blockNumber; + this.timeStamp = timeStamp; + this.nonce = nonce; + this.from = from; + this.value = value; + this.gas = gas; + this.gasPrice = gasPrice; + this.input = input; + this.gasUsed = gasUsed; + this.chainId = chainId; + this.maxFeePerGas = ""; + this.maxPriorityFee = ""; + } + + public Transaction(String hash, String isError, String blockNumber, long timeStamp, int nonce, String from, String to, + String value, String gas, String gasPrice, String maxFeePerGas, String maxPriorityFee, String input, String gasUsed, long chainId, String contractAddress) + { + if (!TextUtils.isEmpty(contractAddress)) + { + String testContractDeploymentAddress = Utils.calculateContractAddress(from, nonce); + if (testContractDeploymentAddress.equalsIgnoreCase(contractAddress)) + { + to = contractAddress; + isConstructor = true; + input = CONSTRUCTOR; + } + } + + this.to = to; + this.hash = hash; + this.error = isError; + this.blockNumber = blockNumber; + this.timeStamp = timeStamp; + this.nonce = nonce; + this.from = from; + this.value = value; + this.gas = gas; + this.maxFeePerGas = maxFeePerGas; + this.maxPriorityFee = maxPriorityFee; + this.gasPrice = gasPrice; + this.input = input; + this.gasUsed = gasUsed; + this.chainId = chainId; + } + + protected Transaction(Parcel in) + { + hash = in.readString(); + error = in.readString(); + blockNumber = in.readString(); + timeStamp = in.readLong(); + nonce = in.readInt(); + from = in.readString(); + to = in.readString(); + value = in.readString(); + gas = in.readString(); + gasPrice = in.readString(); + input = in.readString(); + gasUsed = in.readString(); + chainId = in.readLong(); + maxFeePerGas = in.readString(); + maxPriorityFee = in.readString(); + } + + public static final Creator CREATOR = new Creator() + { + @Override + public Transaction createFromParcel(Parcel in) + { + return new Transaction(in); + } + + @Override + public Transaction[] newArray(int size) + { + return new Transaction[size]; + } + }; + + @Override + public int describeContents() + { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) + { dest.writeString(hash); dest.writeString(error); dest.writeString(blockNumber); dest.writeLong(timeStamp); - dest.writeInt(nonce); - dest.writeString(from); - dest.writeString(to); - dest.writeString(value); - dest.writeString(gas); - dest.writeString(gasPrice); - dest.writeString(input); - dest.writeString(gasUsed); - dest.writeLong(chainId); - dest.writeString(maxFeePerGas); - dest.writeString(maxPriorityFee); - } - - public boolean isRelated(String contractAddress, String walletAddress) - { - if (contractAddress.equals("eth")) - { - return (input.equals("0x") || from.equalsIgnoreCase(walletAddress)); - } - else if (walletAddress.equalsIgnoreCase(contractAddress)) //transactions sent from or sent to the main currency account - { - return from.equalsIgnoreCase(walletAddress) || to.equalsIgnoreCase(walletAddress); - } - else if (to.equalsIgnoreCase(contractAddress)) - { - return true; - } - else - { - return getWalletInvolvedInTransaction(walletAddress); - } - } - - /** - * Fetch result of transaction operation. - * This is very much a WIP - * @param token - * @return - */ - public String getOperationResult(Token token, int precision) - { - //get amount here. will be amount + symbol if appropriate - if (hasInput()) - { - decodeTransactionInput(token.getWallet()); - String value = transactionInput.getOperationValue(token, this); - boolean isSendOrReceive = !from.equalsIgnoreCase(to) && transactionInput.isSendOrReceive(this); - String prefix = (value.length() == 0 || (value.startsWith("#") || !isSendOrReceive)) ? "" : - (token.getIsSent(this) ? "- " : "+ "); - return prefix + value; - } - else - { - return token.getTransactionValue(this, precision); - } - } - - /** - * Can the contract call be valid if the operation token is Ethereum? - * @param token - * @return - */ - public boolean shouldShowSymbol(Token token) - { - if (hasInput()) - { - decodeTransactionInput(token.getWallet()); - return transactionInput.shouldShowSymbol(token); - } - else - { - return true; - } - } - - public String getOperationTokenAddress() - { - if (hasInput()) - { - return to; - } - else - { - return ""; - } - } - - public boolean isLegacyTransaction() - { - try - { - return !TextUtils.isEmpty(gasPrice) && new BigInteger(gasPrice).compareTo(BigInteger.ZERO) > 0; - } - catch (Exception e) - { - return true; - } - } - - public String getOperationName(Context ctx, Token token, String walletAddress) - { - String txName = null; - if (isPending()) - { - txName = ctx.getString(R.string.status_pending); - } - else if (hasInput()) - { - decodeTransactionInput(walletAddress); - if (token.isEthereum() && shouldShowSymbol(token)) - { - transactionInput.type = TransactionType.CONTRACT_CALL; - } - - return transactionInput.getOperationTitle(ctx); - } - - return txName; - } - - public boolean hasInput() - { - return input != null && input.length() >= 10; - } - - public int getOperationToFrom(String walletAddress) - { - if (hasInput()) - { - decodeTransactionInput(walletAddress); - return transactionInput.getOperationToFrom(); - } - else - { - return 0; - } - } - - public StatusType getOperationImage(Token token) - { - if (hasError()) - { - return StatusType.FAILED; - } - else if (hasInput()) - { - decodeTransactionInput(token.getWallet()); - return transactionInput.getOperationImage(this, token.getWallet()); - } - else - { - return from.equalsIgnoreCase(token.getWallet()) ? StatusType.SENT : StatusType.RECEIVE; - } - } - - public TransactionType getTransactionType(String wallet) - { - if (hasError()) - { - return TransactionType.UNKNOWN; - } - else if (hasInput()) - { - decodeTransactionInput(wallet); - return transactionInput.type; - } - else - { - return TransactionType.SEND_ETH; - } - } - - /** - * Supplimental info in this case is the intrinsic root value attached to a contract call - * EG: Calling cryptokitties ERC721 'breedWithAuto' function requires you to call the function and also attach a small amount of ETH - * for the 'breeding fee'. That fee is later released to the caller of the 'birth' function. - * Supplemental info for these transaction would appear as -0.031 for the 'breedWithAuto' and +0.031 on the 'birth' call - * However it's not that simple - the 'breeding fee' will be in the value attached to the transaction, however the 'midwife' reward appears - * as an internal transaction, so won't be in the 'value' property. - * - * @return - */ - public String getSupplementalInfo(String walletAddress, String networkName) - { - if (hasInput()) - { - decodeTransactionInput(walletAddress); - return transactionInput.getSupplimentalInfo(this, walletAddress, networkName); - } - else - { - return ""; - } - } - - public String getPrefix(Token token) - { - if (hasInput()) - { - decodeTransactionInput(token.getWallet()); - if (!transactionInput.isSendOrReceive(this) || token.isEthereum()) - { - return ""; - } - else if (token.isERC721()) - { - return ""; - } - } - - boolean isSent = token.getIsSent(this); - boolean isSelf = from.equalsIgnoreCase(to); - if (isSelf) return ""; - else if (isSent) return "- "; - else return "+ "; - } + dest.writeInt(nonce); + dest.writeString(from); + dest.writeString(to); + dest.writeString(value); + dest.writeString(gas); + dest.writeString(gasPrice); + dest.writeString(input); + dest.writeString(gasUsed); + dest.writeLong(chainId); + dest.writeString(maxFeePerGas); + dest.writeString(maxPriorityFee); + } + + public boolean isRelated(String contractAddress, String walletAddress) + { + if (contractAddress.equals("eth")) + { + return (input.equals("0x") || from.equalsIgnoreCase(walletAddress)); + } + else if (walletAddress.equalsIgnoreCase(contractAddress)) //transactions sent from or sent to the main currency account + { + return from.equalsIgnoreCase(walletAddress) || to.equalsIgnoreCase(walletAddress); + } + else if (to.equalsIgnoreCase(contractAddress)) + { + return true; + } + else + { + return getWalletInvolvedInTransaction(walletAddress); + } + } + + /** + * Fetch result of transaction operation. + * This is very much a WIP + * + * @param token + * @return + */ + public String getOperationResult(Token token, int precision) + { + //get amount here. will be amount + symbol if appropriate + if (hasInput()) + { + decodeTransactionInput(token.getWallet()); + String value = transactionInput.getOperationValue(token, this); + boolean isSendOrReceive = !from.equalsIgnoreCase(to) && transactionInput.isSendOrReceive(this); + String prefix = (value.length() == 0 || (value.startsWith("#") || !isSendOrReceive)) ? "" : + (token.getIsSent(this) ? "- " : "+ "); + return prefix + value; + } + else + { + return token.getTransactionValue(this, precision); + } + } + + /** + * Can the contract call be valid if the operation token is Ethereum? + * + * @param token + * @return + */ + public boolean shouldShowSymbol(Token token) + { + if (hasInput()) + { + decodeTransactionInput(token.getWallet()); + return transactionInput.shouldShowSymbol(token); + } + else + { + return true; + } + } + + public String getOperationTokenAddress() + { + if (hasInput()) + { + return to; + } + else + { + return ""; + } + } + + public boolean isLegacyTransaction() + { + try + { + return !TextUtils.isEmpty(gasPrice) && new BigInteger(gasPrice).compareTo(BigInteger.ZERO) > 0; + } + catch (Exception e) + { + return true; + } + } + + public String getOperationName(Context ctx, Token token, String walletAddress) + { + String txName = null; + if (isPending()) + { + txName = ctx.getString(R.string.status_pending); + } + else if (hasInput()) + { + decodeTransactionInput(walletAddress); + if (token.isEthereum() && shouldShowSymbol(token)) + { + transactionInput.type = TransactionType.CONTRACT_CALL; + } + + return transactionInput.getOperationTitle(ctx); + } + + return txName; + } + + public boolean hasInput() + { + return input != null && input.length() >= 10; + } + + public int getOperationToFrom(String walletAddress) + { + if (hasInput()) + { + decodeTransactionInput(walletAddress); + return transactionInput.getOperationToFrom(); + } + else + { + return 0; + } + } + + public StatusType getOperationImage(Token token) + { + if (hasError()) + { + return StatusType.FAILED; + } + else if (hasInput()) + { + decodeTransactionInput(token.getWallet()); + return transactionInput.getOperationImage(this, token.getWallet()); + } + else + { + return from.equalsIgnoreCase(token.getWallet()) ? StatusType.SENT : StatusType.RECEIVE; + } + } + + public TransactionType getTransactionType(String wallet) + { + if (hasError()) + { + return TransactionType.UNKNOWN; + } + else if (hasInput()) + { + decodeTransactionInput(wallet); + return transactionInput.type; + } + else + { + return TransactionType.SEND_ETH; + } + } + + /** + * Supplimental info in this case is the intrinsic root value attached to a contract call + * EG: Calling cryptokitties ERC721 'breedWithAuto' function requires you to call the function and also attach a small amount of ETH + * for the 'breeding fee'. That fee is later released to the caller of the 'birth' function. + * Supplemental info for these transaction would appear as -0.031 for the 'breedWithAuto' and +0.031 on the 'birth' call + * However it's not that simple - the 'breeding fee' will be in the value attached to the transaction, however the 'midwife' reward appears + * as an internal transaction, so won't be in the 'value' property. + * + * @return + */ + public String getSupplementalInfo(String walletAddress, String networkName) + { + if (hasInput()) + { + decodeTransactionInput(walletAddress); + return transactionInput.getSupplimentalInfo(this, walletAddress, networkName); + } + else + { + return ""; + } + } + + public String getPrefix(Token token) + { + if (hasInput()) + { + decodeTransactionInput(token.getWallet()); + if (!transactionInput.isSendOrReceive(this) || token.isEthereum()) + { + return ""; + } + else if (token.isERC721()) + { + return ""; + } + } + + boolean isSent = token.getIsSent(this); + boolean isSelf = from.equalsIgnoreCase(to); + if (isSelf) return ""; + else if (isSent) return "- "; + else return "+ "; + } public BigDecimal getRawValue(String walletAddress) throws Exception { - if (hasInput()) - { - decodeTransactionInput(walletAddress); - return transactionInput.getRawValue(); - } - else - { - return new BigDecimal(value); - } - } - - public StatusType getTransactionStatus() - { - if (hasError()) - { - return StatusType.FAILED; - } - else if (blockNumber.equals("-1")) - { - return StatusType.REJECTED; - } - else if (isPending()) - { - return StatusType.PENDING; - } - else - { - return null; - } - } + if (hasInput()) + { + decodeTransactionInput(walletAddress); + return transactionInput.getRawValue(); + } + else + { + return new BigDecimal(value); + } + } + + public StatusType getTransactionStatus() + { + if (hasError()) + { + return StatusType.FAILED; + } + else if (blockNumber.equals("-1")) + { + return StatusType.REJECTED; + } + else if (isPending()) + { + return StatusType.PENDING; + } + else + { + return null; + } + } public void addTransactionElements(Map resultMap) { - resultMap.put("__hash", new EventResult("", hash)); - resultMap.put("__to", new EventResult("", to)); - resultMap.put("__from", new EventResult("", from)); - resultMap.put("__value", new EventResult("", value)); - resultMap.put("__chainId", new EventResult("", String.valueOf(chainId))); - } - - public String getEventName(String walletAddress) - { - String eventName = ""; - if (hasInput()) - { - decodeTransactionInput(walletAddress); - eventName = transactionInput.getOperationEvent(walletAddress); - } - - return eventName; - } - - public int getSupplementalColour(String supplementalTxt) - { - if (!TextUtils.isEmpty(supplementalTxt)) - { - switch (supplementalTxt.charAt(1)) - { - case '-': - return R.color.negative; - case '+': - return R.color.positive; - default: - break; - } - } - - return R.color.text_primary; - } - - public String getDestination(Token token) - { - if (hasInput()) - { - decodeTransactionInput(token.getWallet()); - return transactionInput.getOperationAddress(this, token); - } - else - { - return token.getAddress(); - } - } - - public String getOperationDetail(Context ctx, Token token, TokensService tService) - { - if (hasInput()) - { - decodeTransactionInput(token.getWallet()); - return transactionInput.getOperationDescription (ctx, this, token, tService); - } - else - { - return ctx.getString(R.string.operation_definition, ctx.getString(R.string.to), ENSHandler.matchENSOrFormat(ctx, to)); - } - } - - private void decodeTransactionInput(String walletAddress) - { - if (transactionInput == null && hasInput() && Utils.isAddressValid(walletAddress)) - { - transactionInput = decoder.decodeInput(this, walletAddress); - } - } - - public boolean getWalletInvolvedInTransaction(String walletAddr) - { - decodeTransactionInput(walletAddr); - if ((transactionInput != null && transactionInput.functionData != null) && transactionInput.containsAddress(walletAddr)) return true; - else if (from.equalsIgnoreCase(walletAddr)) return true; - else if (to.equalsIgnoreCase(walletAddr)) return true; - else return input != null && input.length() > 40 && input.contains(Numeric.cleanHexPrefix(walletAddr.toLowerCase())); - } - - public boolean isNFTSent(String walletAddress) - { - if (hasInput()) - { - decodeTransactionInput(walletAddress); - return transactionInput.isSent(); - } - else - { - return true; - } - } - - public boolean getIsSent(String walletAddress) - { - if (hasInput()) - { - decodeTransactionInput(walletAddress); - return transactionInput.isSent(); - } - else - { - return from.equalsIgnoreCase(walletAddress); - } - } - - public boolean isValueChange(String walletAddress) - { - if (hasInput()) - { - decodeTransactionInput(walletAddress); - return transactionInput.isSendOrReceive(this); - } - else - { - return true; - } - } - - private String calculateContractAddress(String account, long nonce){ - byte[] addressAsBytes = Numeric.hexStringToByteArray(account); - byte[] calculatedAddressAsBytes = - Hash.sha3(RlpEncoder.encode( - new RlpList( - RlpString.create(addressAsBytes), - RlpString.create((nonce))))); - - calculatedAddressAsBytes = Arrays.copyOfRange(calculatedAddressAsBytes, - 12, calculatedAddressAsBytes.length); - return Numeric.toHexString(calculatedAddressAsBytes); - } + resultMap.put("__hash", new EventResult("", hash)); + resultMap.put("__to", new EventResult("", to)); + resultMap.put("__from", new EventResult("", from)); + resultMap.put("__value", new EventResult("", value)); + resultMap.put("__chainId", new EventResult("", String.valueOf(chainId))); + } + + public String getEventName(String walletAddress) + { + String eventName = ""; + if (hasInput()) + { + decodeTransactionInput(walletAddress); + eventName = transactionInput.getOperationEvent(walletAddress); + } + + return eventName; + } + + public int getSupplementalColour(String supplementalTxt) + { + if (!TextUtils.isEmpty(supplementalTxt)) + { + switch (supplementalTxt.charAt(1)) + { + case '-': + return R.color.negative; + case '+': + return R.color.positive; + default: + break; + } + } + + return R.color.text_primary; + } + + public String getDestination(Token token) + { + if (hasInput()) + { + decodeTransactionInput(token.getWallet()); + return transactionInput.getOperationAddress(this, token); + } + else + { + return token.getAddress(); + } + } + + public String getOperationDetail(Context ctx, Token token, TokensService tService) + { + if (hasInput()) + { + decodeTransactionInput(token.getWallet()); + return transactionInput.getOperationDescription(ctx, this, token, tService); + } + else + { + return ctx.getString(R.string.operation_definition, ctx.getString(R.string.to), ENSHandler.matchENSOrFormat(ctx, to)); + } + } + + private void decodeTransactionInput(String walletAddress) + { + if (transactionInput == null && hasInput() && Utils.isAddressValid(walletAddress)) + { + transactionInput = decoder.decodeInput(this, walletAddress); + } + } + + public boolean getWalletInvolvedInTransaction(String walletAddr) + { + decodeTransactionInput(walletAddr); + if ((transactionInput != null && transactionInput.functionData != null) && transactionInput.containsAddress(walletAddr)) + return true; + else if (from.equalsIgnoreCase(walletAddr)) return true; + else if (to.equalsIgnoreCase(walletAddr)) return true; + else + return input != null && input.length() > 40 && input.contains(Numeric.cleanHexPrefix(walletAddr.toLowerCase())); + } + + public boolean isNFTSent(String walletAddress) + { + if (hasInput()) + { + decodeTransactionInput(walletAddress); + return transactionInput.isSent(); + } + else + { + return true; + } + } + + public boolean getIsSent(String walletAddress) + { + if (hasInput()) + { + decodeTransactionInput(walletAddress); + return transactionInput.isSent(); + } + else + { + return from.equalsIgnoreCase(walletAddress); + } + } + + public boolean isValueChange(String walletAddress) + { + if (hasInput()) + { + decodeTransactionInput(walletAddress); + return transactionInput.isSendOrReceive(this); + } + else + { + return true; + } + } + + private String calculateContractAddress(String account, long nonce) + { + byte[] addressAsBytes = Numeric.hexStringToByteArray(account); + byte[] calculatedAddressAsBytes = + Hash.sha3(RlpEncoder.encode( + new RlpList( + RlpString.create(addressAsBytes), + RlpString.create((nonce))))); + + calculatedAddressAsBytes = Arrays.copyOfRange(calculatedAddressAsBytes, + 12, calculatedAddressAsBytes.length); + return Numeric.toHexString(calculatedAddressAsBytes); + } } diff --git a/build.gradle b/build.gradle index 90dbf107e1..9b76231eb6 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,8 @@ buildscript { } allprojects { + apply from: rootProject.file("codestyle.gradle") + repositories { google() jcenter() diff --git a/build.sh b/build.sh index 1311f9f95e..75cdf3a57f 100644 --- a/build.sh +++ b/build.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -cd dmz && ../gradlew -i build && ../gradlew -i test && cd .. -cd lib && ../gradlew -i build && ../gradlew -i test && cd .. -cd util && ../gradlew -i build && ../gradlew -i test && cd .. -./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt \ No newline at end of file +cd dmz && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +cd lib && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +cd util && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt -x checkStyleMain -x checkStyleTest \ No newline at end of file diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000000..4cde10a1e1 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/codestyle.gradle b/codestyle.gradle new file mode 100644 index 0000000000..e642c669e4 --- /dev/null +++ b/codestyle.gradle @@ -0,0 +1,90 @@ +import java.util.regex.Matcher +import java.util.regex.Pattern + +apply plugin: 'checkstyle' + +checkstyle { + // default path is config/checkstyle/checkstyle.xml + toolVersion "10.3.4" + ignoreFailures false + maxWarnings 0 + configFile rootProject.file("checkstyle.xml") +} + +// Customize all the Checkstyle tasks +tasks.withType(Checkstyle) { + // Specify all files that should be checked + classpath = files() + source "${project.rootDir}" + + reports { + html { + enabled true + destination rootProject.file("build/reports/checkstyle/checkstyle.html") + } + xml { + enabled true + destination rootProject.file("build/reports/checkstyle/checkstyle.xml") + } + } +} + +// Execute Checkstyle on all files +task checkstyle(type: Checkstyle) { +} + +// Execute Checkstyle on all modified files +task checkstyleChanged(type: Checkstyle) { + def changedFiles = getChangedFiles() + include changedFiles +} + +/** + * Get all files that are changed but not deleted nor renamed. + * Compares to master or the specified target branch. + * + * @return list of all changed files + */ +def getChangedFiles() { + // Get the target and source branch + def baseRef = System.getenv("GITHUB_BASE_REF") + def headRef = System.getenv("GITHUB_HEAD_REF") + + def targetBranch = 'origin/' + (baseRef ? baseRef : getParentBranch()) + def sourceBranch = headRef ? 'origin/' + headRef : "" + + // Get list of all changed files including status + def systemOutStream = new ByteArrayOutputStream() + def command = "git diff --name-only $targetBranch $sourceBranch" + command.execute().waitForProcessOutput(systemOutStream, System.err) + def allFiles = systemOutStream.toString().trim().split('\n') + systemOutStream.close() + + allFiles.toList() +} + +/** + * Determines the parent branch. + * + * @return the found parent branch or master if not possible + */ +def getParentBranch() { + def branch = "" + // Get short name of the HEAD branch + def branchDeterminer = "git rev-parse --abbrev-ref HEAD".execute() + branchDeterminer.in.eachLine { line -> branch = line } + branchDeterminer.err.eachLine { line -> println line } + branchDeterminer.waitFor() + // Search all branches for parent + def branchLine = 'git show-branch -a'.execute().text.readLines().find { + it.contains('*') && !(it ==~ ".*\\[$branch[~^\\]].*") + } + try { + // Filter parent branch name + def parent = (branchLine =~ /\[([^~^\]]*)[~^\]]/)[0][1] + return parent + } catch (Exception ignored) { + println "Could not determine parent branch, compare to master" + return "master" + } +} From 2f94a2c7f51ba5e08257e26bb11299cd7f041d8b Mon Sep 17 00:00:00 2001 From: James Brown Date: Thu, 29 Sep 2022 10:05:49 +1000 Subject: [PATCH 108/183] Temporarily remove codestyle dependency --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9b76231eb6..c355f044db 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ buildscript { } allprojects { - apply from: rootProject.file("codestyle.gradle") + //apply from: rootProject.file("codestyle.gradle") repositories { google() From eef507fc616ea97076be72e6a8377be7b6ef762e Mon Sep 17 00:00:00 2001 From: justindg Date: Fri, 30 Sep 2022 17:08:59 -0700 Subject: [PATCH 109/183] Display OpenSea NFT Rarity Data if available (#2851) * Display OpenSea NFT Rarity Data if available. * Add translations --- .../app/entity/opensea/OpenSeaAsset.java | 4 +++ .../app/entity/opensea/Rarity.java | 31 +++++++++++++++++++ .../app/ui/NFTAssetDetailActivity.java | 7 +++++ .../res/layout/activity_nft_asset_detail.xml | 7 +++++ app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-id/strings.xml | 1 + app/src/main/res/values-my/strings.xml | 1 + app/src/main/res/values-vi/strings.xml | 1 + app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 11 files changed, 56 insertions(+) create mode 100644 app/src/main/java/com/alphawallet/app/entity/opensea/Rarity.java diff --git a/app/src/main/java/com/alphawallet/app/entity/opensea/OpenSeaAsset.java b/app/src/main/java/com/alphawallet/app/entity/opensea/OpenSeaAsset.java index 954e2fdb27..635de75260 100644 --- a/app/src/main/java/com/alphawallet/app/entity/opensea/OpenSeaAsset.java +++ b/app/src/main/java/com/alphawallet/app/entity/opensea/OpenSeaAsset.java @@ -88,6 +88,10 @@ public class OpenSeaAsset @Expose public LastSale lastSale; + @SerializedName("rarity_data") + @Expose + public Rarity rarity; + public static class Collection { @SerializedName("stats") diff --git a/app/src/main/java/com/alphawallet/app/entity/opensea/Rarity.java b/app/src/main/java/com/alphawallet/app/entity/opensea/Rarity.java new file mode 100644 index 0000000000..5160fcaec5 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/opensea/Rarity.java @@ -0,0 +1,31 @@ +package com.alphawallet.app.entity.opensea; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Rarity +{ + @SerializedName("strategy_id") + @Expose + public String strategyId; + + @SerializedName("strategy_version") + @Expose + public String strategyVersion; + + @SerializedName("rank") + @Expose + public long rank; + + @SerializedName("score") + @Expose + public double score; + + @SerializedName("max_rank") + @Expose + public long maxRank; + + @SerializedName("tokens_scored") + @Expose + public long tokensScored; +} 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 ea55e0c0c0..a5b0112605 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java @@ -90,6 +90,7 @@ public class NFTAssetDetailActivity extends BaseActivity implements StandardFunc private TokenInfoView tivLastSale; private TokenInfoView tivAveragePrice; private TokenInfoView tivFloorPrice; + private TokenInfoView tivRarityData; private Animation rotation; private ActivityResultLauncher handleTransactionSuccess; private ActivityResultLauncher getGasSettings; @@ -196,6 +197,7 @@ private void initViews() tivLastSale = findViewById(R.id.last_sale); tivAveragePrice = findViewById(R.id.average_price); tivFloorPrice = findViewById(R.id.floor_price); + tivRarityData = findViewById(R.id.rarity); rotation = AnimationUtils.loadAnimation(this, R.anim.rotate_refresh); rotation.setRepeatCount(Animation.INFINITE); @@ -407,6 +409,11 @@ private void loadFromOpenSeaData(OpenSeaAsset openSeaAsset) nftAttributeLayout.bind(token, openSeaAsset.traits, 0); } + if (openSeaAsset.rarity != null && openSeaAsset.rarity.rank > 0) + { + tivRarityData.setValue("#" + openSeaAsset.rarity.rank); + } + if (openSeaAsset.owner != null && openSeaAsset.owner.user != null) { diff --git a/app/src/main/res/layout/activity_nft_asset_detail.xml b/app/src/main/res/layout/activity_nft_asset_detail.xml index c94456e42b..1c6799a04a 100644 --- a/app/src/main/res/layout/activity_nft_asset_detail.xml +++ b/app/src/main/res/layout/activity_nft_asset_detail.xml @@ -119,6 +119,13 @@ android:visibility="gone" custom:tokenInfoLabel="@string/asset_total_supply" /> + + Política de privacidad Términos de servicio Billeteras conectadas + Rareza diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 54b93d97a5..fd742515f4 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -928,4 +928,5 @@ Politique de confidentialité Conditions d\'utilisation Portefeuilles connectés + Rareté diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 564d4680a3..57c5f1b551 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -928,4 +928,5 @@ Kebijakan pribadi Ketentuan Layanan Dompet yang terhubung + Keanehan diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index f52ca143b6..a783aef229 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -949,4 +949,5 @@ %1$s တိုကင် %1$s ချိန်ခွင်လျှာမလုံလောက် ကိုယ်ရေးအချက်အလက်မူဝါဒ + ရှားပါးသည်။ diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 70f0aeb809..48eb779608 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -928,4 +928,5 @@ Không đủ %1$s cân bằng Chuyển giao an toàn Ví kết nối + Việc hiếm có diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 31d044f2bc..bc3dd91c3f 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -915,4 +915,5 @@ 隐私政策 服务条款 已连接的钱包 + 稀有度 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 012b7a61bb..c96b6bdbac 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -988,4 +988,5 @@ | ETH 0 + Rarity From aa1c2e56b3106c4a94520bb84617659661c52773 Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 1 Oct 2022 11:01:47 +1000 Subject: [PATCH 110/183] Temporarily remove lint syntax check --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d771eb99c0..b8195683e4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,4 +21,4 @@ jobs: - name: Run Kotlin lint run: ./gradlew :app:detekt - name: Run Android Lint - run: ./gradlew :app:lintAnalyticsDebug -x checkStyleMain -x checkStyleTest \ No newline at end of file + run: ./gradlew :app:lintAnalyticsDebug \ No newline at end of file From e14c2582360cf3edc39990e0d3e7d945ad689f9f Mon Sep 17 00:00:00 2001 From: justindg Date: Sat, 1 Oct 2022 16:59:35 -0700 Subject: [PATCH 111/183] Swap upgrade: Allow users to filter exchanges and preview multiple quotes from different providers (#2835) * Swap upgrade: allow user to select routes and filter exchanges * Add provider website in a separate line * Redo current price calculation * Prevent fetching route for same src/dest token * Rename for consistency * Fix NumberFormatException crash due to invalid amount * Add checkstyle plugin * Config checkstyle rules * Add CheckStyle workflow * Upload reports * Add configuration and fail the build if has violation * Simulate modification * Remove bad tokens from list (i.e. empty symbol/name) * Ignore trailing or leading whitespaces when sorting * Update unit test * Swap upgrade: allow user to select routes and filter exchanges * Migrate to ProgressInfo to avoid separate observers * Add provider website in a separate line * Fix masking circle color * Prevent fetching route for same src/dest token * Handle no routes found scenario * Rework exchange selection flow * Wrap in nested scrollview * Remove bad tokens from list (i.e. empty symbol/name) * Ignore trailing or leading whitespaces when sorting * Update unit test * Add translations --- app/src/main/AndroidManifest.xml | 10 +- app/src/main/assets/swap_providers_list.json | 110 ++++++++ app/src/main/java/com/alphawallet/app/C.java | 7 - .../app/di/RepositoriesModule.java | 8 + .../alphawallet/app/entity/lifi/Action.java | 50 ++++ .../app/entity/lifi/Connection.java | 79 +----- .../alphawallet/app/entity/lifi/Estimate.java | 100 +++++++ .../alphawallet/app/entity/lifi/FeeCost.java | 25 ++ .../alphawallet/app/entity/lifi/GasCost.java | 19 ++ .../alphawallet/app/entity/lifi/Quote.java | 181 +------------ .../alphawallet/app/entity/lifi/Route.java | 36 +++ .../app/entity/lifi/RouteError.java | 23 ++ .../app/entity/lifi/RouteOptions.java | 33 +++ .../app/entity/lifi/SwapProvider.java | 25 ++ .../alphawallet/app/entity/lifi/Token.java | 91 +++++++ .../repository/PreferenceRepositoryType.java | 5 + .../SharedPreferenceRepository.java | 15 ++ .../app/repository/SwapRepository.java | 36 +++ .../app/repository/SwapRepositoryType.java | 10 + .../alphawallet/app/service/SwapService.java | 177 ++++++++++++- .../app/ui/SelectRouteActivity.java | 201 ++++++++++++++ .../app/ui/SelectSwapProvidersActivity.java | 78 ++++++ .../com/alphawallet/app/ui/SwapActivity.java | 249 ++++++++++++------ .../app/ui/widget/adapter/RouteAdapter.java | 105 ++++++++ .../ui/widget/adapter/SelectChainAdapter.java | 24 +- .../ui/widget/adapter/SelectTokenAdapter.java | 15 +- .../widget/adapter/SwapProviderAdapter.java | 87 ++++++ .../app/ui/widget/adapter/TokenFilter.java | 31 ++- .../entity/OnRouteSelectedListener.java | 6 + .../app/ui/widget/entity/ProgressInfo.java | 28 ++ .../com/alphawallet/app/util/SwapUtils.java | 46 +++- .../app/viewmodel/SelectRouteViewModel.java | 119 +++++++++ .../SelectSwapProvidersViewModel.java | 85 ++++++ .../app/viewmodel/SwapViewModel.java | 127 +++++++-- .../com/alphawallet/app/viewmodel/Tokens.java | 8 +- .../app/widget/SelectTokenDialog.java | 6 +- .../app/widget/StandardHeader.java | 36 ++- .../app/widget/SwapSettingsDialog.java | 54 +++- .../alphawallet/app/widget/TokenSelector.java | 21 +- .../main/res/drawable/ic_swap_horizontal.xml | 10 + .../res/drawable/select_masking_circle.xml | 5 +- .../main/res/layout/activity_select_route.xml | 137 ++++++++++ app/src/main/res/layout/activity_swap.xml | 37 ++- .../main/res/layout/dialog_swap_settings.xml | 17 ++ .../main/res/layout/item_amount_display.xml | 9 +- app/src/main/res/layout/item_chain_select.xml | 4 +- app/src/main/res/layout/item_exchange.xml | 53 ++++ app/src/main/res/layout/item_route.xml | 119 +++++++++ .../main/res/layout/item_standard_header.xml | 28 +- app/src/main/res/values-es/strings.xml | 12 + app/src/main/res/values-fr/strings.xml | 12 + app/src/main/res/values-id/strings.xml | 12 + app/src/main/res/values-my/strings.xml | 12 + app/src/main/res/values-vi/strings.xml | 12 + app/src/main/res/values-zh/strings.xml | 12 + app/src/main/res/values/attrs.xml | 4 + app/src/main/res/values/strings.xml | 15 +- .../app/entity/lifi/ActionTest.java | 23 ++ .../app/entity/lifi/QuoteTest.java | 22 -- .../{ConnectionTest.java => TokenTest.java} | 6 +- .../ui/widget/adapter/TokenFilterTest.java | 22 +- .../alphawallet/app/util/SwapUtilsTest.java | 59 +++-- .../alphawallet/app/viewmodel/TokensTest.java | 13 +- 63 files changed, 2497 insertions(+), 524 deletions(-) create mode 100644 app/src/main/assets/swap_providers_list.json create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/Action.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/Estimate.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/FeeCost.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/GasCost.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/Route.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/RouteError.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/RouteOptions.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/SwapProvider.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/lifi/Token.java create mode 100644 app/src/main/java/com/alphawallet/app/repository/SwapRepository.java create mode 100644 app/src/main/java/com/alphawallet/app/repository/SwapRepositoryType.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/SelectRouteActivity.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/SelectSwapProvidersActivity.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/adapter/RouteAdapter.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/adapter/SwapProviderAdapter.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/entity/OnRouteSelectedListener.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/entity/ProgressInfo.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/SelectRouteViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java create mode 100644 app/src/main/res/drawable/ic_swap_horizontal.xml create mode 100644 app/src/main/res/layout/activity_select_route.xml create mode 100644 app/src/main/res/layout/item_exchange.xml create mode 100644 app/src/main/res/layout/item_route.xml create mode 100644 app/src/test/java/com/alphawallet/app/entity/lifi/ActionTest.java delete mode 100644 app/src/test/java/com/alphawallet/app/entity/lifi/QuoteTest.java rename app/src/test/java/com/alphawallet/app/entity/lifi/{ConnectionTest.java => TokenTest.java} (85%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d3bdc3f18a..69a9ec1da4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -307,6 +307,14 @@ android:label="Native Swap" android:windowSoftInputMode="adjustResize" /> + + + + @@ -314,7 +322,7 @@ - + diff --git a/app/src/main/assets/swap_providers_list.json b/app/src/main/assets/swap_providers_list.json new file mode 100644 index 0000000000..6bfd9baaf9 --- /dev/null +++ b/app/src/main/assets/swap_providers_list.json @@ -0,0 +1,110 @@ +[ + { + "key": "dodo", + "name": "DODO", + "url": "https://dodoex.io/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/dodo.png" + }, + { + "key": "paraswap", + "name": "ParaSwap", + "url": "https://www.paraswap.io/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/paraswap.png" + }, + { + "key": "1inch", + "name": "1inch", + "url": "https://1inch.io/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/oneinch.png" + }, + { + "key": "openocean", + "name": "OpenOcean", + "url": "https://openocean.finance/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/openocean.png" + }, + { + "key": "0x", + "name": "0x", + "url": "https://www.0x.org/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/zerox.png" + }, + { + "key": "superfluid", + "name": "Superfluid", + "url": "https://www.superfluid.finance/", + "logoURI": "https://www.superfluid.finance/icons/icon-72x72.png" + }, + { + "key": "uniswap", + "name": "UniswapV2", + "url": "https://uniswap.org/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/uniswap.png" + }, + { + "key": "quickswap", + "name": "QuickSwap", + "url": "https://quickswap.exchange/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/quick.png" + }, + { + "key": "pancakeswap", + "name": "PancakeSwap", + "url": "https://pancakeswap.finance/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/pancake.png" + }, + { + "key": "honeyswap", + "name": "Honeyswap", + "url": "https://honeyswap.org/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/honey.png" + }, + { + "key": "spookyswap", + "name": "SpookySwap", + "url": "https://spooky.fi/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/spooky.png" + }, + { + "key": "spiritswap", + "name": "SpiritSwap", + "url": "https://www.spiritswap.finance/", + "logoURI": "https://github.com/Layer3Org/spiritswap-tokens-list-icon/blob/master/token-list/images/inspirit.png?raw=true" + }, + { + "key": "solarbeam", + "name": "Solarbeam", + "url": "https://solarbeam.io/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/solarbeam.png" + }, + { + "key": "jswap", + "name": "JSwap", + "url": "https://app.jswap.finance/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/jswap.png" + }, + { + "key": "cronaswap", + "name": "CronaSwap", + "url": "https://app.cronaswap.org/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/cronaswap.png" + }, + { + "key": "voltage", + "name": "Voltage", + "url": "https://app.voltage.finance/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/voltage.png" + }, + { + "key": "ubeswap", + "name": "UbeSwap", + "url": "https://ubeswap.org/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/ubeswap.png" + }, + { + "key": "sushiswap", + "name": "SushiSwap", + "url": "https://sushi.com/", + "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/sushi.png" + } +] \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 8c39765503..b887c46b91 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -321,13 +321,6 @@ public enum TokenStatus { public static final String OPENSEA_SINGLE_ASSET_API_RINKEBY = "https://testnets-api.opensea.io/api/v1/asset/"; public static final String OPENSEA_SINGLE_ASSET_API_MATIC = "https://api.opensea.io/api/v2/metadata/matic/"; - // Progress Info - public interface ProgressInfo { - int FETCHING_CHAINS = 1; - int FETCHING_CONNECTIONS = 2; - int FETCHING_QUOTE = 3; - } - //Timing public static long CONNECT_TIMEOUT = 10; //Seconds public static long READ_TIMEOUT = 10; diff --git a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java index 127d9e6be5..1c45aa1082 100644 --- a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java +++ b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java @@ -12,6 +12,8 @@ import com.alphawallet.app.repository.OnRampRepositoryType; import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.repository.SharedPreferenceRepository; +import com.alphawallet.app.repository.SwapRepository; +import com.alphawallet.app.repository.SwapRepositoryType; import com.alphawallet.app.repository.TokenLocalSource; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.repository.TokenRepositoryType; @@ -117,6 +119,12 @@ OnRampRepositoryType provideOnRampRepository(@ApplicationContext Context context return new OnRampRepository(context, analyticsServiceType); } + @Singleton + @Provides + SwapRepositoryType provideSwapRepository(@ApplicationContext Context context) { + return new SwapRepository(context); + } + @Singleton @Provides CoinbasePayRepositoryType provideCoinbasePayRepository() { diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Action.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Action.java new file mode 100644 index 0000000000..110be10c1a --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Action.java @@ -0,0 +1,50 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class Action +{ + @SerializedName("fromChainId") + @Expose + public long fromChainId; + + @SerializedName("toChainId") + @Expose + public long toChainId; + + @SerializedName("fromToken") + @Expose + public Token fromToken; + + @SerializedName("toToken") + @Expose + public Token toToken; + + @SerializedName("fromAmount") + @Expose + public String fromAmount; + + @SerializedName("slippage") + @Expose + public double slippage; + + @SerializedName("fromAddress") + @Expose + public String fromAddress; + + @SerializedName("toAddress") + @Expose + public String toAddress; + + public String getCurrentPrice() + { + return new BigDecimal(fromToken.priceUSD) + .divide(new BigDecimal(toToken.priceUSD), 4, RoundingMode.DOWN) + .stripTrailingZeros() + .toPlainString(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java index 9d5166d1b6..01fe4a324c 100644 --- a/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Connection.java @@ -4,7 +4,6 @@ import com.google.gson.annotations.SerializedName; import java.util.List; -import java.util.Objects; public class Connection { @@ -18,83 +17,9 @@ public class Connection @SerializedName("fromTokens") @Expose - public List fromTokens; + public List fromTokens; @SerializedName("toTokens") @Expose - public List toTokens; - - public static class LToken - { - @SerializedName("address") - @Expose - public String address; - - @SerializedName("symbol") - @Expose - public String symbol; - - @SerializedName("decimals") - @Expose - public long decimals; - - @SerializedName("chainId") - @Expose - public long chainId; - - @SerializedName("name") - @Expose - public String name; - - @SerializedName("coinKey") - @Expose - public String coinKey; - - @SerializedName("priceUSD") - @Expose - public String priceUSD; - - @SerializedName("logoURI") - @Expose - public String logoURI; - - public String balance; - public double fiatEquivalent; - - @Override - public boolean equals(Object o) - { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - LToken lToken = (LToken) o; - return address.equals(lToken.address) && symbol.equals(lToken.symbol); - } - - @Override - public int hashCode() - { - return Objects.hash(address, symbol); - } - - // Note: In the LIFI API, the native token has either of these two addresses. - public boolean isNativeToken() - { - return address.equalsIgnoreCase("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") || - address.equalsIgnoreCase("0x0000000000000000000000000000000000000000"); - } - - public double getFiatValue() - { - try - { - double value = Double.parseDouble(balance); - double priceUSD = Double.parseDouble(this.priceUSD); - return value * priceUSD; - } - catch (NumberFormatException | NullPointerException e) - { - return 0.0; - } - } - } + public List toTokens; } diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Estimate.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Estimate.java new file mode 100644 index 0000000000..ab63b81844 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Estimate.java @@ -0,0 +1,100 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.ArrayList; + +public class Estimate +{ + @SerializedName("fromAmount") + @Expose + public String fromAmount; + + @SerializedName("toAmount") + @Expose + public String toAmount; + + @SerializedName("toAmountMin") + @Expose + public String toAmountMin; + + @SerializedName("approvalAddress") + @Expose + public String approvalAddress; + + @SerializedName("executionDuration") + @Expose + public long executionDuration; + + @SerializedName("feeCosts") + @Expose + public ArrayList feeCosts; + + @SerializedName("gasCosts") + @Expose + public ArrayList gasCosts; + + @SerializedName("data") + @Expose + public Data data; + + @SerializedName("fromAmountUSD") + @Expose + public String fromAmountUSD; + + @SerializedName("toAmountUSD") + @Expose + public String toAmountUSD; + + public static class Data + { + @SerializedName("blockNumber") + @Expose + public long blockNumber; + + @SerializedName("network") + @Expose + public long network; + + @SerializedName("srcToken") + @Expose + public String srcToken; + + @SerializedName("srcDecimals") + @Expose + public long srcDecimals; + + @SerializedName("srcAmount") + @Expose + public String srcAmount; + + @SerializedName("destToken") + @Expose + public String destToken; + + @SerializedName("destDecimals") + @Expose + public long destDecimals; + + @SerializedName("destAmount") + @Expose + public String destAmount; + + @SerializedName("gasCostUSD") + @Expose + public String gasCostUSD; + + @SerializedName("gasCost") + @Expose + public String gasCost; + + @SerializedName("buyAmount") + @Expose + public String buyAmount; + + @SerializedName("sellAmount") + @Expose + public String sellAmount; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/FeeCost.java b/app/src/main/java/com/alphawallet/app/entity/lifi/FeeCost.java new file mode 100644 index 0000000000..bbbd5cd645 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/FeeCost.java @@ -0,0 +1,25 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.ArrayList; + +public class FeeCost +{ + @SerializedName("name") + @Expose + public String name; + + @SerializedName("percentage") + @Expose + public String percentage; + + @SerializedName("token") + @Expose + public Token token; + + @SerializedName("amount") + @Expose + public String amount; +} \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/GasCost.java b/app/src/main/java/com/alphawallet/app/entity/lifi/GasCost.java new file mode 100644 index 0000000000..d2ccd5b39b --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/GasCost.java @@ -0,0 +1,19 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class GasCost +{ + @SerializedName("amount") + @Expose + public String amount; + + @SerializedName("amountUSD") + @Expose + public String amountUSD; + + @SerializedName("token") + @Expose + public Token token; +} \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java index 2e0d1cf6d2..fc2d80e4f1 100644 --- a/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Quote.java @@ -3,9 +3,6 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; -import java.math.BigDecimal; -import java.util.ArrayList; - public class Quote { @SerializedName("id") @@ -22,186 +19,16 @@ public class Quote @SerializedName("toolDetails") @Expose - public ToolDetails toolDetails; - - public static class ToolDetails - { - @SerializedName("key") - @Expose - public String key; - - @SerializedName("name") - @Expose - public String name; - - @SerializedName("logoURI") - @Expose - public String logoURI; - } + public SwapProvider swapProvider; @SerializedName("action") @Expose public Action action; - public static class Action - { - @SerializedName("fromChainId") - @Expose - public long fromChainId; - - @SerializedName("toChainId") - @Expose - public long toChainId; - - @SerializedName("fromToken") - @Expose - public Connection.LToken fromToken; - - @SerializedName("toToken") - @Expose - public Connection.LToken toToken; - - @SerializedName("fromAmount") - @Expose - public String fromAmount; - - @SerializedName("slippage") - @Expose - public double slippage; - - @SerializedName("fromAddress") - @Expose - public String fromAddress; - - @SerializedName("toAddress") - @Expose - public String toAddress; - } - @SerializedName("estimate") @Expose public Estimate estimate; - public static class Estimate - { - @SerializedName("fromAmount") - @Expose - public String fromAmount; - - @SerializedName("toAmount") - @Expose - public String toAmount; - - @SerializedName("toAmountMin") - @Expose - public String toAmountMin; - - @SerializedName("approvalAddress") - @Expose - public String approvalAddress; - - @SerializedName("executionDuration") - @Expose - public long executionDuration; - -// @SerializedName("feeCosts") -// @Expose -// public JSONArray feeCosts; - - @SerializedName("gasCosts") - @Expose - public ArrayList gasCosts; - - public static class GasCost - { - @SerializedName("amount") - @Expose - public String amount; - - @SerializedName("amountUSD") - @Expose - public String amountUSD; - - @SerializedName("token") - @Expose - public Token token; - - public static class Token - { - @SerializedName("symbol") - @Expose - public String symbol; - - @SerializedName("decimals") - @Expose - public long decimals; - } - } - - @SerializedName("data") - @Expose - public Data data; - - public static class Data - { - @SerializedName("blockNumber") - @Expose - public long blockNumber; - - @SerializedName("network") - @Expose - public long network; - - @SerializedName("srcToken") - @Expose - public String srcToken; - - @SerializedName("srcDecimals") - @Expose - public long srcDecimals; - - @SerializedName("srcAmount") - @Expose - public String srcAmount; - - @SerializedName("destToken") - @Expose - public String destToken; - - @SerializedName("destDecimals") - @Expose - public long destDecimals; - - @SerializedName("destAmount") - @Expose - public String destAmount; - - @SerializedName("gasCostUSD") - @Expose - public String gasCostUSD; - - @SerializedName("gasCost") - @Expose - public String gasCost; - - @SerializedName("buyAmount") - @Expose - public String buyAmount; - - @SerializedName("sellAmount") - @Expose - public String sellAmount; - } - - @SerializedName("fromAmountUSD") - @Expose - public String fromAmountUSD; - - @SerializedName("toAmountUSD") - @Expose - public String toAmountUSD; - } - @SerializedName("transactionRequest") @Expose public TransactionRequest transactionRequest; @@ -236,10 +63,4 @@ public static class TransactionRequest @Expose public String gasPrice; } - - public String getCurrentPrice() - { - return new BigDecimal(action.fromToken.priceUSD) - .multiply(new BigDecimal(action.toToken.priceUSD)).toString(); - } } diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Route.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Route.java new file mode 100644 index 0000000000..97719ea00c --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Route.java @@ -0,0 +1,36 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class Route +{ + @SerializedName("gasCostUSD") + @Expose + public String gasCostUSD; + + @SerializedName("steps") + @Expose + public List steps; + + @SerializedName("tags") + @Expose + public List tags; + + public static class Step + { + @SerializedName("toolDetails") + @Expose + public SwapProvider swapProvider; + + @SerializedName("action") + @Expose + public Action action; + + @SerializedName("estimate") + @Expose + public Estimate estimate; + } +} diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/RouteError.java b/app/src/main/java/com/alphawallet/app/entity/lifi/RouteError.java new file mode 100644 index 0000000000..aa6135d733 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/RouteError.java @@ -0,0 +1,23 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class RouteError +{ + @SerializedName("tool") + @Expose + public String tool; + + @SerializedName("message") + @Expose + public String message; + + @SerializedName("errorType") + @Expose + public String errorType; + + @SerializedName("code") + @Expose + public String code; +} diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/RouteOptions.java b/app/src/main/java/com/alphawallet/app/entity/lifi/RouteOptions.java new file mode 100644 index 0000000000..99882f661a --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/RouteOptions.java @@ -0,0 +1,33 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.Gson; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +public class RouteOptions +{ + public String integrator; + public String slippage; + public Exchanges exchanges; + public String order; + + public RouteOptions() + { + this.exchanges = new Exchanges(); + } + + public static class Exchanges + { + public List allow = new ArrayList<>(); + } + + public JSONObject getJson() throws JSONException + { + String json = new Gson().toJson(this); + return new JSONObject(json); + } +} diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/SwapProvider.java b/app/src/main/java/com/alphawallet/app/entity/lifi/SwapProvider.java new file mode 100644 index 0000000000..6b01e6a292 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/SwapProvider.java @@ -0,0 +1,25 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class SwapProvider +{ + @SerializedName("key") + @Expose + public String key; + + @SerializedName("name") + @Expose + public String name; + + @SerializedName("logoURI") + @Expose + public String logoURI; + + @SerializedName("url") + @Expose + public String url; + + public boolean isChecked; +} \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/entity/lifi/Token.java b/app/src/main/java/com/alphawallet/app/entity/lifi/Token.java new file mode 100644 index 0000000000..83ec1225a6 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/lifi/Token.java @@ -0,0 +1,91 @@ +package com.alphawallet.app.entity.lifi; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.Objects; + +public class Token +{ + @SerializedName("address") + @Expose + public String address; + + @SerializedName("symbol") + @Expose + public String symbol; + + @SerializedName("decimals") + @Expose + public long decimals; + + @SerializedName("chainId") + @Expose + public long chainId; + + @SerializedName("name") + @Expose + public String name; + + @SerializedName("coinKey") + @Expose + public String coinKey; + + @SerializedName("priceUSD") + @Expose + public String priceUSD; + + @SerializedName("logoURI") + @Expose + public String logoURI; + + public String balance; + public double fiatEquivalent; + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Token lToken = (Token) o; + return address.equals(lToken.address) && symbol.equals(lToken.symbol); + } + + @Override + public int hashCode() + { + return Objects.hash(address, symbol); + } + + // Note: In the LIFI API, the native token has either of these two addresses. + public boolean isNativeToken() + { + return address.equalsIgnoreCase("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") || + address.equalsIgnoreCase("0x0000000000000000000000000000000000000000"); + } + + public double getFiatValue() + { + try + { + double value = Double.parseDouble(balance); + double priceUSD = Double.parseDouble(this.priceUSD); + return value * priceUSD; + } + catch (NumberFormatException | NullPointerException e) + { + return 0.0; + } + } + + public boolean isSimilarTo(com.alphawallet.app.entity.tokens.Token aToken, String walletAddress) + { + if (this.chainId == aToken.tokenInfo.chainId + && this.address.equalsIgnoreCase(aToken.getAddress())) + { + return true; + } + + return aToken.getAddress().equalsIgnoreCase(walletAddress) && isNativeToken(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java index 99b177faad..5f67dcbe3b 100644 --- a/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java +++ b/app/src/main/java/com/alphawallet/app/repository/PreferenceRepositoryType.java @@ -2,6 +2,8 @@ import com.alphawallet.app.entity.CurrencyItem; +import java.util.Set; + public interface PreferenceRepositoryType { String getCurrentWalletAddress(); @@ -96,4 +98,7 @@ public interface PreferenceRepositoryType { boolean isNewWallet(String address); void setNewWallet(String address, boolean isNewWallet); + + Set getSelectedSwapProviders(); + void setSelectedSwapProviders(Set swapProviders); } diff --git a/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java b/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java index 61fa1e01f9..bc48da6555 100644 --- a/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/SharedPreferenceRepository.java @@ -10,7 +10,9 @@ import com.alphawallet.app.C; import com.alphawallet.app.entity.CurrencyItem; +import java.util.HashSet; import java.util.Locale; +import java.util.Set; public class SharedPreferenceRepository implements PreferenceRepositoryType { private static final String CURRENT_ACCOUNT_ADDRESS_KEY = "current_account_address"; @@ -41,6 +43,7 @@ public class SharedPreferenceRepository implements PreferenceRepositoryType { public static final String MARSHMALLOW_SUPPORT_WARNING = "marshmallow_version_support_warning_shown"; private static final String LAST_FRAGMENT_ID = "lastfrag_id"; private static final String LAST_VERSION_CODE = "last_version_code"; + private static final String SELECTED_SWAP_PROVIDERS_KEY = "selected_exchanges"; private static final String RATE_APP_SHOWN = "rate_us_shown"; private static final String LAUNCH_COUNT = "launch_count"; @@ -379,6 +382,18 @@ public void setNewWallet(String address, boolean isNewWallet) pref.edit().putBoolean(keyOf(address), isNewWallet).apply(); } + @Override + public Set getSelectedSwapProviders() + { + return pref.getStringSet(SELECTED_SWAP_PROVIDERS_KEY, new HashSet<>()); + } + + @Override + public void setSelectedSwapProviders(Set swapProviders) + { + pref.edit().putStringSet(SELECTED_SWAP_PROVIDERS_KEY, swapProviders).apply(); + } + @NonNull private String keyOf(String address) { diff --git a/app/src/main/java/com/alphawallet/app/repository/SwapRepository.java b/app/src/main/java/com/alphawallet/app/repository/SwapRepository.java new file mode 100644 index 0000000000..155aa473fb --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/repository/SwapRepository.java @@ -0,0 +1,36 @@ +package com.alphawallet.app.repository; + +import android.content.Context; + +import com.alphawallet.app.entity.lifi.SwapProvider; +import com.alphawallet.app.util.Utils; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.util.List; + +public class SwapRepository implements SwapRepositoryType +{ + public static final String FETCH_CHAINS = "https://li.quest/v1/chains"; + public static final String FETCH_TOKENS = "https://li.quest/v1/connections"; + public static final String FETCH_QUOTE = "https://li.quest/v1/quote"; + public static final String FETCH_TOOLS = "https://li.quest/v1/tools"; + public static final String FETCH_ROUTES = "https://li.quest/v1/advanced/routes"; + private static final String SWAP_PROVIDERS_FILENAME = "swap_providers_list.json"; + + private final Context context; + + public SwapRepository(Context context) + { + this.context = context; + } + + @Override + public List getProviders() + { + return new Gson().fromJson(Utils.loadJSONFromAsset(context, SWAP_PROVIDERS_FILENAME), + new TypeToken>() + { + }.getType()); + } +} diff --git a/app/src/main/java/com/alphawallet/app/repository/SwapRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/SwapRepositoryType.java new file mode 100644 index 0000000000..978babf52b --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/repository/SwapRepositoryType.java @@ -0,0 +1,10 @@ +package com.alphawallet.app.repository; + +import com.alphawallet.app.entity.lifi.SwapProvider; + +import java.util.List; + +public interface SwapRepositoryType +{ + public List getProviders(); +} diff --git a/app/src/main/java/com/alphawallet/app/service/SwapService.java b/app/src/main/java/com/alphawallet/app/service/SwapService.java index 512947c6dd..fab5804e2e 100644 --- a/app/src/main/java/com/alphawallet/app/service/SwapService.java +++ b/app/src/main/java/com/alphawallet/app/service/SwapService.java @@ -3,24 +3,29 @@ import android.net.Uri; import com.alphawallet.app.C; -import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.RouteOptions; +import com.alphawallet.app.entity.lifi.Token; +import com.alphawallet.app.repository.SwapRepository; import com.alphawallet.app.util.BalanceUtils; import com.alphawallet.app.util.JsonUtils; +import org.json.JSONException; +import org.json.JSONObject; + import java.util.Objects; +import java.util.Set; import java.util.concurrent.TimeUnit; import io.reactivex.Single; +import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.ResponseBody; import timber.log.Timber; public class SwapService { - private static final String FETCH_CHAINS = "https://li.quest/v1/chains"; - private static final String FETCH_TOKENS = "https://li.quest/v1/connections"; - private static final String SWAP_TOKEN = "https://li.quest/v1/quote"; private static OkHttpClient httpClient; public SwapService() @@ -38,8 +43,18 @@ private Request buildRequest(String api) Request.Builder requestB = new Request.Builder() .url(api) .header("User-Agent", "Chrome/74.0.3729.169") - .method("GET", null) - .addHeader("Content-Type", "application/json"); + .addHeader("Content-Type", "application/json") + .get(); + return requestB.build(); + } + + private Request buildPostRequest(String api, RequestBody requestBody) + { + Request.Builder requestB = new Request.Builder() + .url(api) + .header("User-Agent", "Chrome/74.0.3729.169") + .addHeader("Content-Type", "application/json") + .post(requestBody); return requestB.build(); } @@ -69,49 +84,185 @@ private String executeRequest(String api) return JsonUtils.EMPTY_RESULT; } + private String executePostRequest(String api, RequestBody requestBody) + { + try (okhttp3.Response response = httpClient.newCall(buildPostRequest(api, requestBody)).execute()) + { + if (response.isSuccessful()) + { + ResponseBody responseBody = response.body(); + if (responseBody != null) + { + return responseBody.string(); + } + } + else + { + return Objects.requireNonNull(response.body()).string(); + } + } + catch (Exception e) + { + Timber.e(e); + return e.getMessage(); + } + + return JsonUtils.EMPTY_RESULT; + } + public Single getChains() { return Single.fromCallable(this::fetchChains); } + public Single getTools() + { + return Single.fromCallable(this::fetchTools); + } + public Single getConnections(long from, long to) { return Single.fromCallable(() -> fetchPairs(from, to)); } - public Single getQuote(Connection.LToken source, Connection.LToken dest, String address, String amount, String slippage) + public Single getQuote(Token source, + Token dest, + String address, + String amount, + String slippage, + String allowExchanges) + { + return Single.fromCallable(() -> fetchQuote(source, dest, address, amount, slippage, allowExchanges)); + } + + public Single getRoutes(Token source, + Token dest, + String address, + String amount, + String slippage, + Set exchanges) { - return Single.fromCallable(() -> fetchQuote(source, dest, address, amount, slippage)); + return Single.fromCallable(() -> fetchRoutes(source, dest, address, amount, slippage, exchanges)); + } + + public Single getRoutes(String fromChainId, + String toChainId, + String fromTokenAddress, + String toTokenAddress, + String fromAddress, + String fromAmount, + String slippage, + Set exchanges) + { + return Single.fromCallable(() -> fetchRoutes(fromChainId, toChainId, fromTokenAddress, toTokenAddress, fromAddress, fromAmount, slippage, exchanges)); } public String fetchChains() { Uri.Builder builder = new Uri.Builder(); - builder.encodedPath(FETCH_CHAINS); + builder.encodedPath(SwapRepository.FETCH_CHAINS); + return executeRequest(builder.build().toString()); + } + + public String fetchTools() + { + Uri.Builder builder = new Uri.Builder(); + builder.encodedPath(SwapRepository.FETCH_TOOLS); return executeRequest(builder.build().toString()); } public String fetchPairs(long fromChain, long toChain) { Uri.Builder builder = new Uri.Builder(); - builder.encodedPath(FETCH_TOKENS) + builder.encodedPath(SwapRepository.FETCH_TOKENS) .appendQueryParameter("fromChain", String.valueOf(fromChain)) .appendQueryParameter("toChain", String.valueOf(toChain)); return executeRequest(builder.build().toString()); } - public String fetchQuote(Connection.LToken source, Connection.LToken dest, String address, String amount, String slippage) + public String fetchQuote(Token source, + Token dest, + String address, + String amount, + String slippage, + String allowExchanges) { Uri.Builder builder = new Uri.Builder(); - builder.encodedPath(SWAP_TOKEN) + builder.encodedPath(SwapRepository.FETCH_QUOTE) .appendQueryParameter("fromChain", String.valueOf(source.chainId)) .appendQueryParameter("toChain", String.valueOf(dest.chainId)) .appendQueryParameter("fromToken", source.address) .appendQueryParameter("toToken", dest.address) .appendQueryParameter("fromAddress", address) .appendQueryParameter("fromAmount", BalanceUtils.getRawFormat(amount, source.decimals)) -// .appendQueryParameter("order", "RECOMMENDED") + .appendQueryParameter("allowExchanges", allowExchanges) .appendQueryParameter("slippage", slippage); return executeRequest(builder.build().toString()); } + + public String fetchRoutes(Token source, + Token dest, + String address, + String amount, + String slippage, + Set exchanges) + { + RouteOptions options = new RouteOptions(); + options.slippage = slippage; + options.exchanges.allow.addAll(exchanges); + + RequestBody body = null; + try + { + JSONObject json = new JSONObject(); + json.put("fromChainId", String.valueOf(source.chainId)); + json.put("toChainId", String.valueOf(dest.chainId)); + json.put("fromTokenAddress", source.address); + json.put("toTokenAddress", dest.address); + json.put("fromAddress", address); + json.put("fromAmount", BalanceUtils.getRawFormat(amount, source.decimals)); + json.put("options", options.getJson()); + body = RequestBody.create(json.toString(), MediaType.parse("application/json")); + } + catch (JSONException e) + { + Timber.e(e); + } + + return executePostRequest(SwapRepository.FETCH_ROUTES, body); + } + + public String fetchRoutes(String fromChainId, + String toChainId, + String fromTokenAddress, + String toTokenAddress, + String fromAddress, + String fromAmount, + String slippage, + Set exchanges) + { + RouteOptions options = new RouteOptions(); + options.slippage = slippage; + options.exchanges.allow.addAll(exchanges); + + RequestBody body = null; + try + { + JSONObject json = new JSONObject(); + json.put("fromChainId", fromChainId); + json.put("toChainId", toChainId); + json.put("fromTokenAddress", fromTokenAddress); + json.put("toTokenAddress", toTokenAddress); + json.put("fromAddress", fromAddress); + json.put("fromAmount", fromAmount); + json.put("options", options.getJson()); + body = RequestBody.create(json.toString(), MediaType.parse("application/json")); + } + catch (JSONException e) + { + Timber.e(e); + } + + return executePostRequest(SwapRepository.FETCH_ROUTES, body); + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/SelectRouteActivity.java b/app/src/main/java/com/alphawallet/app/ui/SelectRouteActivity.java new file mode 100644 index 0000000000..c29c1bfed2 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/SelectRouteActivity.java @@ -0,0 +1,201 @@ +package com.alphawallet.app.ui; + +import android.content.Intent; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.lifi.Route; +import com.alphawallet.app.ui.widget.adapter.RouteAdapter; +import com.alphawallet.app.ui.widget.entity.ProgressInfo; +import com.alphawallet.app.util.BalanceUtils; +import com.alphawallet.app.util.SwapUtils; +import com.alphawallet.app.viewmodel.SelectRouteViewModel; +import com.alphawallet.app.widget.AWalletAlertDialog; +import com.alphawallet.app.widget.AddressIcon; +import com.google.android.material.button.MaterialButton; + +import java.util.List; +import java.util.Locale; + +import dagger.hilt.android.AndroidEntryPoint; + +@AndroidEntryPoint +public class SelectRouteActivity extends BaseActivity +{ + private static final long GET_ROUTES_INTERVAL_MS = 30000; + private static final long COUNTDOWN_INTERVAL_MS = 1000; + private SelectRouteViewModel viewModel; + private RecyclerView recyclerView; + private TextView fromAmount; + private TextView fromSymbol; + private TextView currentPrice; + private TextView countdownText; + private LinearLayout noRoutesLayout; + private MaterialButton selectExchangesBtn; + private AddressIcon fromTokenIcon; + private AWalletAlertDialog progressDialog; + private CountDownTimer getRoutesTimer; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_select_route); + + toolbar(); + + setTitle(getString(R.string.title_select_route)); + + initViews(); + + initViewModel(); + + initTimer(); + } + + @Override + protected void onResume() + { + getRoutes(); + super.onResume(); + } + + @Override + protected void onPause() + { + if (getRoutesTimer != null) + { + getRoutesTimer.cancel(); + } + super.onPause(); + } + + private void initViews() + { + recyclerView = findViewById(R.id.list_routes); + fromAmount = findViewById(R.id.from_amount); + fromSymbol = findViewById(R.id.from_symbol); + fromTokenIcon = findViewById(R.id.from_token_icon); + currentPrice = findViewById(R.id.current_price); + countdownText = findViewById(R.id.text_countdown); + noRoutesLayout = findViewById(R.id.layout_no_routes_found); + selectExchangesBtn = findViewById(R.id.btn_select_exchanges); + selectExchangesBtn.setOnClickListener(v -> { + Intent intent = new Intent(this, SelectSwapProvidersActivity.class); + startActivity(intent); + }); + + progressDialog = new AWalletAlertDialog(this); + progressDialog.setCancelable(false); + progressDialog.setProgressMode(); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this) + .get(SelectRouteViewModel.class); + viewModel.routes().observe(this, this::onRoutes); + viewModel.progressInfo().observe(this, this::onProgressInfo); + } + + private void initTimer() + { + getRoutesTimer = new CountDownTimer(GET_ROUTES_INTERVAL_MS, COUNTDOWN_INTERVAL_MS) + { + @Override + public void onTick(long millisUntilFinished) + { + String format = millisUntilFinished < 10000 ? "0:0%d" : "0:%d"; + String time = String.format(Locale.ENGLISH, format, millisUntilFinished / 1000); + countdownText.setText(getString(R.string.label_available_routes, time)); + } + + @Override + public void onFinish() + { + getRoutes(); + } + }; + } + + private void getRoutes() + { + String fromChainId = getIntent().getStringExtra("fromChainId"); + String toChainId = getIntent().getStringExtra("toChainId"); + String fromTokenAddress = getIntent().getStringExtra("fromTokenAddress"); + String toTokenAddress = getIntent().getStringExtra("toTokenAddress"); + String fromAddress = getIntent().getStringExtra("fromAddress"); + String fromAmount = getIntent().getStringExtra("fromAmount"); + long fromTokenDecimals = getIntent().getLongExtra("fromTokenDecimals", -1); + String slippage = getIntent().getStringExtra("slippage"); + String fromSymbol = getIntent().getStringExtra("fromTokenSymbol"); + String fromTokenLogoUri = getIntent().getStringExtra("fromTokenLogoUri"); + + this.fromAmount.setText(BalanceUtils.getShortFormat(fromAmount, fromTokenDecimals)); + this.fromSymbol.setText(fromSymbol); + this.fromTokenIcon.bindData(fromTokenLogoUri, Long.parseLong(fromChainId), fromTokenAddress, fromSymbol); + + viewModel.getRoutes(fromChainId, toChainId, fromTokenAddress, toTokenAddress, fromAddress, fromAmount, slippage, viewModel.getPreferredExchanges()); + } + + private void onRoutes(List routes) + { + processRoutes(routes); + + getRoutesTimer.start(); + } + + private void processRoutes(List routeList) + { + RouteAdapter adapter = new RouteAdapter(this, routeList, provider -> { + Intent intent = new Intent(); + intent.putExtra("provider", provider); + setResult(RESULT_OK, intent); + finish(); + }); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(adapter); + + if (!routeList.isEmpty()) + { + Route route = routeList.get(0); + currentPrice.setText(SwapUtils.getFormattedCurrentPrice(route.steps.get(0).action)); + noRoutesLayout.setVisibility(View.GONE); + } + else + { + currentPrice.setText(R.string.NA); + noRoutesLayout.setVisibility(View.VISIBLE); + } + } + + private void onProgressInfo(ProgressInfo progressInfo) + { + if (progressInfo.shouldShow()) + { + progressDialog.setMessage(progressInfo.getMessage()); + progressDialog.show(); + } + else + { + progressDialog.dismiss(); + } + } + + @Override + public void onBackPressed() + { + setResult(RESULT_CANCELED); + super.onBackPressed(); + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/SelectSwapProvidersActivity.java b/app/src/main/java/com/alphawallet/app/ui/SelectSwapProvidersActivity.java new file mode 100644 index 0000000000..c70087e814 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/SelectSwapProvidersActivity.java @@ -0,0 +1,78 @@ +package com.alphawallet.app.ui; + +import android.os.Bundle; +import android.view.MenuItem; +import android.widget.Toast; + +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.alphawallet.app.R; +import com.alphawallet.app.ui.widget.adapter.SwapProviderAdapter; +import com.alphawallet.app.viewmodel.SelectSwapProvidersViewModel; + +import dagger.hilt.android.AndroidEntryPoint; + +@AndroidEntryPoint +public class SelectSwapProvidersActivity extends BaseActivity +{ + private SelectSwapProvidersViewModel viewModel; + private SwapProviderAdapter adapter; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + setContentView(R.layout.basic_list_activity); + + toolbar(); + + setTitle(getString(R.string.title_select_exchanges)); + + initViewModel(); + + initViews(); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this) + .get(SelectSwapProvidersViewModel.class); + } + + private void initViews() + { + RecyclerView recyclerView = findViewById(R.id.list); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + adapter = new SwapProviderAdapter(viewModel.getSwapProviders()); + recyclerView.setAdapter(adapter); + } + + @Override + public void onBackPressed() + { + if (viewModel.savePreferences(adapter.getExchanges())) + { + setResult(RESULT_OK); + super.onBackPressed(); + } + else + { + Toast.makeText(this, getString(R.string.message_select_one_exchange), Toast.LENGTH_SHORT).show(); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) + { + if (item.getItemId() == android.R.id.home) + { + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index f066cee50b..fe122797df 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -2,7 +2,7 @@ import android.content.Intent; import android.os.Bundle; -import android.os.Handler; +import android.os.CountDownTimer; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; @@ -12,6 +12,7 @@ import android.widget.TextView; import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.Nullable; import androidx.lifecycle.ViewModelProvider; @@ -25,8 +26,9 @@ import com.alphawallet.app.entity.lifi.Chain; import com.alphawallet.app.entity.lifi.Connection; import com.alphawallet.app.entity.lifi.Quote; -import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.entity.lifi.Token; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; +import com.alphawallet.app.ui.widget.entity.ProgressInfo; import com.alphawallet.app.util.BalanceUtils; import com.alphawallet.app.util.SwapUtils; import com.alphawallet.app.viewmodel.SwapViewModel; @@ -35,6 +37,7 @@ import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.ActionSheetDialog; import com.alphawallet.app.widget.SelectTokenDialog; +import com.alphawallet.app.widget.StandardHeader; import com.alphawallet.app.widget.SwapSettingsDialog; import com.alphawallet.app.widget.TokenInfoView; import com.alphawallet.app.widget.TokenSelector; @@ -51,6 +54,7 @@ public class SwapActivity extends BaseActivity implements StandardFunctionInterface, ActionSheetCallback { private static final long GET_QUOTE_INTERVAL_MS = 30000; + private static final long COUNTDOWN_INTERVAL_MS = 1000; private SwapViewModel viewModel; private TokenSelector sourceSelector; private TokenSelector destSelector; @@ -62,39 +66,26 @@ public class SwapActivity extends BaseActivity implements StandardFunctionInterf private AWalletAlertDialog errorDialog; private RelativeLayout tokenLayout; private LinearLayout infoLayout; + private StandardHeader quoteHeader; private TokenInfoView provider; - private TokenInfoView fees; + private TokenInfoView providerWebsite; + private TokenInfoView gasFees; + private TokenInfoView otherFees; private TokenInfoView currentPrice; private TokenInfoView minReceived; private LinearLayout noConnectionsLayout; private MaterialButton continueBtn; private MaterialButton openSettingsBtn; private TextView chainName; - private Token token; + private com.alphawallet.app.entity.tokens.Token token; private Wallet wallet; - private Connection.LToken sourceToken; + private Token sourceToken; private List chains; - private final Handler getQuoteHandler = new Handler(); - private final Runnable getQuoteRunnable = new Runnable() - { - @Override - public void run() - { - if (confirmationDialog == null || !confirmationDialog.isShowing()) - { - viewModel.getQuote( - sourceSelector.getToken(), - destSelector.getToken(), - wallet.address, - sourceSelector.getAmount(), - settingsDialog.getSlippage()); - } - else - { - startQuoteTask(GET_QUOTE_INTERVAL_MS); - } - } - }; + private String selectedRouteProvider; + private CountDownTimer getQuoteTimer; + private ActivityResultLauncher selectSwapProviderLauncher; + private ActivityResultLauncher gasSettingsLauncher; + private ActivityResultLauncher getRoutesLauncher; @Override protected void onCreate(@Nullable Bundle savedInstanceState) @@ -113,7 +104,42 @@ protected void onCreate(@Nullable Bundle savedInstanceState) initViews(); - viewModel.getChains(); + initTimer(); + + registerActivityResultLaunchers(); + + viewModel.prepare(this, selectSwapProviderLauncher); + } + + private void registerActivityResultLaunchers() + { + selectSwapProviderLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) + { + viewModel.getChains(); + } + }); + + gasSettingsLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> confirmationDialog.setCurrentGasIndex(result)); + + getRoutesLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) + { + Intent data = result.getData(); + if (data != null) + { + selectedRouteProvider = data.getStringExtra("provider"); + getQuote(); + } + } + else if (result.getResultCode() == RESULT_CANCELED) + { + continueBtn.setEnabled(!TextUtils.isEmpty(selectedRouteProvider)); + } + }); } private void initViewModel() @@ -131,6 +157,24 @@ private void initViewModel() viewModel.transactionError().observe(this, this::txError); } + private void initTimer() + { + getQuoteTimer = new CountDownTimer(GET_QUOTE_INTERVAL_MS, COUNTDOWN_INTERVAL_MS) + { + @Override + public void onTick(long millisUntilFinished) + { + // TODO: Display countdown timer? + } + + @Override + public void onFinish() + { + getQuote(); + } + }; + } + private void getIntentData() { long chainId = getIntent().getLongExtra(C.EXTRA_CHAIN_ID, EthereumNetworkBase.MAINNET_ID); @@ -145,14 +189,21 @@ private void initViews() destSelector = findViewById(R.id.to_input); tokenLayout = findViewById(R.id.layout_tokens); infoLayout = findViewById(R.id.layout_info); + quoteHeader = findViewById(R.id.header_quote); provider = findViewById(R.id.tiv_provider); - fees = findViewById(R.id.tiv_fees); + providerWebsite = findViewById(R.id.tiv_provider_website); + gasFees = findViewById(R.id.tiv_gas_fees); + otherFees = findViewById(R.id.tiv_other_fees); currentPrice = findViewById(R.id.tiv_current_price); minReceived = findViewById(R.id.tiv_min_received); noConnectionsLayout = findViewById(R.id.layout_no_connections); continueBtn = findViewById(R.id.btn_continue); openSettingsBtn = findViewById(R.id.btn_open_settings); + quoteHeader.getImageControl().setOnClickListener(v -> { + getAvailableRoutes(); + }); + progressDialog = new AWalletAlertDialog(this); progressDialog.setCancelable(false); progressDialog.setProgressMode(); @@ -186,11 +237,11 @@ public void onSelectorClicked() @Override public void onAmountChanged(String amount) { - startQuoteTask(0); + getAvailableRoutes(); } @Override - public void onSelectionChanged(Connection.LToken token) + public void onSelectionChanged(Token token) { sourceTokenChanged(token); } @@ -221,7 +272,7 @@ public void onAmountChanged(String amount) } @Override - public void onSelectionChanged(Connection.LToken token) + public void onSelectionChanged(Token token) { destTokenChanged(token); } @@ -248,11 +299,11 @@ private ActionSheetDialog createConfirmationAction(Quote quote) ActionSheetDialog confDialog = null; try { - Token activeToken = viewModel.getTokensService().getTokenOrBase(sourceToken.chainId, sourceToken.address); + com.alphawallet.app.entity.tokens.Token activeToken = viewModel.getTokensService().getTokenOrBase(sourceToken.chainId, sourceToken.address); Web3Transaction w3Tx = viewModel.buildWeb3Transaction(quote); confDialog = new ActionSheetDialog(this, w3Tx, activeToken, "", w3Tx.recipient.toString(), viewModel.getTokensService(), this); - confDialog.setURL(quote.toolDetails.name); + confDialog.setURL(quote.swapProvider.name); confDialog.setCanceledOnTouchOutside(false); confDialog.setGasEstimate(Numeric.toBigInt(quote.transactionRequest.gasLimit)); } @@ -264,7 +315,7 @@ private ActionSheetDialog createConfirmationAction(Quote quote) return confDialog; } - private void destTokenChanged(Connection.LToken token) + private void destTokenChanged(Token token) { destSelector.setBalance(viewModel.getBalance(token)); @@ -272,10 +323,10 @@ private void destTokenChanged(Connection.LToken token) destTokenDialog.setSelectedToken(token.address); - startQuoteTask(0); + getAvailableRoutes(); } - private void sourceTokenChanged(Connection.LToken token) + private void sourceTokenChanged(Token token) { if (destSelector.getToken() == null) { @@ -294,17 +345,31 @@ private void sourceTokenChanged(Connection.LToken token) sourceToken = token; - startQuoteTask(0); + getAvailableRoutes(); } @Override protected void onResume() { super.onResume(); + if (settingsDialog != null) + { + settingsDialog.setSwapProviders(viewModel.getPreferredSwapProviders()); + } + } + + @Override + protected void onPause() + { + if (getQuoteTimer != null) + { + getQuoteTimer.cancel(); + } + super.onPause(); } // The source token should default to the token selected in the main wallet dialog (ie the token from the intent). - private void initSourceToken(Connection.LToken selectedToken) + private void initSourceToken(Token selectedToken) { if (selectedToken != null) { @@ -318,7 +383,7 @@ private void initSourceToken(Connection.LToken selectedToken) } } - private void initFromDialog(List fromTokens) + private void initFromDialog(List fromTokens) { Tokens.sortValue(fromTokens); sourceTokenDialog = new SelectTokenDialog(fromTokens, this, tokenItem -> { @@ -327,7 +392,7 @@ private void initFromDialog(List fromTokens) }); } - private void initToDialog(List toTokens) + private void initToDialog(List toTokens) { Tokens.sortName(toTokens); Tokens.sortValue(toTokens); @@ -337,30 +402,39 @@ private void initToDialog(List toTokens) }); } - private void startQuoteTask(long delay) + private void getAvailableRoutes() { - stopQuoteTask(); - - continueBtn.setEnabled(false); + if (getQuoteTimer != null) + { + getQuoteTimer.cancel(); + } if (sourceSelector.getToken() != null && destSelector.getToken() != null + && !sourceSelector.getToken().equals(destSelector.getToken()) && !TextUtils.isEmpty(sourceSelector.getAmount())) { - getQuoteHandler.postDelayed(getQuoteRunnable, delay); + viewModel.getRoutes( + this, + getRoutesLauncher, + sourceSelector.getToken(), + destSelector.getToken(), + wallet.address, + sourceSelector.getAmount(), + settingsDialog.getSlippage() + ); } } - private void stopQuoteTask() - { - getQuoteHandler.removeCallbacks(getQuoteRunnable); - } - private void onChains(List chains) { this.chains = chains; - settingsDialog = new SwapSettingsDialog(this, chains, + settingsDialog = new SwapSettingsDialog( + this, + chains, + viewModel.getSwapProviders(), + viewModel.getPreferredSwapProviders(), chain -> { chainName.setText(chain.name); viewModel.setChain(chain); @@ -400,13 +474,13 @@ private void onConnections(List connections) { if (!connections.isEmpty()) { - List fromTokens = new ArrayList<>(); - List toTokens = new ArrayList<>(); - Connection.LToken selectedToken = null; + List fromTokens = new ArrayList<>(); + List toTokens = new ArrayList<>(); + Token selectedToken = null; for (Connection c : connections) { - for (Connection.LToken t : c.fromTokens) + for (Token t : c.fromTokens) { if (!fromTokens.contains(t)) { @@ -417,7 +491,7 @@ private void onConnections(List connections) { fromTokens.add(t); - if (t.chainId == token.tokenInfo.chainId && t.address.equalsIgnoreCase(token.getAddress())) + if (t.isSimilarTo(token, wallet.address)) { selectedToken = t; } @@ -425,7 +499,7 @@ private void onConnections(List connections) } } - for (Connection.LToken t : c.toTokens) + for (Token t : c.toTokens) { if (!toTokens.contains(t)) { @@ -451,7 +525,21 @@ private void onConnections(List connections) infoLayout.setVisibility(View.GONE); noConnectionsLayout.setVisibility(View.VISIBLE); } + } + private void getQuote() + { + if (!TextUtils.isEmpty(selectedRouteProvider)) + { + viewModel.getQuote( + sourceSelector.getToken(), + destSelector.getToken(), + wallet.address, + sourceSelector.getAmount(), + settingsDialog.getSlippage(), + selectedRouteProvider + ); + } } private void onQuote(Quote quote) @@ -467,7 +555,7 @@ private void onQuote(Quote quote) continueBtn.setEnabled(true); - getQuoteHandler.postDelayed(getQuoteRunnable, GET_QUOTE_INTERVAL_MS); + getQuoteTimer.start(); } private void updateDestAmount(Quote quote) @@ -484,32 +572,31 @@ private void updateDestAmount(Quote quote) private void updateInfoSummary(Quote quote) { - provider.setValue(quote.toolDetails.name); - fees.setValue(SwapUtils.getTotalGasFees(quote.estimate.gasCosts)); - currentPrice.setValue(SwapUtils.getFormattedCurrentPrice(quote).trim()); - minReceived.setValue(SwapUtils.getMinimumAmountReceived(quote)); + provider.setValue(quote.swapProvider.name); + String url = viewModel.getSwapProviderUrl(quote.swapProvider.key); + if (!TextUtils.isEmpty(url)) + { + providerWebsite.setValue(url); + providerWebsite.setLink(); + } + gasFees.setValue(SwapUtils.getTotalGasFees(quote.estimate.gasCosts)); + otherFees.setValue(SwapUtils.getOtherFees(quote.estimate.feeCosts)); + currentPrice.setValue(SwapUtils.getFormattedCurrentPrice(quote.action).trim()); + minReceived.setValue(SwapUtils.getFormattedMinAmount(quote.estimate, quote.action)); infoLayout.setVisibility(View.VISIBLE); } - private void onProgressInfo(int code) + private void onProgressInfo(ProgressInfo progressInfo) { - String message; - switch (code) + if (progressInfo.shouldShow()) { - case C.ProgressInfo.FETCHING_CHAINS: - message = getString(R.string.message_fetching_chains); - break; - case C.ProgressInfo.FETCHING_CONNECTIONS: - message = getString(R.string.message_fetching_connections); - break; - case C.ProgressInfo.FETCHING_QUOTE: - message = getString(R.string.message_fetching_quote); - break; - default: - message = getString(R.string.title_dialog_handling); - break; + progressDialog.setTitle(progressInfo.getMessage()); + progressDialog.show(); + } + else + { + progressDialog.dismiss(); } - progressDialog.setTitle(message); } private void onProgress(Boolean shouldShowProgress) @@ -548,7 +635,7 @@ private void onError(ErrorEnvelope errorEnvelope) sourceSelector.setError(getString(R.string.error_insufficient_balance, sourceSelector.getToken().symbol)); break; case C.ErrorCode.SWAP_TIMEOUT_ERROR: - startQuoteTask(0); + getAvailableRoutes(); break; case C.ErrorCode.SWAP_CONNECTIONS_ERROR: case C.ErrorCode.SWAP_CHAIN_ERROR: @@ -567,7 +654,7 @@ private void onError(ErrorEnvelope errorEnvelope) errorDialog.setTitle(R.string.title_dialog_error); errorDialog.setMessage(errorEnvelope.message); errorDialog.setButton(R.string.try_again, v -> { - startQuoteTask(0); + getAvailableRoutes(); errorDialog.dismiss(); }); errorDialog.setSecondaryButton(R.string.action_cancel, v -> errorDialog.dismiss()); @@ -630,6 +717,6 @@ public void notifyConfirm(String mode) @Override public ActivityResultLauncher gasSelectLauncher() { - return null; + return gasSettingsLauncher; } } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/RouteAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/RouteAdapter.java new file mode 100644 index 0000000000..0dd563796b --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/RouteAdapter.java @@ -0,0 +1,105 @@ +package com.alphawallet.app.ui.widget.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.lifi.Route; +import com.alphawallet.app.ui.widget.entity.OnRouteSelectedListener; +import com.alphawallet.app.util.SwapUtils; +import com.alphawallet.app.widget.AddressIcon; +import com.google.android.material.card.MaterialCardView; + +import java.util.List; + +public class RouteAdapter extends RecyclerView.Adapter +{ + private final Context context; + private final List data; + private final OnRouteSelectedListener listener; + + public RouteAdapter(Context context, List data, OnRouteSelectedListener listener) + { + this.context = context; + this.data = data; + this.listener = listener; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) + { + int buttonTypeId = R.layout.item_route; + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(buttonTypeId, parent, false); + return new ViewHolder(itemView); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) + { + Route item = data.get(position); + if (item != null) + { + Route.Step step = item.steps.get(0); + + holder.provider.setText(context.getString(R.string.label_swap_via, step.swapProvider.name)); + + for (String tag : item.tags) + { + if (tag.equalsIgnoreCase("RECOMMENDED")) + { + holder.tag.setVisibility(View.VISIBLE); + holder.tag.setText(tag); + } + } + + holder.value.setText(SwapUtils.getFormattedMinAmount(step.estimate, step.action)); + holder.icon.bindData(step.action.toToken.logoURI, step.action.toToken.chainId, step.action.toToken.address, step.action.toToken.symbol); +// holder.symbol.setText(step.action.toToken.symbol); + holder.gas.setText(context.getString(R.string.info_gas_fee, SwapUtils.getTotalGasFees(step.estimate.gasCosts))); + holder.fees.setVisibility(step.estimate.feeCosts.isEmpty() ? View.GONE : View.VISIBLE); + holder.fees.setText(SwapUtils.getOtherFees(step.estimate.feeCosts)); + holder.layout.setOnClickListener(v -> listener.onRouteSelected(step.swapProvider.key)); + } + } + + @Override + public int getItemCount() + { + return data.size(); + } + + static class ViewHolder extends RecyclerView.ViewHolder + { + MaterialCardView layout; + TextView tag; + TextView provider; + TextView value; + TextView symbol; + TextView gas; + TextView fees; + TextView price; + AddressIcon icon; + + ViewHolder(View view) + { + super(view); + layout = view.findViewById(R.id.layout); + tag = view.findViewById(R.id.tag); + provider = view.findViewById(R.id.provider); + value = view.findViewById(R.id.value); + symbol = view.findViewById(R.id.symbol); + gas = view.findViewById(R.id.gas); + fees = view.findViewById(R.id.fees); + price = view.findViewById(R.id.price); + icon = view.findViewById(R.id.token_icon); + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectChainAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectChainAdapter.java index b7e210f0fa..3f8f502b74 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectChainAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectChainAdapter.java @@ -1,11 +1,9 @@ package com.alphawallet.app.ui.widget.adapter; - import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; @@ -14,7 +12,7 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.lifi.Chain; import com.alphawallet.app.widget.SwapSettingsDialog; -import com.bumptech.glide.Glide; +import com.alphawallet.app.widget.TokenIcon; import com.google.android.material.radiobutton.MaterialRadioButton; import java.util.List; @@ -51,11 +49,7 @@ public void onBindViewHolder(ViewHolder holder, int position) { holder.name.setText(item.metamask.chainName); holder.chainId.setText(context.getString(R.string.chain_id, item.id)); - - Glide.with(context) - .load(item.logoURI) - .circleCrop() - .into(holder.chainIcon); + holder.chainIcon.bindData(item.id); if (item.id == selectedChainId) { @@ -75,18 +69,18 @@ public int getItemCount() public void setChains(List chains) { this.chains = chains; - notifyDataSetChanged(); + notifyItemRangeChanged(0, getItemCount()); } - public void setSelectedChain(long selectedChainId) + public long getSelectedChain() { - this.selectedChainId = selectedChainId; - notifyDataSetChanged(); + return this.selectedChainId; } - public long getSelectedChain() + public void setSelectedChain(long selectedChainId) { - return this.selectedChainId; + this.selectedChainId = selectedChainId; + notifyItemRangeChanged(0, getItemCount()); } static class ViewHolder extends RecyclerView.ViewHolder @@ -95,7 +89,7 @@ static class ViewHolder extends RecyclerView.ViewHolder TextView name; TextView chainId; View itemLayout; - ImageView chainIcon; + TokenIcon chainIcon; ViewHolder(View view) { diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java index 0118a9bc30..c5f32d6305 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SelectTokenAdapter.java @@ -1,6 +1,5 @@ package com.alphawallet.app.ui.widget.adapter; - import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -11,7 +10,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.alphawallet.app.R; -import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Token; import com.alphawallet.app.widget.AddressIcon; import com.alphawallet.app.widget.SelectTokenDialog; import com.google.android.material.radiobutton.MaterialRadioButton; @@ -21,12 +20,12 @@ public class SelectTokenAdapter extends RecyclerView.Adapter { - private final List displayData; + private final List displayData; private final SelectTokenDialog.SelectTokenDialogEventListener callback; - private String selectedTokenAddress; private final TokenFilter tokenFilter; + private String selectedTokenAddress; - public SelectTokenAdapter(List tokens, SelectTokenDialog.SelectTokenDialogEventListener callback) + public SelectTokenAdapter(List tokens, SelectTokenDialog.SelectTokenDialogEventListener callback) { tokenFilter = new TokenFilter(tokens); this.callback = callback; @@ -47,7 +46,7 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { - Connection.LToken item = displayData.get(position); + Token item = displayData.get(position); if (item != null) { holder.name.setText(item.name); @@ -56,7 +55,7 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) holder.name.append(")"); holder.tokenIcon.bindData(item.logoURI, item.chainId, selectedTokenAddress, item.symbol); - + String balance = item.balance; if (!TextUtils.isEmpty(balance)) { @@ -80,7 +79,7 @@ public void filter(String keyword) updateList(tokenFilter.filterBy(keyword)); } - public void updateList(List filteredList) + public void updateList(List filteredList) { displayData.clear(); displayData.addAll(filteredList); diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SwapProviderAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SwapProviderAdapter.java new file mode 100644 index 0000000000..724af0fdca --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SwapProviderAdapter.java @@ -0,0 +1,87 @@ +package com.alphawallet.app.ui.widget.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.lifi.SwapProvider; +import com.alphawallet.app.widget.AddressIcon; +import com.google.android.material.checkbox.MaterialCheckBox; + +import java.util.List; + +public class SwapProviderAdapter extends RecyclerView.Adapter +{ + private final List data; + + public SwapProviderAdapter(List data) + { + this.data = data; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) + { + int buttonTypeId = R.layout.item_exchange; + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(buttonTypeId, parent, false); + return new ViewHolder(itemView); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) + { + SwapProvider item = data.get(position); + if (item != null) + { + holder.title.setText(item.name); + + holder.subtitle.setText(item.url); + + holder.icon.bindData(item.logoURI, -1, "", ""); + + holder.layout.setOnClickListener(v -> holder.checkBox.setChecked(!item.isChecked)); + + holder.checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> item.isChecked = isChecked); + + holder.checkBox.setChecked(item.isChecked); + } + } + + public List getExchanges() + { + return data; + } + + @Override + public int getItemCount() + { + return data.size(); + } + + static class ViewHolder extends RecyclerView.ViewHolder + { + RelativeLayout layout; + AddressIcon icon; + TextView title; + TextView subtitle; + MaterialCheckBox checkBox; + + ViewHolder(View view) + { + super(view); + layout = view.findViewById(R.id.layout_list_item); + icon = view.findViewById(R.id.token_icon); + title = view.findViewById(R.id.provider); + subtitle = view.findViewById(R.id.subtitle); + checkBox = view.findViewById(R.id.checkbox); + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java index dd57ff6a6d..1e9fb39653 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokenFilter.java @@ -1,29 +1,46 @@ package com.alphawallet.app.ui.widget.adapter; +import android.text.TextUtils; + import androidx.annotation.NonNull; -import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Token; import java.util.ArrayList; import java.util.List; +import java.util.ListIterator; import java.util.Locale; public class TokenFilter { - private final List tokens; + private final List tokens; - public TokenFilter(List tokens) + public TokenFilter(List tokens) { this.tokens = tokens; + removeBadTokens(); + } + + private void removeBadTokens() + { + ListIterator iterator = this.tokens.listIterator(); + while (iterator.hasNext()) + { + Token t = iterator.next(); + if (TextUtils.isEmpty(t.name) || TextUtils.isEmpty(t.symbol)) + { + iterator.remove(); + } + } } - public List filterBy(String keyword) + public List filterBy(String keyword) { String lowerCaseKeyword = lowerCase(keyword); - List result = new ArrayList<>(); + List result = new ArrayList<>(); // First filter: Add all entries that start with the keyword on top of the list. - for (Connection.LToken lToken : this.tokens) + for (Token lToken : this.tokens) { String name = lowerCase(lToken.name); String symbol = lowerCase(lToken.symbol); @@ -35,7 +52,7 @@ public List filterBy(String keyword) } // Second filter: Add the rest of the entries that contain the keyword on top of the list. - for (Connection.LToken lToken : this.tokens) + for (Token lToken : this.tokens) { String name = lowerCase(lToken.name); String symbol = lowerCase(lToken.symbol); diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/OnRouteSelectedListener.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/OnRouteSelectedListener.java new file mode 100644 index 0000000000..2592a3bb57 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/OnRouteSelectedListener.java @@ -0,0 +1,6 @@ +package com.alphawallet.app.ui.widget.entity; + +public interface OnRouteSelectedListener +{ + void onRouteSelected(String provider); +} diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ProgressInfo.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ProgressInfo.java new file mode 100644 index 0000000000..e5523168e5 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ProgressInfo.java @@ -0,0 +1,28 @@ +package com.alphawallet.app.ui.widget.entity; + +public class ProgressInfo +{ + private boolean shouldShow; + private int messageRes; + + public ProgressInfo(boolean shouldShow, int messageRes) + { + this.shouldShow = shouldShow; + this.messageRes = messageRes; + } + + public ProgressInfo(boolean shouldShow) + { + this.shouldShow = shouldShow; + } + + public boolean shouldShow() + { + return shouldShow; + } + + public int getMessage() + { + return messageRes; + } +} diff --git a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java index baee0d76b4..b69f0f4a64 100644 --- a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java +++ b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java @@ -1,5 +1,9 @@ package com.alphawallet.app.util; +import com.alphawallet.app.entity.lifi.Action; +import com.alphawallet.app.entity.lifi.Estimate; +import com.alphawallet.app.entity.lifi.FeeCost; +import com.alphawallet.app.entity.lifi.GasCost; import com.alphawallet.app.entity.lifi.Quote; import java.math.BigDecimal; @@ -7,39 +11,59 @@ public class SwapUtils { + private static final String CURRENT_PRICE_FORMAT = "1 %s ≈ %s %s"; private static final String GAS_PRICE_FORMAT = "%s %s"; + private static final String FEE_FORMAT = "%s %s"; private static final String MINIMUM_RECEIVED_FORMAT = "%s %s"; - private static final String CURRENT_PRICE_FORMAT = "1 %s ≈ %s %s"; - public static String getTotalGasFees(ArrayList gasCosts) + public static String getTotalGasFees(ArrayList gasCosts) { StringBuilder gas = new StringBuilder(); - for (Quote.Estimate.GasCost gc : gasCosts) + for (GasCost gc : gasCosts) { gas.append(SwapUtils.getGasFee(gc)).append(System.lineSeparator()); } return gas.toString().trim(); } - public static String getGasFee(Quote.Estimate.GasCost gasCost) + public static String getGasFee(GasCost gasCost) { return String.format(GAS_PRICE_FORMAT, BalanceUtils.getScaledValueFixed(new BigDecimal(gasCost.amount), gasCost.token.decimals, 4), gasCost.token.symbol); } - public static String getFormattedCurrentPrice(Quote quote) + public static String getOtherFees(ArrayList feeCosts) + { + StringBuilder fees = new StringBuilder(); + for (FeeCost fc : feeCosts) + { + fees.append(fc.name); + fees.append(": "); + fees.append(SwapUtils.getFee(fc)).append(System.lineSeparator()); + } + return fees.toString().trim(); + } + + public static String getFee(FeeCost feeCost) + { + return String.format(FEE_FORMAT, + BalanceUtils.getScaledValueFixed(new BigDecimal(feeCost.amount), feeCost.token.decimals, 4), + feeCost.token.symbol); + } + + public static String getFormattedCurrentPrice(Action action) { return String.format(CURRENT_PRICE_FORMAT, - quote.action.fromToken.symbol, - quote.getCurrentPrice(), - quote.action.toToken.symbol); + action.fromToken.symbol, + action.getCurrentPrice(), + action.toToken.symbol); } - public static String getMinimumAmountReceived(Quote quote) + public static String getFormattedMinAmount(Estimate estimate, Action action) { return String.format(MINIMUM_RECEIVED_FORMAT, - BalanceUtils.getShortFormat(quote.estimate.toAmountMin, quote.action.toToken.decimals), - quote.action.toToken.symbol); + BalanceUtils.getScaledValue(estimate.toAmountMin, action.toToken.decimals, 4), + action.toToken.symbol); } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SelectRouteViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SelectRouteViewModel.java new file mode 100644 index 0000000000..4e2a7c5de5 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SelectRouteViewModel.java @@ -0,0 +1,119 @@ +package com.alphawallet.app.viewmodel; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.lifi.Route; +import com.alphawallet.app.repository.PreferenceRepositoryType; +import com.alphawallet.app.service.SwapService; +import com.alphawallet.app.ui.widget.entity.ProgressInfo; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.List; +import java.util.Set; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +@HiltViewModel +public class SelectRouteViewModel extends BaseViewModel +{ + private final PreferenceRepositoryType preferenceRepository; + private final SwapService swapService; + private final MutableLiveData> routes = new MutableLiveData<>(); + private final MutableLiveData progressInfo = new MutableLiveData<>(); + private Disposable routeDisposable; + + @Inject + public SelectRouteViewModel( + PreferenceRepositoryType preferenceRepository, + SwapService swapService) + { + this.preferenceRepository = preferenceRepository; + this.swapService = swapService; + } + + public LiveData> routes() + { + return routes; + } + + public LiveData progressInfo() + { + return progressInfo; + } + + public void getRoutes(String fromChainId, + String toChainId, + String fromTokenAddress, + String toTokenAddress, + String fromAddress, + String fromAmount, + String slippage, + Set exchanges) + { + progressInfo.postValue(new ProgressInfo(true, R.string.message_fetching_routes)); + + routeDisposable = swapService + .getRoutes(fromChainId, toChainId, fromTokenAddress, toTokenAddress, fromAddress, fromAmount, slippage, exchanges) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::onRoutes, this::onRoutesError); + } + + private void onRoutes(String result) + { + progressInfo.postValue(new ProgressInfo(false)); + + try + { + JSONObject obj = new JSONObject(result); + if (obj.has("routes")) + { + JSONArray json = obj.getJSONArray("routes"); + List routeList = new Gson().fromJson(json.toString(), new TypeToken>() + { + }.getType()); + routes.postValue(routeList); + } + else + { +// postError(C.ErrorCode.SWAP_CONNECTIONS_ERROR, result); + } + } + catch (JSONException e) + { +// postError(C.ErrorCode.SWAP_CONNECTIONS_ERROR, Objects.requireNonNull(e.getMessage())); + } + } + + private void onRoutesError(Throwable throwable) + { + // TODO: + } + + public Set getPreferredExchanges() + { + return preferenceRepository.getSelectedSwapProviders(); + } + + @Override + protected void onCleared() + { + if (routeDisposable != null && !routeDisposable.isDisposed()) + { + routeDisposable.dispose(); + } + super.onCleared(); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java new file mode 100644 index 0000000000..e162683958 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java @@ -0,0 +1,85 @@ +package com.alphawallet.app.viewmodel; + +import android.content.Context; + +import com.alphawallet.app.entity.lifi.SwapProvider; +import com.alphawallet.app.repository.PreferenceRepositoryType; +import com.alphawallet.app.repository.SwapRepositoryType; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; + +@HiltViewModel +public class SelectSwapProvidersViewModel extends BaseViewModel +{ + private final PreferenceRepositoryType preferenceRepository; + private final SwapRepositoryType swapRepository; + + @Inject + public SelectSwapProvidersViewModel( + PreferenceRepositoryType preferenceRepository, + SwapRepositoryType swapRepository) + { + this.preferenceRepository = preferenceRepository; + this.swapRepository = swapRepository; + } + + public Set getPreferredExchanges(Context context) + { + Set exchanges = preferenceRepository.getSelectedSwapProviders(); + if (exchanges.isEmpty()) + { + List swapProviders = getSwapProviders(); + if (swapProviders != null) + { + for (SwapProvider provider : swapProviders) + { + exchanges.add(provider.key); + } + preferenceRepository.setSelectedSwapProviders(exchanges); + } + } + return exchanges; + } + + public List getSwapProviders() + { + List swapProviders = swapRepository.getProviders(); + + if (swapProviders != null) + { + Set preferredProviders = preferenceRepository.getSelectedSwapProviders(); + for (SwapProvider provider : swapProviders) + { + if (preferredProviders.contains(provider.key)) + { + provider.isChecked = true; + } + } + } + + return swapProviders; + } + + public boolean savePreferences(List swapProviders) + { + Set stringSet = new HashSet<>(); + for (SwapProvider providerool : swapProviders) + { + if (providerool.isChecked) + { + stringSet.add(providerool.key); + } + } + if (!stringSet.isEmpty()) + { + preferenceRepository.setSelectedSwapProviders(stringSet); + } + return !stringSet.isEmpty(); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java index 2bcfcd2812..d3c2a55b4e 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java @@ -1,11 +1,14 @@ package com.alphawallet.app.viewmodel; import android.app.Activity; +import android.content.Intent; +import androidx.activity.result.ActivityResultLauncher; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import com.alphawallet.app.C; +import com.alphawallet.app.R; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.TransactionData; @@ -13,12 +16,18 @@ import com.alphawallet.app.entity.lifi.Chain; import com.alphawallet.app.entity.lifi.Connection; import com.alphawallet.app.entity.lifi.Quote; -import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.entity.lifi.SwapProvider; +import com.alphawallet.app.entity.lifi.Token; import com.alphawallet.app.interact.CreateTransactionInteract; +import com.alphawallet.app.repository.PreferenceRepositoryType; +import com.alphawallet.app.repository.SwapRepositoryType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.KeyService; import com.alphawallet.app.service.SwapService; import com.alphawallet.app.service.TokensService; +import com.alphawallet.app.ui.SelectRouteActivity; +import com.alphawallet.app.ui.SelectSwapProvidersActivity; +import com.alphawallet.app.ui.widget.entity.ProgressInfo; import com.alphawallet.app.util.BalanceUtils; import com.alphawallet.app.util.Hex; import com.alphawallet.app.web3.entity.Address; @@ -35,6 +44,7 @@ import java.util.List; import java.util.Locale; import java.util.Objects; +import java.util.Set; import javax.inject.Inject; @@ -48,6 +58,8 @@ public class SwapViewModel extends BaseViewModel { private final AssetDefinitionService assetDefinitionService; + private final PreferenceRepositoryType preferenceRepository; + private final SwapRepositoryType swapRepository; private final TokensService tokensService; private final SwapService swapService; private final CreateTransactionInteract createTransactionInteract; @@ -58,7 +70,7 @@ public class SwapViewModel extends BaseViewModel private final MutableLiveData> connections = new MutableLiveData<>(); private final MutableLiveData quote = new MutableLiveData<>(); private final MutableLiveData network = new MutableLiveData<>(); - private final MutableLiveData progressInfo = new MutableLiveData<>(); + private final MutableLiveData progressInfo = new MutableLiveData<>(); private final MutableLiveData transactionFinalised = new MutableLiveData<>(); private final MutableLiveData transactionError = new MutableLiveData<>(); @@ -70,12 +82,16 @@ public class SwapViewModel extends BaseViewModel @Inject public SwapViewModel( AssetDefinitionService assetDefinitionService, + PreferenceRepositoryType preferenceRepository, + SwapRepositoryType swapRepository, TokensService tokensService, SwapService swapService, CreateTransactionInteract createTransactionInteract, KeyService keyService) { this.assetDefinitionService = assetDefinitionService; + this.preferenceRepository = preferenceRepository; + this.swapRepository = swapRepository; this.tokensService = tokensService; this.swapService = swapService; this.createTransactionInteract = createTransactionInteract; @@ -117,7 +133,7 @@ public LiveData network() return network; } - public LiveData progressInfo() + public LiveData progressInfo() { return progressInfo; } @@ -144,8 +160,7 @@ public void setChain(Chain c) public void getChains() { - progressInfo.postValue(C.ProgressInfo.FETCHING_CHAINS); - progress.postValue(true); + progressInfo.postValue(new ProgressInfo(true, R.string.message_fetching_chains)); chainsDisposable = swapService.getChains() .subscribeOn(Schedulers.io()) @@ -153,10 +168,23 @@ public void getChains() .subscribe(this::onChains, this::onChainsError); } + public String getSwapProviderUrl(String key) + { + List tools = getSwapProviders(); + for (SwapProvider td : tools) + { + if (key.startsWith(td.key)) + { + return td.url; + } + } + + return ""; + } + public void getConnections(long from, long to) { - progressInfo.postValue(C.ProgressInfo.FETCHING_CONNECTIONS); - progress.postValue(true); + progressInfo.postValue(new ProgressInfo(true, R.string.message_fetching_connections)); connectionsDisposable = swapService.getConnections(from, to) .subscribeOn(Schedulers.io()) @@ -164,14 +192,14 @@ public void getConnections(long from, long to) .subscribe(this::onConnections, this::onConnectionsError); } - public void getQuote(Connection.LToken source, Connection.LToken dest, String address, String amount, String slippage) + public void getQuote(Token source, Token dest, String address, String amount, String slippage, String allowExchanges) { + if (!isValidAmount(amount)) return; if (hasEnoughBalance(source, amount)) { - progressInfo.postValue(C.ProgressInfo.FETCHING_QUOTE); - progress.postValue(true); + progressInfo.postValue(new ProgressInfo(true, R.string.message_fetching_quote)); - quoteDisposable = swapService.getQuote(source, dest, address, amount, slippage) + quoteDisposable = swapService.getQuote(source, dest, address, amount, slippage, allowExchanges) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::onQuote, this::onQuoteError); @@ -182,6 +210,19 @@ public void getQuote(Connection.LToken source, Connection.LToken dest, String ad } } + private boolean isValidAmount(String amount) + { + try + { + BigDecimal d = new BigDecimal(amount); + } + catch (Exception e) + { + return false; + } + return true; + } + private void onChainsError(Throwable t) { postError(C.ErrorCode.SWAP_CHAIN_ERROR, Objects.requireNonNull(t.getMessage())); @@ -197,7 +238,7 @@ private void onQuoteError(Throwable t) postError(C.ErrorCode.SWAP_QUOTE_ERROR, Objects.requireNonNull(t.getMessage())); } - public boolean hasEnoughBalance(Connection.LToken source, String amount) + public boolean hasEnoughBalance(Token source, String amount) { BigDecimal bal = new BigDecimal(getBalance(source)); BigDecimal reqAmount = new BigDecimal(amount); @@ -255,7 +296,7 @@ private void onConnections(String result) postError(C.ErrorCode.SWAP_CONNECTIONS_ERROR, Objects.requireNonNull(e.getMessage())); } - progress.postValue(false); + progressInfo.postValue(new ProgressInfo(false)); } private void onQuote(String result) @@ -270,7 +311,7 @@ private void onQuote(String result) quote.postValue(q); } - progress.postValue(false); + progressInfo.postValue(new ProgressInfo(false)); } private void postError(int errorCode, String errorStr) @@ -308,9 +349,9 @@ private boolean isValidQuote(String result) && result.contains("tool"); } - public String getBalance(Connection.LToken token) + public String getBalance(Token token) { - Token t; + com.alphawallet.app.entity.tokens.Token t; if (token.isNativeToken()) { t = tokensService.getServiceToken(token.chainId); @@ -360,6 +401,16 @@ public Web3Transaction buildWeb3Transaction(Quote quote) ); } + public List getSwapProviders() + { + return swapRepository.getProviders(); + } + + public Set getPreferredSwapProviders() + { + return preferenceRepository.getSelectedSwapProviders(); + } + @Override protected void onCleared() { @@ -381,4 +432,48 @@ protected void onCleared() } super.onCleared(); } + + public void getRoutes(Activity activity, + ActivityResultLauncher launcher, + Token source, + Token dest, + String address, + String amount, + String slippage) + { + if (!isValidAmount(amount)) return; + if (hasEnoughBalance(source, amount)) + { + Intent intent = new Intent(activity, SelectRouteActivity.class); + intent.putExtra("fromChainId", String.valueOf(source.chainId)); + intent.putExtra("toChainId", String.valueOf(dest.chainId)); + intent.putExtra("fromTokenAddress", String.valueOf(source.address)); + intent.putExtra("toTokenAddress", String.valueOf(dest.address)); + intent.putExtra("fromAddress", address); + intent.putExtra("fromAmount", BalanceUtils.getRawFormat(amount, source.decimals)); + intent.putExtra("fromTokenDecimals", source.decimals); + intent.putExtra("slippage", slippage); + intent.putExtra("fromTokenSymbol", source.symbol); + intent.putExtra("fromTokenIcon", source.symbol); + intent.putExtra("fromTokenLogoUri", source.logoURI); + launcher.launch(intent); + } + else + { + error.postValue(new ErrorEnvelope(C.ErrorCode.INSUFFICIENT_BALANCE, "")); + } + } + + public void prepare(Activity activity, ActivityResultLauncher launcher) + { + if (getPreferredSwapProviders().isEmpty()) + { + Intent intent = new Intent(activity, SelectSwapProvidersActivity.class); + launcher.launch(intent); + } + else + { + getChains(); + } + } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/Tokens.java b/app/src/main/java/com/alphawallet/app/viewmodel/Tokens.java index cd4367823d..07689b8646 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/Tokens.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/Tokens.java @@ -1,6 +1,6 @@ package com.alphawallet.app.viewmodel; -import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Token; import java.math.BigDecimal; import java.util.Collections; @@ -8,7 +8,7 @@ public class Tokens { - public static void sortValue(List tokenItems) + public static void sortValue(List tokenItems) { Collections.sort(tokenItems, (l, r) -> { if (l.isNativeToken()) @@ -28,7 +28,7 @@ else if (r.isNativeToken()) }); } - public static void sortName(List tokenItems) + public static void sortName(List tokenItems) { Collections.sort(tokenItems, (l, r) -> { if (l.isNativeToken()) @@ -41,7 +41,7 @@ else if (r.isNativeToken()) } else { - return l.name.compareToIgnoreCase(r.name); + return l.name.trim().compareToIgnoreCase(r.name.trim()); } }); } diff --git a/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java b/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java index c98fb66881..bc2ce27ba8 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/SelectTokenDialog.java @@ -19,7 +19,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.alphawallet.app.R; -import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Token; import com.alphawallet.app.ui.widget.adapter.SelectTokenAdapter; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetDialog; @@ -56,7 +56,7 @@ public SelectTokenDialog(@NonNull Activity activity) btnClose.setOnClickListener(v -> dismiss()); } - public SelectTokenDialog(List tokenItems, Activity activity, SelectTokenDialogEventListener callback) + public SelectTokenDialog(List tokenItems, Activity activity, SelectTokenDialogEventListener callback) { this(activity); @@ -102,6 +102,6 @@ public void setSelectedToken(String address) public interface SelectTokenDialogEventListener { - void onChainSelected(Connection.LToken tokenItem); + void onChainSelected(Token tokenItem); } } diff --git a/app/src/main/java/com/alphawallet/app/widget/StandardHeader.java b/app/src/main/java/com/alphawallet/app/widget/StandardHeader.java index 0eb01a7490..2cd0a27315 100644 --- a/app/src/main/java/com/alphawallet/app/widget/StandardHeader.java +++ b/app/src/main/java/com/alphawallet/app/widget/StandardHeader.java @@ -4,6 +4,7 @@ import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -16,6 +17,8 @@ public class StandardHeader extends LinearLayout { private TextView headerText; + private TextView textControl; + private ImageView imageControl; private ChainName chainName; private SwitchMaterial switchMaterial; private View separator; @@ -40,30 +43,41 @@ private void getAttrs(Context context, AttributeSet attrs) int headerId = a.getResourceId(R.styleable.StandardHeader_headerText, R.string.empty); boolean showSwitch = a.getBoolean(R.styleable.StandardHeader_showSwitch, false); boolean showChainName = a.getBoolean(R.styleable.StandardHeader_showChain, false); + boolean showTextControl = a.getBoolean(R.styleable.StandardHeader_showTextControl, false); + boolean showImageControl = a.getBoolean(R.styleable.StandardHeader_showImageControl, false); + int controlText = a.getResourceId(R.styleable.StandardHeader_controlText, -1); + int controlImageRes = a.getResourceId(R.styleable.StandardHeader_controlImageRes, -1); headerText = findViewById(R.id.text_header); chainName = findViewById(R.id.chain_name); switchMaterial = findViewById(R.id.switch_material); separator = findViewById(R.id.separator); + textControl = findViewById(R.id.text_control); + imageControl = findViewById(R.id.image_control); headerText.setText(headerId); - if (showSwitch) + switchMaterial.setVisibility(showSwitch ? View.VISIBLE : View.GONE); + chainName.setVisibility(showChainName ? View.VISIBLE : View.GONE); + + if (showTextControl) { - switchMaterial.setVisibility(View.VISIBLE); + textControl.setVisibility(View.VISIBLE); + textControl.setText(controlText); } else { - switchMaterial.setVisibility(View.GONE); + textControl.setVisibility(View.GONE); } - if (showChainName) + if (showImageControl) { - chainName.setVisibility(View.VISIBLE); + imageControl.setVisibility(View.VISIBLE); + imageControl.setImageResource(controlImageRes); } else { - chainName.setVisibility(View.GONE); + imageControl.setVisibility(View.GONE); } } finally @@ -92,6 +106,16 @@ public SwitchMaterial getSwitch() return switchMaterial; } + public TextView getTextControl() + { + return textControl; + } + + public ImageView getImageControl() + { + return imageControl; + } + public void hideSeparator() { separator.setVisibility(View.GONE); diff --git a/app/src/main/java/com/alphawallet/app/widget/SwapSettingsDialog.java b/app/src/main/java/com/alphawallet/app/widget/SwapSettingsDialog.java index 0f17a299f6..1ae6da13e5 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SwapSettingsDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/SwapSettingsDialog.java @@ -3,9 +3,11 @@ import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED; import android.app.Activity; +import android.content.Intent; import android.content.res.Resources; import android.view.View; import android.widget.ImageView; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; @@ -13,19 +15,25 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.lifi.Chain; +import com.alphawallet.app.entity.lifi.SwapProvider; +import com.alphawallet.app.ui.SelectSwapProvidersActivity; import com.alphawallet.app.ui.widget.adapter.ChainFilter; import com.alphawallet.app.ui.widget.adapter.SelectChainAdapter; +import com.google.android.flexbox.FlexboxLayout; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetDialog; import java.util.List; +import java.util.Set; public class SwapSettingsDialog extends BottomSheetDialog { private RecyclerView chainList; private SelectChainAdapter adapter; - private List chains; + private List swapProviders; private SlippageWidget slippageWidget; + private StandardHeader preferredExchangesHeader; + private FlexboxLayout preferredSwapProviders; public SwapSettingsDialog(@NonNull Activity activity) { @@ -35,7 +43,7 @@ public SwapSettingsDialog(@NonNull Activity activity) setOnShowListener(dialogInterface -> { view.setMinimumHeight(Resources.getSystem().getDisplayMetrics().heightPixels); - BottomSheetBehaviorbehavior = BottomSheetBehavior.from((View) view.getParent()); + BottomSheetBehavior behavior = BottomSheetBehavior.from((View) view.getParent()); behavior.setState(STATE_EXPANDED); behavior.setSkipCollapsed(true); }); @@ -45,15 +53,55 @@ public SwapSettingsDialog(@NonNull Activity activity) ImageView closeBtn = findViewById(R.id.image_close); closeBtn.setOnClickListener(v -> dismiss()); + + preferredExchangesHeader = findViewById(R.id.header_exchanges); + preferredExchangesHeader.getTextControl().setOnClickListener(v -> { + Intent intent = new Intent(activity, SelectSwapProvidersActivity.class); + activity.startActivity(intent); + }); + + preferredSwapProviders = findViewById(R.id.layout_exchanges); } - public SwapSettingsDialog(Activity activity, List chains, SwapSettingsInterface swapSettingsInterface) + public SwapSettingsDialog(Activity activity, + List chains, + List swapProviders, + Set preferredSwapProviders, + SwapSettingsInterface swapSettingsInterface) { this(activity); ChainFilter filter = new ChainFilter(chains); adapter = new SelectChainAdapter(activity, filter.getSupportedChains(), swapSettingsInterface); chainList.setLayoutManager(new LinearLayoutManager(getContext())); chainList.setAdapter(adapter); + this.swapProviders = swapProviders; + setSwapProviders(preferredSwapProviders); + } + + private TextView createTextView(String name) + { + int margin = (int) getContext().getResources().getDimension(R.dimen.tiny_8); + FlexboxLayout.LayoutParams params = + new FlexboxLayout.LayoutParams(FlexboxLayout.LayoutParams.WRAP_CONTENT, FlexboxLayout.LayoutParams.WRAP_CONTENT); + params.setMargins(margin, margin, margin, margin); + + TextView exchange = new TextView(getContext(), null); + exchange.setText(name); + exchange.setLayoutParams(params); + return exchange; + } + + public void setSwapProviders(Set swapProviders) + { + preferredSwapProviders.removeAllViews(); + for (SwapProvider provider : this.swapProviders) + { + if (swapProviders.contains(provider.key)) + { + preferredSwapProviders.addView(createTextView(provider.name)); + } + } + preferredSwapProviders.invalidate(); } public void setChains(List chains) diff --git a/app/src/main/java/com/alphawallet/app/widget/TokenSelector.java b/app/src/main/java/com/alphawallet/app/widget/TokenSelector.java index 02768154fe..4c74fb4ec2 100644 --- a/app/src/main/java/com/alphawallet/app/widget/TokenSelector.java +++ b/app/src/main/java/com/alphawallet/app/widget/TokenSelector.java @@ -10,19 +10,16 @@ import android.util.AttributeSet; import android.view.View; import android.widget.EditText; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import androidx.core.content.ContextCompat; import com.alphawallet.app.R; -import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Token; import com.alphawallet.app.util.Utils; -import com.bumptech.glide.Glide; import com.google.android.material.button.MaterialButton; - public class TokenSelector extends LinearLayout { private final Handler handler = new Handler(Looper.getMainLooper()); @@ -38,7 +35,7 @@ public class TokenSelector extends LinearLayout private final TextView error; private Runnable runnable; private TokenSelectorEventListener callback; - private Connection.LToken tokenItem; + private Token tokenItem; public TokenSelector(Context context, AttributeSet attrs) { @@ -146,7 +143,7 @@ public void reset() setVisibility(View.VISIBLE); } - public void init(Connection.LToken tokenItem) + public void init(Token tokenItem) { this.tokenItem = tokenItem; @@ -192,7 +189,7 @@ public void afterTextChanged(Editable editable) }); } - public Connection.LToken getToken() + public Token getToken() { return this.tokenItem; } @@ -202,14 +199,14 @@ public String getAmount() return editText.getText().toString(); } - public void clearAmount() + public void setAmount(String amount) { - editText.getText().clear(); + editText.setText(amount); } - public void setAmount(String amount) + public void clearAmount() { - editText.setText(amount); + editText.getText().clear(); } public void setBalance(String amount) @@ -258,7 +255,7 @@ public interface TokenSelectorEventListener /** * Triggered when a new Token is selected. **/ - void onSelectionChanged(Connection.LToken token); + void onSelectionChanged(Token token); /** * Triggered when the `Max` button is clicked. diff --git a/app/src/main/res/drawable/ic_swap_horizontal.xml b/app/src/main/res/drawable/ic_swap_horizontal.xml new file mode 100644 index 0000000000..5550dac617 --- /dev/null +++ b/app/src/main/res/drawable/ic_swap_horizontal.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/select_masking_circle.xml b/app/src/main/res/drawable/select_masking_circle.xml index 11731c2d51..d461be3579 100644 --- a/app/src/main/res/drawable/select_masking_circle.xml +++ b/app/src/main/res/drawable/select_masking_circle.xml @@ -5,8 +5,7 @@ android:thicknessRatio="1" android:useLevel="false"> + android:type="radial" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_select_route.xml b/app/src/main/res/layout/activity_select_route.xml new file mode 100644 index 0000000000..2b42773762 --- /dev/null +++ b/app/src/main/res/layout/activity_select_route.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_swap.xml b/app/src/main/res/layout/activity_swap.xml index 031fbbbc66..266a09e616 100644 --- a/app/src/main/res/layout/activity_swap.xml +++ b/app/src/main/res/layout/activity_swap.xml @@ -119,26 +119,41 @@ android:text="@string/action_open_settings" /> + + + android:visibility="gone" + tools:visibility="visible"> + + + custom:tokenInfoLabel="@string/label_provider" + tools:visibility="visible" /> + custom:tokenInfoLabel="@string/label_provider_website" /> + + + + diff --git a/app/src/main/res/layout/dialog_swap_settings.xml b/app/src/main/res/layout/dialog_swap_settings.xml index 54be936f8d..707fc4d1f2 100644 --- a/app/src/main/res/layout/dialog_swap_settings.xml +++ b/app/src/main/res/layout/dialog_swap_settings.xml @@ -3,6 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" + xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical"> + + + + @@ -43,6 +44,12 @@ app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" tools:visibility="visible" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_chain_select.xml b/app/src/main/res/layout/item_chain_select.xml index c9ef1b78ba..19cd634062 100644 --- a/app/src/main/res/layout/item_chain_select.xml +++ b/app/src/main/res/layout/item_chain_select.xml @@ -9,13 +9,13 @@ android:paddingStart="@dimen/small_12" android:paddingEnd="@dimen/tiny_8"> - + tools:src="@drawable/ic_ethereum" /> + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_route.xml b/app/src/main/res/layout/item_route.xml new file mode 100644 index 0000000000..0dc18f33ac --- /dev/null +++ b/app/src/main/res/layout/item_route.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_standard_header.xml b/app/src/main/res/layout/item_standard_header.xml index ffe880589c..4f6d76c72c 100644 --- a/app/src/main/res/layout/item_standard_header.xml +++ b/app/src/main/res/layout/item_standard_header.xml @@ -1,5 +1,6 @@ + android:visibility="gone" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 8615cfb169..d47f435bce 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -916,4 +916,16 @@ Términos de servicio Billeteras conectadas Rareza + Intercambios preferidos + Tarifa de gasolina: %s + Fetching Routes + Obtención de rutas + Seleccionar intercambios + Nuevas rutas en %s + Cantidad a intercambiar + Sitio web del proveedor + Detalles de cotización + Intercambiar a través de %s + No se encontraron rutas para los parámetros dados. + Seleccione al menos un intercambio. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index fd742515f4..854eb89b95 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -929,4 +929,16 @@ Conditions d\'utilisation Portefeuilles connectés Rareté + Échanges préférés + Frais de gaz: %s + Récupération d\'itinéraires + Sélectionnez l\'itinéraire + Sélectionnez les échanges + Nouvelles routes dans %s + Montant à échanger + Site Web du fournisseur + Détails du devis + Échange via %s + Aucune route trouvée pour les paramètres donnés. + Sélectionnez au moins un échange. diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 57c5f1b551..a1aa5880a8 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -929,4 +929,16 @@ Ketentuan Layanan Dompet yang terhubung Keanehan + Pertukaran Pilihan + Pertukaran Pilihan: %s + Mengambil Rute + Pilih Rute + Pilih Pertukaran + Rute Baru di %s + Jumlah Untuk Tukar + Provider Website + Detail Kutipan + Tukar melalui %s + Tidak ada rute yang ditemukan untuk parameter yang diberikan. + Pilih setidaknya satu bursa. diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index a783aef229..ddec40adc3 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -950,4 +950,16 @@ %1$s ချိန်ခွင်လျှာမလုံလောက် ကိုယ်ရေးအချက်အလက်မူဝါဒ ရှားပါးသည်။ + နှစ်သက်သော ဖလှယ်မှုများ + ဓာတ်ငွေ့ကြေး: %s + လမ်းကြောင်းများ ရယူခြင်း။ + လမ်းကြောင်းကို ရွေးပါ။ + Exchanges ကို ရွေးပါ။ + လမ်းကြောင်းအသစ်များ %s + လဲလှယ်ရန် ပမာဏ + ဝန်ဆောင်မှုပေးသော ဝဘ်ဆိုဒ် + ကိုးကားအသေးစိတ် + မှတဆင့်လဲလှယ်ပါ။ %s + ပေးထားသော ကန့်သတ်ဘောင်များအတွက် လမ်းကြောင်းများ ရှာမတွေ့ပါ။ + အနည်းဆုံးလဲလှယ်မှုတစ်ခုကို ရွေးပါ။ diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 48eb779608..044d1bf5e4 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -929,4 +929,16 @@ Chuyển giao an toàn Ví kết nối Việc hiếm có + Sở giao dịch ưu tiên + Phí xăng: %s + Tìm nạp các tuyến đường + Chọn tuyến đường + Chọn trao đổi + Các tuyến đường mới trong %s + Số tiền để hoán đổi + Trang web của nhà cung cấp + Trích dẫn Chi tiết + Hoán đổi qua %s + Không tìm thấy các tuyến đường cho các thông số đã cho. + Chọn ít nhất một sàn giao dịch. diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index bc3dd91c3f..8e06c7008b 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -916,4 +916,16 @@ 服务条款 已连接的钱包 稀有度 + 首选交易所 + 汽油费: %s + 获取路线 + 选择路线 + 选择交易所 + 新航线 %s + 交换金额 + 提供者网站 + 报价详情 + 通过 %s 交换 + 没有找到给定参数的路由。 + 至少选择一个交易所。 diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 13c29970b6..ca7e42edde 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -36,8 +36,12 @@ + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c96b6bdbac..e964d05ba1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -932,7 +932,8 @@ Slippage Open Settings No connections found for this chain. - Fees + Gas Fee + Other Fees Current Price Minimum Received Balance: @@ -989,4 +990,16 @@ ETH 0 Rarity + Preferred Exchanges + Gas Fee: %s + Fetching Routes + Select Route + Select Exchanges + New Routes in %s + Amount To Swap + Provider Website + Quote Details + Swap via %s + No routes found for the given parameters. + Select at least one exchange. diff --git a/app/src/test/java/com/alphawallet/app/entity/lifi/ActionTest.java b/app/src/test/java/com/alphawallet/app/entity/lifi/ActionTest.java new file mode 100644 index 0000000000..eed2ee523c --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/entity/lifi/ActionTest.java @@ -0,0 +1,23 @@ +package com.alphawallet.app.entity.lifi; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import org.junit.Test; + +public class ActionTest +{ + @Test + public void should_return_current_price() + { + Action action = new Action(); + action.fromToken = new Token(); + action.toToken = new Token(); + action.fromToken.priceUSD = "5"; + action.fromToken.decimals = 18; + action.toToken.priceUSD = "1000"; + action.toToken.decimals = 18; + + assertThat(action.getCurrentPrice(), equalTo("0.005")); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/entity/lifi/QuoteTest.java b/app/src/test/java/com/alphawallet/app/entity/lifi/QuoteTest.java deleted file mode 100644 index be6cadd866..0000000000 --- a/app/src/test/java/com/alphawallet/app/entity/lifi/QuoteTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.alphawallet.app.entity.lifi; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsEqual.equalTo; - -import org.junit.Test; - -public class QuoteTest -{ - @Test - public void should_return_current_price() - { - Quote quote = new Quote(); - quote.action = new Quote.Action(); - quote.action.fromToken = new Connection.LToken(); - quote.action.toToken = new Connection.LToken(); - quote.action.fromToken.priceUSD = "5"; - quote.action.toToken.priceUSD = "1000"; - - assertThat(quote.getCurrentPrice(), equalTo("5000")); - } -} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/entity/lifi/ConnectionTest.java b/app/src/test/java/com/alphawallet/app/entity/lifi/TokenTest.java similarity index 85% rename from app/src/test/java/com/alphawallet/app/entity/lifi/ConnectionTest.java rename to app/src/test/java/com/alphawallet/app/entity/lifi/TokenTest.java index 81ccb252ca..6c7d72a6ca 100644 --- a/app/src/test/java/com/alphawallet/app/entity/lifi/ConnectionTest.java +++ b/app/src/test/java/com/alphawallet/app/entity/lifi/TokenTest.java @@ -5,12 +5,12 @@ import org.junit.Test; -public class ConnectionTest +public class TokenTest { @Test public void getFiatValue() { - Connection.LToken lToken = new Connection.LToken(); + Token lToken = new Token(); lToken.priceUSD = "6.72"; lToken.balance = "1"; @@ -20,7 +20,7 @@ public void getFiatValue() @Test public void getFiatValue_should_handle_exception() { - Connection.LToken lToken = new Connection.LToken(); + Token lToken = new Token(); lToken.priceUSD = "6.72"; lToken.balance = ""; assertThat(lToken.getFiatValue(), equalTo(0.0)); diff --git a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java index bf5bec3dbf..84e4513f27 100644 --- a/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java +++ b/app/src/test/java/com/alphawallet/app/ui/widget/adapter/TokenFilterTest.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Token; import org.junit.Before; import org.junit.Test; @@ -20,17 +21,18 @@ public class TokenFilterTest @Before public void setUp() throws Exception { - List list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(createToken("Ethereum", "ETH", "1")); list.add(createToken("Solana", "SOL", "2")); list.add(createToken("Binance", "BNB", "3")); + list.add(createToken("", "", "4")); tokenFilter = new TokenFilter(list); } @Test public void nameContains() { - List result = tokenFilter.filterBy("an"); + List result = tokenFilter.filterBy("an"); assertThat(result.size(), equalTo(2)); assertThat(result.get(0).name, equalTo("Solana")); assertThat(result.get(1).name, equalTo("Binance")); @@ -39,7 +41,7 @@ public void nameContains() @Test public void nameStartsWith() { - List result = tokenFilter.filterBy("So"); + List result = tokenFilter.filterBy("So"); assertThat(result.size(), equalTo(1)); assertThat(result.get(0).name, equalTo("Solana")); } @@ -47,7 +49,7 @@ public void nameStartsWith() @Test public void symbolContains() { - List result = tokenFilter.filterBy("B"); + List result = tokenFilter.filterBy("B"); assertThat(result.size(), equalTo(1)); assertThat(result.get(0).name, equalTo("Binance")); } @@ -55,7 +57,7 @@ public void symbolContains() @Test public void symbolStartsWith() { - List result = tokenFilter.filterBy("S"); + List result = tokenFilter.filterBy("S"); assertThat(result.size(), equalTo(1)); assertThat(result.get(0).name, equalTo("Solana")); } @@ -63,7 +65,7 @@ public void symbolStartsWith() @Test public void should_be_case_insensitive() { - List result = tokenFilter.filterBy("s"); + List result = tokenFilter.filterBy("s"); assertThat(result.size(), equalTo(1)); assertThat(result.get(0).name, equalTo("Solana")); @@ -75,22 +77,22 @@ public void should_be_case_insensitive() @Test public void should_sort_starts_with_in_front_of_contains() { - List list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(createToken("Solana", "SOL", "2")); list.add(createToken("WETH", "WETH", "2")); list.add(createToken("Ethereum", "ETH", "1")); tokenFilter = new TokenFilter(list); - List result = tokenFilter.filterBy("eth"); + List result = tokenFilter.filterBy("eth"); assertThat(result.size(), equalTo(2)); assertThat(result.get(0).name, equalTo("Ethereum")); assertThat(result.get(1).name, equalTo("WETH")); } @NonNull - private Connection.LToken createToken(String name, String symbol, String address) + private Token createToken(String name, String symbol, String address) { - Connection.LToken e = new Connection.LToken(); + Token e = new Token(); e.name = name; e.symbol = symbol; e.address = address; diff --git a/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java b/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java index 470a1f4c66..4c4452d1c0 100644 --- a/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java +++ b/app/src/test/java/com/alphawallet/app/util/SwapUtilsTest.java @@ -3,8 +3,11 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; -import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Action; +import com.alphawallet.app.entity.lifi.Estimate; +import com.alphawallet.app.entity.lifi.GasCost; import com.alphawallet.app.entity.lifi.Quote; +import com.alphawallet.app.entity.lifi.Token; import org.junit.Test; @@ -15,16 +18,16 @@ public class SwapUtilsTest @Test public void should_return_formatted_total_gas_fees() { - ArrayList gasCostList = new ArrayList<>(); - Quote.Estimate.GasCost gasCost1 = new Quote.Estimate.GasCost(); + ArrayList gasCostList = new ArrayList<>(); + GasCost gasCost1 = new GasCost(); gasCost1.amount = "1000000000000000000"; - gasCost1.token = new Quote.Estimate.GasCost.Token(); + gasCost1.token = new Token(); gasCost1.token.symbol = "ETH"; gasCost1.token.decimals = 18; - Quote.Estimate.GasCost gasCost2 = new Quote.Estimate.GasCost(); + GasCost gasCost2 = new GasCost(); gasCost2.amount = "2000000000000000000"; - gasCost2.token = new Quote.Estimate.GasCost.Token(); + gasCost2.token = new Token(); gasCost2.token.symbol = "MATIC"; gasCost2.token.decimals = 18; @@ -37,9 +40,9 @@ public void should_return_formatted_total_gas_fees() @Test public void should_return_formatted_gas_fee() { - Quote.Estimate.GasCost gasCost = new Quote.Estimate.GasCost(); + GasCost gasCost = new GasCost(); gasCost.amount = "1000000000000000000"; - gasCost.token = new Quote.Estimate.GasCost.Token(); + gasCost.token = new Token(); gasCost.token.symbol = "ETH"; gasCost.token.decimals = 18; @@ -49,30 +52,34 @@ public void should_return_formatted_gas_fee() @Test public void should_return_formatted_minimum_received() { - Quote quote = new Quote(); - quote.action = new Quote.Action(); - quote.action.toToken = new Connection.LToken(); - quote.estimate = new Quote.Estimate(); - quote.estimate.toAmountMin = "1000000"; - quote.action.toToken.decimals = 6; - quote.action.toToken.symbol = "ETH"; + Action action = new Action(); + action.toToken = new Token(); + action.toToken.decimals = 6; + action.toToken.symbol = "ETH"; - assertThat(SwapUtils.getMinimumAmountReceived(quote), equalTo("1.000000 ETH")); + Estimate estimate1 = new Estimate(); + estimate1.toAmountMin = "1000000"; + assertThat(SwapUtils.getFormattedMinAmount(estimate1, action), equalTo("1 ETH")); + + Estimate estimate2 = new Estimate(); + estimate2.toAmountMin = "1234567"; + assertThat(SwapUtils.getFormattedMinAmount(estimate2, action), equalTo("1.2345 ETH")); } @Test public void should_return_formatted_current_price() { - Quote quote = new Quote(); - quote.action = new Quote.Action(); - quote.action.fromToken = new Connection.LToken(); - quote.action.toToken = new Connection.LToken(); - quote.action.fromToken.priceUSD = "5"; - quote.action.fromToken.symbol = "ETH"; - quote.action.toToken.priceUSD = "1000"; - quote.action.toToken.symbol = "USDC"; + Action action = new Action(); + action.fromToken = new Token(); + action.toToken = new Token(); + action.fromToken.priceUSD = "2000"; + action.fromToken.symbol = "ETH"; + action.fromToken.decimals = 18; + action.toToken.priceUSD = "1"; + action.toToken.symbol = "USDC"; + action.toToken.decimals = 6; - String expected = "1 ETH ≈ 5000 USDC"; - assertThat(SwapUtils.getFormattedCurrentPrice(quote), equalTo(expected)); + String expected = "1 ETH ≈ 2000 USDC"; + assertThat(SwapUtils.getFormattedCurrentPrice(action), equalTo(expected)); } } \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/viewmodel/TokensTest.java b/app/src/test/java/com/alphawallet/app/viewmodel/TokensTest.java index 910d45037d..c6a058005a 100644 --- a/app/src/test/java/com/alphawallet/app/viewmodel/TokensTest.java +++ b/app/src/test/java/com/alphawallet/app/viewmodel/TokensTest.java @@ -4,6 +4,7 @@ import static org.hamcrest.core.IsEqual.equalTo; import com.alphawallet.app.entity.lifi.Connection; +import com.alphawallet.app.entity.lifi.Token; import org.junit.Test; @@ -15,7 +16,7 @@ public class TokensTest @Test public void sort_token_by_fiat_value_in_DESC() { - List list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(createToken("Ethereum", "ETH", "0x0", 0)); list.add(createToken("Binance Smart Chain", "BNB", "0x1", 1)); list.add(createToken("Solana", "SOL", "0x2", 2)); @@ -30,7 +31,7 @@ public void sort_token_by_fiat_value_in_DESC() @Test public void sort_tokens_by_name_alphabetically() { - List list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(createToken("Ethereum", "ETH", "0x0", 0)); list.add(createToken("Binance Smart Chain", "BNB", "0x1", 0)); list.add(createToken("Solana", "SOL", "0x2", 0)); @@ -45,7 +46,7 @@ public void sort_tokens_by_name_alphabetically() @Test public void sort_name_should_return_native_token_first() { - List list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(createToken("Solana", "SOL", "0x0", 0)); list.add(createToken("Stox", "STX", "0x0000000000000000000000000000000000000000", 0)); list.add(createToken("stETH", "stETH", "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 0)); @@ -60,7 +61,7 @@ public void sort_name_should_return_native_token_first() @Test public void sort_name_should_be_case_insensitive() { - List list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(createToken("Stox", "STX", "0x0", 0)); list.add(createToken("stETH", "stETH", "0x3", 0)); @@ -70,9 +71,9 @@ public void sort_name_should_be_case_insensitive() assertThat(list.get(1).symbol, equalTo("STX")); } - private Connection.LToken createToken(String name, String symbol, String address, double fiatEquivalent) + private Token createToken(String name, String symbol, String address, double fiatEquivalent) { - Connection.LToken lToken = new Connection.LToken(); + Token lToken = new Token(); lToken.name = name; lToken.symbol = symbol; lToken.address = address; From 60499cf3a989f56586ea026557e572e93882bfe9 Mon Sep 17 00:00:00 2001 From: justindg Date: Sun, 2 Oct 2022 20:29:35 -0700 Subject: [PATCH 112/183] Testnet Update - Added Arbitrum Goerli, Optimism Goerli, Sepolia networks (#2858) * Add new networks - Optimism Goerli, Arbitrum Goerli, Sepolia * Mark Deprecated Testnets * Make goerli default --- app/src/main/java/com/alphawallet/app/C.java | 6 + .../app/repository/EthereumNetworkBase.java | 106 ++++++++++++------ .../adapter/MultiSelectNetworkAdapter.java | 11 ++ .../com/alphawallet/app/widget/TokenIcon.java | 19 ++++ app/src/main/res/drawable/ic_sepolia_test.png | Bin 0 -> 127735 bytes .../main/res/layout/item_network_check.xml | 50 ++++++--- app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-id/strings.xml | 1 + app/src/main/res/values-my/strings.xml | 1 + app/src/main/res/values-vi/strings.xml | 1 + app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/colors_misc.xml | 1 + app/src/main/res/values/strings.xml | 1 + .../ethereum/EthereumNetworkBase.java | 12 ++ 15 files changed, 160 insertions(+), 52 deletions(-) create mode 100644 app/src/main/res/drawable/ic_sepolia_test.png diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index b887c46b91..f4408f1230 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -59,6 +59,9 @@ public abstract class C { public static final String MILKOMEDA_TESTNET_NAME = "Milkomeda Cardano (Test)"; public static final String PHI_NETWORK_NAME = "PHI"; public static final String PHI_V2_NETWORK_NAME = "PHI v2"; + public static final String SEPOLIA_TESTNET_NAME = "Sepolia (Test)"; + public static final String OPTIMISM_GOERLI_TESTNET_NAME = "Optimism Goerli (Test)"; + public static final String ARBITRUM_GOERLI_TESTNET_NAME = "Arbitrum Goerli (Test)"; public static final String ETHEREUM_TICKER_NAME = "ethereum"; public static final String CLASSIC_TICKER_NAME = "ethereum-classic"; @@ -92,6 +95,9 @@ public abstract class C { public static final String MILKOMEDA_SYMBOL = "milkADA"; public static final String MILKOMEDA_TEST_SYMBOL = "milktADA"; public static final String PHI_NETWORK_SYMBOL = "\u03d5"; + public static final String SEPOLIA_SYMBOL = "ETH"; + public static final String OPTIMISM_GOERLI_TEST_SYMBOL = "ETH"; + public static final String ARBITRUM_GOERLI_TEST_SYMBOL = "AGOR"; public static final String BURN_ADDRESS = "0x0000000000000000000000000000000000000000"; diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 6219475e05..ed77138a15 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -3,6 +3,7 @@ /* Please don't add import android at this point. Later this file will be shared * between projects including non-Android projects */ +import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_SIGMA1_ID; @@ -33,6 +34,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISM_GOERLI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_NETWORK_V2_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; @@ -49,6 +51,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.SEPOLIA_TESTNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.SOKOL_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; @@ -187,6 +190,11 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String AURORA_MAINNET_RPC_URL = "https://mainnet.aurora.dev"; public static final String AURORA_TESTNET_RPC_URL = "https://testnet.aurora.dev"; public static final String PHI_NETWORK_RPC = "https://rpc1.phi.network"; + public static final String SEPOLIA_TESTNET_RPC_URL = "https://rpc.sepolia.dev"; + public static final String OPTIMISM_GOERLI_TESTNET_RPC_URL = "https://optimism-goerli.infura.io/v3/" + keyProvider.getInfuraKey(); + public static final String ARBITRUM_GOERLI_TESTNET_RPC_URL = "https://arbitrum-goerli.infura.io/v3/" + keyProvider.getInfuraKey(); + public static final String OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL = "https://goerli.optimism.io"; + public static final String ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL = "https://goerli-rollup.arbitrum.io/rpc"; //All chains that have fiat/real value (not testnet) must be put here //Note: This list also determines the order of display for main net chains in the wallet. @@ -197,6 +205,16 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy FANTOM_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID, PHI_V2_MAIN_ID, PHI_MAIN_ID)); + private static final List testnetList = new ArrayList<>(Arrays.asList( + GOERLI_ID, BINANCE_TEST_ID, HECO_TEST_ID, CRONOS_TEST_ID, OPTIMISM_GOERLI_TEST_ID, KLAYTN_BAOBAB_ID, + FANTOM_TEST_ID, IOTEX_TESTNET_ID, FUJI_TEST_ID, POLYGON_TEST_ID, MILKOMEDA_C1_TEST_ID, ARTIS_TAU1_ID, + ARBITRUM_GOERLI_TEST_ID, SEPOLIA_TESTNET_ID, AURORA_TESTNET_ID, PALM_TEST_ID, + //Deprecated networks + ROPSTEN_ID, RINKEBY_ID, KOVAN_ID, OPTIMISTIC_TEST_ID, SOKOL_ID, ARBITRUM_TEST_ID)); + + private static final List deprecatedNetworkList = new ArrayList<>(Arrays.asList( + RINKEBY_ID, ROPSTEN_ID, KOVAN_ID, SOKOL_ID, OPTIMISTIC_TEST_ID, ARBITRUM_TEST_ID)); + // for reset built-in network private static final LongSparseArray builtinNetworkMap = new LongSparseArray() { { @@ -220,22 +238,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy ARTIS_SIGMA1_RPC_URL, "https://explorer.sigma1.artis.network/tx/", ARTIS_SIGMA1_ID, ARTIS_SIGMA1_RPC_URL, "https://explorer.sigma1.artis.network/api?")); - put(KOVAN_ID, new NetworkInfo(C.KOVAN_NETWORK_NAME, C.ETH_SYMBOL, - KOVAN_RPC_URL, - "https://kovan.etherscan.io/tx/", KOVAN_ID, - KOVAN_FALLBACK_RPC_URL, "https://api-kovan.etherscan.io/api?")); - put(ROPSTEN_ID, new NetworkInfo(C.ROPSTEN_NETWORK_NAME, C.ETH_SYMBOL, - ROPSTEN_RPC_URL, - "https://ropsten.etherscan.io/tx/", ROPSTEN_ID, - ROPSTEN_FALLBACK_RPC_URL, "https://api-ropsten.etherscan.io/api?")); - put(SOKOL_ID, new NetworkInfo(C.SOKOL_NETWORK_NAME, C.POA_SYMBOL, - SOKOL_RPC_URL, - "https://blockscout.com/poa/sokol/tx/", SOKOL_ID, - SOKOL_RPC_URL, "https://blockscout.com/poa/sokol/api?")); - put(RINKEBY_ID, new NetworkInfo(C.RINKEBY_NETWORK_NAME, C.ETH_SYMBOL, - RINKEBY_RPC_URL, - "https://rinkeby.etherscan.io/tx/", RINKEBY_ID, - RINKEBY_FALLBACK_RPC_URL, "https://api-rinkeby.etherscan.io/api?")); put(GOERLI_ID, new NetworkInfo(C.GOERLI_NETWORK_NAME, C.GOERLI_SYMBOL, GOERLI_RPC_URL, "https://goerli.etherscan.io/tx/", GOERLI_ID, @@ -287,10 +289,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy OPTIMISTIC_MAIN_URL, "https://optimistic.etherscan.io/tx/", OPTIMISTIC_MAIN_ID, OPTIMISTIC_MAIN_FALLBACK_URL, "https://api-optimistic.etherscan.io/api?")); - put(OPTIMISTIC_TEST_ID, new NetworkInfo(C.OPTIMISTIC_TEST_NETWORK, C.ETH_SYMBOL, - OPTIMISTIC_TEST_URL, - "https://kovan-optimistic.etherscan.io/tx/", OPTIMISTIC_TEST_ID, OPTIMISTIC_TEST_FALLBACK_URL, - "https://api-kovan-optimistic.etherscan.io/api?")); put(CRONOS_MAIN_ID, new NetworkInfo(C.CRONOS_MAIN_NETWORK, C.CRONOS_SYMBOL, CRONOS_MAIN_RPC_URL, "https://cronoscan.com/tx/", CRONOS_MAIN_ID, CRONOS_MAIN_RPC_URL, @@ -303,10 +301,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy ARBITRUM_MAINNET_RPC, "https://arbiscan.io/tx/", ARBITRUM_MAIN_ID, ARBITRUM_FALLBACK_MAINNET_RPC, "https://api.arbiscan.io/api?")); - put(ARBITRUM_TEST_ID, new NetworkInfo(C.ARBITRUM_TEST_NETWORK, C.ARBITRUM_TEST_SYMBOL, - ARBITRUM_TESTNET_RPC, - "https://testnet.arbiscan.io/tx/", ARBITRUM_TEST_ID, ARBITRUM_FALLBACK_TESTNET_RPC, - "https://testnet.arbiscan.io/api?")); //no transaction API put(PALM_ID, new NetworkInfo(C.PALM_NAME, C.PALM_SYMBOL, PALM_RPC_URL, "https://explorer.palm.io/tx/", PALM_ID, PALM_RPC_FALLBACK_URL, @@ -315,7 +309,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy PALM_TEST_RPC_URL, "https://explorer.palm-uat.xyz/tx/", PALM_TEST_ID, PALM_TEST_RPC_FALLBACK_URL, "https://explorer.palm-uat.xyz/api?")); - put(KLAYTN_ID, new NetworkInfo(C.KLAYTN_NAME, C.KLAYTN_SYMBOL, USE_KLAYTN_RPC, "https://scope.klaytn.com/tx/", KLAYTN_ID, KLAYTN_RPC, @@ -338,7 +331,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(AURORA_TESTNET_ID, new NetworkInfo(C.AURORA_TESTNET_NAME, C.ETH_SYMBOL, AURORA_TESTNET_RPC_URL, "https://testnet.aurorascan.dev/tx/", AURORA_TESTNET_ID, "", "https://api-testnet.aurorascan.dev/api?")); - put(MILKOMEDA_C1_ID, new NetworkInfo(C.MILKOMEDA_NAME, C.MILKOMEDA_SYMBOL, MILKOMEDA_C1_RPC, "https://explorer-mainnet-cardano-evm.c1.milkomeda.com/tx/", MILKOMEDA_C1_ID, "", @@ -355,6 +347,44 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy PHI_NETWORK_V2_RPC, "https://phiscan.com/tx/", PHI_V2_MAIN_ID, "", "https://phiscan.com/api?")); + put(SEPOLIA_TESTNET_ID, new NetworkInfo(C.SEPOLIA_TESTNET_NAME, C.SEPOLIA_SYMBOL, + SEPOLIA_TESTNET_RPC_URL, + "https://sepolia.etherscan.io/tx/", SEPOLIA_TESTNET_ID, "", + "https://sepolia.etherscan.io/api?")); + put(OPTIMISM_GOERLI_TEST_ID, new NetworkInfo(C.OPTIMISM_GOERLI_TESTNET_NAME, C.OPTIMISM_GOERLI_TEST_SYMBOL, + OPTIMISM_GOERLI_TESTNET_RPC_URL, + "https://blockscout.com/optimism/goerli/tx/", OPTIMISM_GOERLI_TEST_ID, OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL, + "https://blockscout.com/optimism/goerli/api?")); + put(ARBITRUM_GOERLI_TEST_ID, new NetworkInfo(C.ARBITRUM_GOERLI_TESTNET_NAME, C.ARBITRUM_SYMBOL, + ARBITRUM_GOERLI_TESTNET_RPC_URL, + "https://goerli-rollup-explorer.arbitrum.io/tx/", ARBITRUM_GOERLI_TEST_ID, ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL, + "https://goerli-rollup-explorer.arbitrum.io/api?")); + + // Deprecated Networks + put(ROPSTEN_ID, new NetworkInfo(C.ROPSTEN_NETWORK_NAME, C.ETH_SYMBOL, + ROPSTEN_RPC_URL, + "https://ropsten.etherscan.io/tx/", ROPSTEN_ID, + ROPSTEN_FALLBACK_RPC_URL, "https://api-ropsten.etherscan.io/api?")); + put(RINKEBY_ID, new NetworkInfo(C.RINKEBY_NETWORK_NAME, C.ETH_SYMBOL, + RINKEBY_RPC_URL, + "https://rinkeby.etherscan.io/tx/", RINKEBY_ID, + RINKEBY_FALLBACK_RPC_URL, "https://api-rinkeby.etherscan.io/api?")); + put(KOVAN_ID, new NetworkInfo(C.KOVAN_NETWORK_NAME, C.ETH_SYMBOL, + KOVAN_RPC_URL, + "https://kovan.etherscan.io/tx/", KOVAN_ID, + KOVAN_FALLBACK_RPC_URL, "https://api-kovan.etherscan.io/api?")); + put(SOKOL_ID, new NetworkInfo(C.SOKOL_NETWORK_NAME, C.POA_SYMBOL, + SOKOL_RPC_URL, + "https://blockscout.com/poa/sokol/tx/", SOKOL_ID, + SOKOL_RPC_URL, "https://blockscout.com/poa/sokol/api?")); + put(OPTIMISTIC_TEST_ID, new NetworkInfo(C.OPTIMISTIC_TEST_NETWORK, C.ETH_SYMBOL, + OPTIMISTIC_TEST_URL, + "https://kovan-optimistic.etherscan.io/tx/", OPTIMISTIC_TEST_ID, OPTIMISTIC_TEST_FALLBACK_URL, + "https://api-kovan-optimistic.etherscan.io/api?")); + put(ARBITRUM_TEST_ID, new NetworkInfo(C.ARBITRUM_TEST_NETWORK, C.ARBITRUM_TEST_SYMBOL, + ARBITRUM_TESTNET_RPC, + "https://testnet.arbiscan.io/tx/", ARBITRUM_TEST_ID, ARBITRUM_FALLBACK_TESTNET_RPC, + "https://testnet.arbiscan.io/api?")); //no transaction API } }; @@ -403,6 +433,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(MILKOMEDA_C1_TEST_ID, R.drawable.ic_milkomeda_test); put(PHI_MAIN_ID, R.drawable.ic_phi_network); put(PHI_V2_MAIN_ID, R.drawable.ic_phi_network); + put(SEPOLIA_TESTNET_ID, R.drawable.ic_sepolia_test); + put(OPTIMISM_GOERLI_TEST_ID, R.drawable.ic_optimism_testnet_logo); + put(ARBITRUM_GOERLI_TEST_ID, R.drawable.ic_icons_arbitrum_test); } }; @@ -447,6 +480,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(MILKOMEDA_C1_TEST_ID, R.drawable.ic_milkomeda_test); put(PHI_MAIN_ID, R.drawable.ic_phi_network); put(PHI_V2_MAIN_ID, R.drawable.ic_phi_network); + put(SEPOLIA_TESTNET_ID, R.drawable.ic_sepolia_test); + put(OPTIMISM_GOERLI_TEST_ID, R.drawable.ic_optimism_testnet_logo); + put(ARBITRUM_GOERLI_TEST_ID, R.drawable.ic_icons_arbitrum_test); } }; @@ -491,6 +527,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(MILKOMEDA_C1_TEST_ID, R.color.milkomeda_test); put(PHI_MAIN_ID, R.color.phi_network); put(PHI_V2_MAIN_ID, R.color.phi_network); + put(SEPOLIA_TESTNET_ID, R.color.sepolia); + put(OPTIMISM_GOERLI_TEST_ID, R.color.optimistic_test); + put(ARBITRUM_GOERLI_TEST_ID, R.color.arbitrum_test); } }; @@ -693,14 +732,9 @@ private void addNetworks(List result, boolean withValue) } else { - //sorted array - for (int i = 0; i < networkMap.size(); i++) + for (long networkId : testnetList) { - NetworkInfo info = networkMap.valueAt(i); - if (!hasValue.contains(info.chainId) && !result.contains(info)) - { - result.add(info); - } + result.add(networkMap.get(networkId)); } } } @@ -782,7 +816,7 @@ public List getSelectedFilters(boolean isMainNet) @Override public Long getDefaultNetwork(boolean isMainNet) { - return isMainNet ? CustomViewSettings.primaryChain : RINKEBY_ID; + return isMainNet ? CustomViewSettings.primaryChain : GOERLI_ID; } @Override @@ -1118,4 +1152,8 @@ public NetworkInfo getBuiltInNetwork(long chainId) return builtinNetworkMap.get(chainId); } + public static boolean isNetworkDeprecated(long chainId) + { + return deprecatedNetworkList.contains(chainId); + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MultiSelectNetworkAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MultiSelectNetworkAdapter.java index 2934e49374..2e9c761387 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MultiSelectNetworkAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MultiSelectNetworkAdapter.java @@ -9,6 +9,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.alphawallet.app.R; +import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.ui.widget.entity.NetworkItem; import com.alphawallet.app.widget.TokenIcon; import com.google.android.material.checkbox.MaterialCheckBox; @@ -76,6 +77,14 @@ public void onBindViewHolder(MultiSelectNetworkAdapter.ViewHolder holder, int po holder.manageView.setOnClickListener(v -> editListener.onEditNetwork(networkList.get(position).getChainId(), holder.manageView)); holder.checkbox.setChecked(item.isSelected()); holder.tokenIcon.bindData(item.getChainId()); + + if (EthereumNetworkBase.isNetworkDeprecated(item.getChainId())) + { + holder.deprecatedIndicator.setVisibility(View.VISIBLE); + holder.tokenIcon.setGrayscale(true); + holder.name.setAlpha(0.7f); + holder.chainId.setAlpha(0.7f); + } } } @@ -99,6 +108,7 @@ class ViewHolder extends RecyclerView.ViewHolder { View manageView; TokenIcon tokenIcon; TextView chainId; + TextView deprecatedIndicator; ViewHolder(View view) { @@ -109,6 +119,7 @@ class ViewHolder extends RecyclerView.ViewHolder { manageView = view.findViewById(R.id.manage_btn); tokenIcon = view.findViewById(R.id.token_icon); chainId = view.findViewById(R.id.chain_id); + deprecatedIndicator = view.findViewById(R.id.deprecated); } } } \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/widget/TokenIcon.java b/app/src/main/java/com/alphawallet/app/widget/TokenIcon.java index 1d1fb5759a..cf8d566cc3 100644 --- a/app/src/main/java/com/alphawallet/app/widget/TokenIcon.java +++ b/app/src/main/java/com/alphawallet/app/widget/TokenIcon.java @@ -4,6 +4,8 @@ import android.content.Context; import android.content.res.TypedArray; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; @@ -398,4 +400,21 @@ private void loadImageFromResource(int resourceId) icon.setVisibility(View.VISIBLE); findViewById(R.id.circle).setVisibility(View.VISIBLE); } + + public void setGrayscale(boolean grayscale) + { + if (grayscale) + { + ColorMatrix matrix = new ColorMatrix(); + matrix.setSaturation(0); + ColorMatrixColorFilter cf = new ColorMatrixColorFilter(matrix); + icon.setColorFilter(cf); + icon.setImageAlpha(128); + } + else + { + icon.setColorFilter(null); + icon.setImageAlpha(255); + } + } } diff --git a/app/src/main/res/drawable/ic_sepolia_test.png b/app/src/main/res/drawable/ic_sepolia_test.png new file mode 100644 index 0000000000000000000000000000000000000000..1274b0f9287ed5d184dee5eba304b4fe115b7143 GIT binary patch literal 127735 zcmV)%K#jkNP)PyA07*naRCr$Oy$6(K*L5AZ?@K>b>>L0z2oNGgfCLGU0wsu~OhO!4q~t}7tZ3S@ zY-z@lpWA5wBLD*ceE_QfmH{jQSO9Piz*zu% z-zfkm0K8y~;qP}}yCZPTjKBr%?`!7xb`RtR906;m{sjPgye4{PmR0PfH8{QfWuUuBHB z&jRz!Q(q5kn~^hr_Tb3x{;PSD@;wV9U^oWSG=&KQL{WsiD6qP^DqjTJBuUWebkOZ| z5XZ3qI41^M<~X<~7MSMmbb8R2M&`O-g1rAf|K{J<{9W~PbrRfu3ByUpT9lk12=K-% z7~m5H@F>5Bz{ia-U%Ux!i``S)<`LKh@NFL88*%g2+D;BU7yz%e7OyP}`(S9yTp+XjhMtO-d3riS`bM%KJ^an%aWg**Vrm@tM7LKNI6!PNNJTtU0Er9`>}Zc;9J?xzKRd^Ok` z!|ep%rUQzE5?xn`>=0r2HjSI{rmRdmiY)tBSQDU?xT5w z0tTf<{7MQrT84WI#&`Io2HkYwgzo zcnH87t+j9PT<=7D?LbgtOo@vHz8GZ_yfe}rIdJ?;f#*&w;N-a_EDwiR=&!&;BqfZ1 zGC|%1As89wq#%M&zVgB%2qOjCAkc|`04NNFCtK=hp417yNU8W&#e=&j+*-2Sx^He! zCm}}21l5W~sa<3=GP$fGG>ya&R9G%+KK1k%Kt0H^4L?pw2H&0-=lo zU%C&T7pDq8!TE`A1GgT5{4W5!#~AaW4ZMH%EjQT+>;m{rcEK-nx=ycg1TKi^W z%z2VLewHB0_|^lthfxCdpad3H3q1Mk^Eh#C1;@`WVriJe#vPcrgUlL?@?5~1L<1vc zesNn&STZn;!ccxDZ#^ET^1aA&c~3wPwH9ffRiCYrh!tXMBu*}xV6F+#W&|F9|NP(T zWrMztpXL7fd0SdJo+t{d?M0!1DaI0|hqgpJu-MaU;n=}_xa-!#I5MAzo{>`oqw{8j z-kel6@!(O?_~!ur48Wi6N*Z?`To)qj4#dqm0@m6W0r*w`Z*|eO421{1wd2Cyk4uXz zByeEIlkeC35RIJGRF-p}aL(_7jdo(t!fDkFIT@5jejJ zACVKnO{u)OKThH5-J@U_ofBh~ul5|a-%b=5iN5&~YQ%)X&&#$ffxJX)bAm%3)VJ?UM9{QZ0rcEz^lp zmIx0&8EG>rCXoABypG9bM<}dPG79WgqG)~zA1`m#35ffYt-F2eL6rz?A?GBVKRIsh z%c)@aTZz}p9Es6r-Hu0ShX%Lbas+qZek<-d5DCrFq*piwg-dYq=Pb{VL{Y`1a{|&l z08^pl>-`06WRCUS?}x$f1Ngn&!lE1h;ob%C8~7SqYrn%<`(35Q+X$TgrII%NA3?)| z9V2aik>fr+03Lt(1Ri_(S)5uOp^Q7o!wBQT3Weccq%1t;LJCB|S~pI>CRht_ON6R` z4y#f?AAu6Qc|4w$$g@nMasg`r_&~o0A%f7LC^Ct58EFgRI;o2&QcBV4FDs+4q*JKsZ~=QtQrFQP#~ zl8qy-Rj5-d`*BH;GJd+@549K(zEv?MBzY=MX%EIdx+u9Vh?8Xh$N#uZev z(5U8C+}*4zlv(RG*)vsdFl#U!{p$SZWiGoAGo;3El$Y{ES5Hjqd{Jsy8Qw z^0T?qqzeJW!l1_YiihXKCNmbtj1&luEfg7}EefC*BQ8_)f*gmYTX^N2x8W7H@1M|_ z^V21xZ_+0jt2_f4;HK=}$KZM^i`cSJ(<;+nb^QVS6%2ma81rj4$gO`H;FxaP$Z}Z`mSh#wwC7KMB*XGw}o?XTxPkaF{tPCUxSq5#CCWf^HCdjs1i7G@`I1^C{s8PKv_X&{_4y$IGdg|#;2UDFcIxPZrh=}xvM5|Pi zIM60{EC45{?Koa?J#{4MlZqr57>2G@nADO$g)|o!I{?*~)zcilUXtIbXc>)D3`b)D z^l_TWCS0^p3w%feP)QfcYF1hknr<%C2kh{~O^M3$v6RI8BRR^nWC z#3XMoHkgfp2VZ^{?!Bcam7r}El2?;g!v>%V?MU>Crz!)s@4_7D*MAYlG>bD^xKLX#$y?F9s5nmVN&j0zUru z7tk*YjKdIpKIE+~(v19Z0)D{eN_j9sruJE4*T4vnC*+vRLI6p@)p@8n_ z40m0nNXQZXYE9)5rovylxlIzWo;tC}ib4RrKN?{;9wQ|stOk`b3g zi;Y3#z6d z;3JP8$0xq@EY4;DQfjs>)f^FQo=Z}ZpDC#fk(D-={M2KIXpx_m2u?DDE)3)Ws768( zjHFV^0_`}$p4n;4O;1S@PE1$1O{ec>WG=Ejv53{5>(}{!qMWw_RHv*E?Y9*6IIoe0 z0>-_4O%al(OeSx00;DiAo+B49bwx%lS{Ke+-r}o8^_cm)<<%ipha(JzLu8~$m=q;4_co-ZF)CK8Xa%uYWt?t= zuNJPGay8Q3mUN8D0U05R#i|t2s2q?9O8#!9+rhrMIdqa3rl2X5(ki-~cTt}MVQbXP z$;%HFUle#eMbMZcyv<*us78@)-G&TK%ICz~E^?o|z!ja~e(fg`l~UHxxJLbx6N{dS zQYK*>3)QmR?_+Ug75(v8e9A2qEzZA1xOxOauaH-#6i_wgO05`ENDjbDBw->cQc|ji zKV*mli-;?nA{9feLo+@6&98ka_D5Rb+2OmbM*I9`qFCuNR(?8`DbF*6Q6&6*ZLPJT z8~-?f{|Mke7-N|4-hEwTBd`nL*VqMd!2Q1f_%T2eljps-_6`g(CJJ4dx0pBufoQl- zt^n`(>(An`ljl%O&0=ICDS;2g1xlCcB@=KG$x3a=g0o5V@>2($%((sRgCQK_ns zfYD<*7Qo*(JB#_LDTxR}DJN$%sg8U?d>AJ*B&hhiO)4oBU7Eag#b2`!NB>%#dX>QB z@pFP{XtDVwRlz9L;=NDSj+^YuN&VLQn?EMemsk6497Af&p>?WaZci;Ec-oIo${4mzp4zf+9|%&I?97S4x=@0QkRlf&AJ6 zj9mb~hOURT_QwJ6Yh5EL1t>nub#)_u$6}m3Fp{AB%g-LihaY8MHHH8i(i=;*h zLXZf*^+=6HDFCkEtw}=yQ>f+hZtN!kQ-7&ExUV>>IRQeC8ejPdz)u1S+zRHdI>$j) z^Afv7%EVQ#=p1iXTX~h#K-Xj?ynA9r!MODRuLG|Qqj5&%D}y0QM%pg=RS;%Go*_+h z@!8#vY{Llb0{Auz>g8_IS|%p(zX7=IQlD+A zPDq)Esgwa;=mYQg;3GIWF0nwNw^Nna!lKt|3&+Z0mM|t5WWqzYqZqO1lJ&v%Kql6y zISWb@B$=9HD4ug~Wsa69aA@y5_RP+?gxeVGdBdcqB;&+=$|Vm4#GSv22k?RvPO}$I ztrQU|qdFFMwiDK|q#tN8I{~Q^oVw`1eWGvTeLA|NIaE&QZ+~BwuiI?4QCs_fD1oCu z+)y~`wj?PU2(?lMAqHuRb4$xu9u1YgaGvIxzzo1V=QvYsxoX!bNn{nO`+upvFHAD? zocTV{#pfxyaey!%Bguz&#qCG%4fo%HIeN)(KQa+%a>K7Blu{oemMU6jr+cZJ?ZSV5 z2Ee~F#{9zOH?jN4tr&q_0N;vH+~hW_wciQgCjh+SayH@eU1Bapg~_8&jq&ckeiVyA zfUK2BG|p(O5X*TtTaUkV^#tZV6hxzCgCs7RVhX6UFFS%vr{=lNH~e(rlu}ED~x@o6%Id|T9@BK7@pESn&?iFoi_rseW zfn5OK^w4eogVx&D1Ni4n3)hWqjS`#(Cbz&?-lm!3g)?aT^}I z=XQz4IeEubyEj!BDW~qWN|!p%4ga0iw*Sf)!v++)uN@qLOW&(IcrZ8muB^4BNd5(Y zzrWdY6-!qD&-Z~p`TstGJ|Zj^0Wy=IFl_Ftma9~gh%CVtA_t_;2qlBM?AQ0m%Na2d z%;@tWhEvjghCHk`GN9I5OXGpV`}Sa8D@II%CP}`r44oz3s-5<_YuU6=GyW%Ea<1KP zL~9|EJ9YG9+LIhFA!cc1RVI$CumWuCgUP1F0(dOvUsJ@RC*os$YOiB?4=YFGI6^y4 z#G01XkK}=ajFG5|xLtc39@C_>v3Z3iIe4ey)Zudzho^niOe<8MaA8_Pp^J3EVT4*a zy|{wa(HMi#NY0lWIad|z0h*Rp5}%}DbaGOiy=%zkB&6yDNf{z1WxmqU0PTQWc!mQl zgKznU*Wi{85S11kwNBKpNny=qZ^H|H?pJw#8)HbZ?7ntj1a<*@2L@T-#adD&|5C&n zZlCM%tNw5%WpbL3;&Pmc%EwOw@A}YRV_+?Ye2~LLdP$aLfGA+`3{@r>f{@m%1~Hoo z#4KSqDCzXqXeglN-mU;9R0lvUiPuCaxo{>r$!$|=$TnhgaR5`Os!YwX2s(^9)iJPc zs^HMV`HZNdTqSe_W2!P(^s+h{Y1LzzA!U^&yYNs0zNVaAwl5s7t{8OwnWR#@_)p228ZgOZ|57p}U5fGvHPO0r zn*j>y@mV?Q)j}MLIKpt8iDG4GrH@fjpdhaw#o|9hUVNNWVyMpQBH;{a?!^f$m! zjYj*l#;rYT0-9vmF_LTrZ@llT@xYyjB*AHNAoj(pG9ZfP9@FbdP)E+cnwf@r3@!>A zyiNZPW6V$P(4%!z?`9XkxB2p0YyTF2e+}RsdFUH9Ln_Ow(Y)?w?mVU4AE`vh!U(Hu zVgA%A-uuYskVY+e*d>A$Z*H##H)=Y?vUeItiH8Y!T3W5T3QhO$2aF6E@i~1mjh7fr z6T~Rh%jw%eK9!s`+}F9bTuDf>)j0%;JwP0x+v%X&ZcBp+u2{4Y zg;qs+T1k#XRu7slAkIsfJjcu@9ywyp#ZZe(eaKrsYTPdWCKGaA;2f!y)xJ<;Mm%WP zco{OeagtNZ0zX;$G4*$gSDTX$SDK6Y;fNaYe1MnTatLp}{|@X6ftJ>2X(%9v<=qaQ z%^CIPvbw1g%(BVqO8Q=(8%lzHhBTou<{jJoh~3ni-v#h(y8PDKTLJuA0N>l(#Uy|` zlOhczE7_Mm@{BU688*m+NNAIHKJpA6d+rQY5g}zKmnc=99Gwq}s$Dq2)&{iXux0E-w{I}Wb1VB5ZSDg2HrxT$+JE9I*v{K} zO+{+Eu_^>7AUnHPiSddINoX)e1lq>^#UoGSv1d-BUxp}?mhi^%syfm*TWf1E)$5_m zQ)lDK$4%u3v~pED*BISS8&gx$0$r=C14*#aW|f{O-YdHoHIr%G`Q{H9<(DP zz9yRRB#ls?s<`^4nQ*)`h0@ORwaku0yea`qMJ4zsTR}{zqg(*J z(@HSi>tU+b6`yk7kiuIKNJLKF+Yt}G5rc-zP6O|HbrLK^zwR{l1YD8%1yrjTtPF=( z8VssDQCGbLRJ7{0e1CSVI`JW*tn##<{i{xmk~6tMgL{(OH%%ujg3MBz%^Z{y1>SZ#W{?;fA`&w;JH=W zzIIR;x&~66;98fFE|w+>jD}TlA>1`>Nu|rX6~Lutd+*Gw_;O1xnUa8{7oQxoNb*>v zSy(I%MmTY9QNV+mWd#KFKH+`}Zd0weTdL5`X38m;Kid*7%$lQUNZ8g*}?n#zB z1ouQqDf@BSQWQvboTAG~Y1qeoUv)d)aPLtZWW86FmvKzDOF?LB3-wqLRr%I|I5+su zc9WbNLyAkiYZt&THA0v8yS4T{=MzC~_r_jsIaB`jRS!u`u-2fg+^qnjqfDAK zijT@SHjtZqm-Anh{R$_d?th9=jpK4Z`{UGjR3}YF-2_KcQXs*IX8-^o07*naRINCc zsC;@#!JNd1^vxt_)2wQuK?U2n>GY>S&+YN8%y%#W8A>!h%u5W55~miHu{_WMpu9BF zXk#=QtIU!OF&rPHu90q{2noG(vtk8jfNV_JWPo+9|syE5q zlM-__J1+I={i{g0xTX+W7xqyz{-eg2Pi*ok?tW}H0>83*z*_si(i>tkTk%|Y&57%S z%qn<#cmMuhd31QhE^kw;8utJiNv5SgnLd8UzEaiodRqZ!{WqxJ~duOK6 zi9(d=SRzDfp;^@@{utCdh<2Mvu~3>8=O)GzPd|%{|Cgi~F-|+is1G$GMV7MHpe%Ab zmx%OZ;puE2CD!>?XHUDCLED1Q=z2#d9qQhN?s3hD)f&8R)utyqInnU5-eOmkhXm0~ z=$BSP&3TNybF-32rW9YGk3~@~ammP=5wb@7Dp^#Oi;hs$z&N3MB+$=toLe1Yp+69w zoDn$HL!uiOtvoAXwR~PP672a|qI6x<1mFuETL-il<|G{3F*-qpeeD2mdGJ2GxCgX+ z9@LGoXOm(cDU|0u^WMJ;u2bGUj%>&nYV1><5f+C#(VV_ z9~0`lf9?PMI8KZMEZa6RE_(w;N939502qn1O!!vMFu_>PPl}mb zaLUS5PIQd6%Mvr)F6O4EG1YD%;aHO<5n~g6&bd6g?4X>l>priWW7nQiXe~C6Sj}?D zPb?1la!o>MC;^O0i*aF*XWXY!Tw1fE6NI#vkU}ELK)KqAT!rcgalm$WKsO)Y?>_V( zZkuu*<8mEbm|Zb6YG&q>?4E$y%)Nhs&pZs^M~pE~ZQ(X=icReT_+?&ZYwg=>c{#^8?CJvBIsFHY&t#O%l7dn z9+PiOScU;!bjwk+43Lcm(j|wq1(Q`wSehVlU3IignpmS!(qI8(Kc}RRWV; zY#4znCt6Z|=6h|f8H7rx;C^3Ir!`-@wzPh;CLIouh%K;188DHlt1DK61|_xPtZ1b_xHij(%N%>c z0^jkbSL2SZ_TZ!y0FNh23&gAf6Ma7`Om%YDhEja)Vg)Ht#(XBj zQ6QY!l#JF%mGaFX6a~xN%rvIEZA6w5Pqhc&iiTiGYAny#JX&0*v}dOCYhlKj$<1+= zO4aJA#YJh(!FC#B$&Vxwkq-tVw5jW7B9+G#NOx43h~;0QG+We)Fc{HRxGfxgJF@7e z%lLt}K8Qn!CN?>dh!jy8D_KM|RRQ~;lEU*{I=A9UIBy$l=|*?X-PZ<2U>CqQFi6(g z``Ppr0KZ@POU$HH213yt!TVj0Jc*A!dm5`j2R3YJgf5=ljM}IR&!xhSCGp)b67HJG z&YT4$(&dJ}7Yg7nI&>JlCmQ(QA z)m5BYSgOI>#Gv+NG)h(W!@?s8<5i6!r{Sn<0y#lAFl<)cLYk*2f&!h$V!9aMq5EEj z2X2{>@_Qyqc@AC&&eeh#fo=cm5di;#F^1oFUl$pHtNSEf2bacL`vU;}%hnyLMt{^! z7lAe${_q#i;(ed~0+!+q(vXa)H|uk%hf?`!MnRN>wS40OL+Zs<<9fywy zfJcrGr>?iKISkPpKoZ0lk1|nUFtQ7h1j~aFo;z_0sbzmh2i}BiXHcc)Q?3EAhM^Z7 zk}4@T0peRXiksb%>g?-|^y_V>rhy!7(g5dL&#hTMadGrEu-?vq(X)8Wkb|!KfASNd zDKVV{*grpuPSQfaq8moY4(OTFkXClpK{!uXCl{4MoiM=3g(aL?=_BX0l!BlTVbsFv zD#HQDdPM%#5nOZ9Ce&VVPm`V(t=3CqhwPWM@xa@DIs#HdYu1SnHz;J8F zbz@so0Kdrmv*!5Lt|Vk6gf>y|)6cM4!0-d#B0?F^R%SncKG%4#+WUB26y-jwsCj6 z0KU%PT5InF@GAf|uI=97MUoXRJ-ykxG6jD1kKT{Pcn;$r5xzQ!xx`JKV_zbG%hhzZ z6-hG%CMreoA<0Cox{xKes4FyyIn!?A$o{?P#F3c)Yxj6g8mda5xJ?L=FvO{aMVwn+ zkq4jPO?y(BXH}1_s|xjf7I~Vwq+ajVY5s04ed3U@0dyN2vMqg^0`LXqAGfEqiP(t= zsChIl@>Z6qg73N@h!RZl*ABo1l&M~!oRcdbTVlG?#)0`cbX&0~eN=g`w2OeYM84Y1 zUgr*_Wyouf0)rC^3s_j`i?WDae%L62UgLB#92dFXKb7J~8&9ym9fJtYBBBP$ncS4+ z0ivLQ$yTv1D)7B;{5l-!Fz2FjNXdMtqHw2Q)Qo?>G3Lpg-to1*zg+-dbA_z6lm^n* z_=0^YujHaKVM*F#3BWJ@!CzrD=pl=`l7!*|tzH`{HzPpv`AX<%9fgQpafo(kaaN$N z?Ti$QFp{H6g^A2P^O&9Lp~aA$cBOeL*0MnuV_X=aN?tf~7R$pS47{xD)r-(TLMwUiJ8S%QZ9vV5(=d<(;q+iu8ft}g|vxG*jh?NHA~8sRj-4U z(HO_ioDq9k+8+?aO%O{3C-WL(UVGo)R1Va_BmqX_u^a~zl;qvptwa3nk~aj zkmGF+eJyUGIz@cNU8R|*lXe_BSeX2M#u!QtcV9l(*d2*_1gy0`3gD+NZ%o!kn$Gju zV^|~N<2xC7(-!tO-u)<^>z5b?Em#w)vmlFQ9OJ;{ER4#ySm{SlB``};Oz4%SJF_-P z;3K6Ls3npp#7wWNMJ0>^nFKWuzwL8N>Znt0?xO7rA-d^^;PGYpTVBBUsj8SzTf3B3!4F*P>6Zu&CwM zΠE7L*y1K2ilx*;g^{zUSmFpPqY+M=Ig4S&`b$bn zBas)f5Qt8OyyoIODU*T4$c_-jiA3J~eG~`CGTNpw0uNDUs$Al6%|toA=gkk`Xbb4D zScoBbB`>WhGaaSLfzWlFZ!ql}eq1s1|Cll6XD;sZ{YM<-hNbXP zfKHnZc)I4-rs55HW8z>Nv8^jK;rl5|Bj3r`jTW-fa947XT4lM0t*#!!W&?xfTy*~U zZ1fhoc2p=ExyF}zkLQ#x^}gocUHmIu;e8>HTGQqdd3QPKwp%!~cP~mt$Zi6aM%0!~ z9x}8#9WAz%+8Qk=V(I--e}Lysokqso2B-0mj+NRJnRyj{v2lf{mRtbMTnKLhQfnT5 z`8)pOu~MzlHW~IOIsV??d=2)|6-DY7v=B+4*c;J{Y)YFt`zx(>SnAd&p@sO@D}ZnG zuDQVY{;VKL9$aD3{V9hfl zr!vx3XiuCT;g3G@7|!KvB#_9%Ja&oz1#0c;&MqvHxNK2s=A%GY=6#6+ZB{b+o{=)u zP#GZ=e>eSQ-{_^@hWEL3jovD*)u^K`48-V1vIOm-HMDb-IoKHaHusuLxE(=?5?wPApEXwfeFIMNC6 zy${`odB=xKA%1^3To|+=1_;*S;}kc^fX$b+gGW7{}}8 zT+cgDYwgPb{5JsiUd~xGm(uD=q+MF-*n(}fsQX|y991X`EpWyFzxF2|!pX5g5qA+r zvGjb@a%b0y%QXvN6yByitXRXk2aXfLCIEPCY5FdJU(VIu>i4qohP$4=AE%2_MGQ#y zz#zbZJ@c5Krjm%2o4FKldFx%qwOXmEg+S5;DN@Sh*%PNk&+nz6jKY~nWduGN4F&8K zz?GtrRe@`8?T$)1`*3?S%MyJ{F~E$;ao65iyzT2>hAF1OeZVayjG2`8OL>D7jk!Fh zoTn~Do3z;$g3hM_e77;?v8}#J*UR>{a4fHvQ`Y0O*1ieA?@-Nkxkv7Mt4#Xavmjm< zhq|=ogQ3Q$d{Hv^tM7gk&n%BnBwZ<%Vfi!rC5AMZqOzc1C7$xt(orX2d9~_ry;;;o z0DNtegr?7kXo8)6>E)jH?)$f91eomf6pUB*i1n-_qSg3{^3Nj&_F-NPz&( z_lT83z-rzUQ=vsXT*a$jd<@_8s@tT{XQCdrnhY8M?m~T9-K%&-^E6vRqSTjy$<6OF z#{9+BT%GG{D>o&8TWi1DMc$jfTI(^oHTS1Q6XIVK7y<7OJbnW2`^=Y+x2NTyQp@~6 z9y$W5Ho~Qr*N75;&V!=gX3f1zT5bAZ8z0;eyVk8Z&>M6ceBd!@#Vg8JvKds zhCD}N42~YyC$i9>$R#o_CE5+NmO#FIWm?eZB`;)0)dMrKo?K|Af^t*?D0?m616I{UDZ2dy0>4dgWT0xXUn z*J3b9$5tWE6|>;y-yh#&jQQ;w^tQR+Y29=HZmnga@`_tK`TV3jdk(oZnyU37jAX`v z!Ba!vcmDh%SSk|fATPZXMZfL3;S}0TfDIYA9HozUx7`xiAGz?Yx=8E!Z{KV;{M9~R zS)=(0nX4gZWh-}$r!wei!RY<;H*pkVw7QJh z#Gsch3Tr|k8pAhe2s3~(-2)1Q+^~4pu>Dsn!6*gS$=VC+q zx7Pl10RM7BZ@$Ev^!DTp&w>mcM(yCu8#I??ZeU{3d;jwL9>W(-ub|bLkq0QE!yA22 z^2vlEZCLX(73B#j6fUWy@q+W(7EcXl)w&huu)B?`Gy=?H5aTEbl;~8cHf@PUP%oq< zUJ?Z;h6BuZyEwFmrR@eCuF8s3O60|;%K4KB7oMqAaFDcddT9wK7MC#Q1QEufMv*=g zY}1#HBtH{SGcI4k&xmZ5-=!uqXS3!+oeZN$Xd0@SOg=)A_odM12maQB*uy6vw}{1a z*r~4MJot3zIx}=+i&s2tGwA&9#+ZL~m9FfL?{=HVa>vi-f;+U<(lnk87`Ei4K{v&L z`Ve>kS7JoM#uXOBOFv@?q$Wh*l#D|4Ysn7|YpQ3AI($Y}vhyA_K9g&d4@ z-f;#(8wGIBdHWM>{(qN3*^+PLk| zAu+*<4GX@k=)f6$b46F?tQkm9S|iC!L@{1Cdk*JTR#7l<={nX^5w$d26__?Qa`&#Z zG!_8oR3aRF$pW&D7-TVmr`|l{y%>nb3f*Feqb-Z?`=$ppsp+LH-ucP_IG>Zq^}Tnh z@a>7cC$Gp)8DoC@iZ0T1^5L5Tz_-!{R)AVODO}Vd3DLSpflhQ$SYl)&JT)}<^@l%z zm1GV@+(Dj=T<08@ELw9b`@)&2ZpS6Gn&mpz$sM(Om=_%Zt<7qNQ_IcVQg2g`V2vV6_(z%e8o1$WJMubk0!iLysVe!)|we&Rk`&)Uh$ZbqIgGn0R_^v5~FMwcY_B4+1 z>mPg!Upza)ux!aPmfnGUD5Xr=J+RH=@{4KqSCoX0Ydo-($G*F*t2+WdPa>7C4#0(i za~8e&jaOfRkoSx9)?|r$7-FiO;Mm~<824AuYqh1FUN#cX-( z7uvXmp@2Kv;pGD0r6GXx{pvqX(nIe%rFiuCbaJ7sLm5!P;&PMXyHj8~AK|}$@P54f za7&D@f?}jx4cq>)1CX~Ha4Ho6oSj3RUp2;j|JA+X+q?Ij8_MlHk9D_ht^G}k{kL}4 zJ~^YNKw>N;_JAx^=FM#|Ho!-|d>ViJ=;x8PXJLz2+Mpp)OV$ekxX6NS35md+ABsLc z`tlFM#jTjO_H1{zwzVUm{_AxF&Y;x;rAFtqiwvW1-Y-hIXd`RN342K-bV`eA5=m^T zl>)`${0sp+WSGl>oWkPE&mKq0pQ$Jz#+N0ARHRs~+T=Y;IU*G>8a=Bsj`HKK;*$W* z(tjp9S;}cb@lpxWA@+r1e9xO-gWJTtFjD}RCdib>s@{;_80k}GwZpI9GRFL!9p2}T z?QX|MbEnSCT1!dMcWwRt8URl7pu(acFtca}0Q-2KDS`j`jt^oX>0vnsT47r{oK(FK z-9fpA;#FlN0i3{10M{tUL3X8bsiA!9&ue#!J23)s_cRI!l&Y9)*CyTReY0r^s%d-R z8bkQDc~Oj``wyU-#8T`->O9S9P(><)vQ&1|Nrd}8v9N?QD}5AkOMJiy{G)M-fn`Gx zcK&f5E1F83I6gf#fnQOnZ~_WVgp5WyQCkXqT4f)%O&R>dH@*rzHcghoB#vfC>AJ6? z7ciFyzw%Pqi4m85{Ejh((%~EKbwdL9_JOw#g{>rwnAp) zvUVG*;}kLbSB4SFtdQu0_pdz2jS5S--5U{j1>gxVtm;rG+K~eNEZ3lSMSKW%g@zuA8 z*Lld6Y@Aj6{VP9e@Z&lE9lqo@B#7T|0KPr6$(mb@NqTlEq0GzOkOXiBB~L8@zxnQu zV$_-vy=^IBwaYMxy#zUPe#)(v-KOP1am5Zk0@tqb^}crje1{+TZP=Yt*vXcC6{gzs zx;kE=yi0`AL7u%(wK_&xqxs0ZD3DNaO*vwbjq$nbf~rqNnOMjJw<94M(TkPyoIi3CnfwC1-oW zWo=$$h=NF}+en?f>tkQRXOEvjpXQvbPGjVR0@*l2D`=|$5Ov~}t&i?OA8b_wdlkwq zfN$TEe6_aRY{4dpLC1-ET17Z#a@aJhVi`Q6Una`E?=R4CZ~xgxQFeRs;7~uyl4nD1q*N}P-N(s= z`v|bSY%HJ##mV%t!Qu zFU7uCx)L8M)zW0N>jvEavx34M~2e=lh}u1Wk+jyQ~E2^r@DyzZ-S$Lqd&ALhh< zR(x+!vXOGt5ZR~Z-Q6!50Ke3f)UERraxm}zG-*C`xkKN4{|zHCydePm@{4q;JK{2L z0#%!c#e=8?7)cXiLuu0RpCA65v`H&M*JxO3P5~tJ=ipf(uVwGKMtnms?bC zc(pXrmryG5WRw4d_<*wu4>iC9aCR=2$cX^%WLcNGeXm&npYV)s_B_5h0Q^$dZL@!` zOVuwtj!M#TX%}EHQ~)Qf$G||EF*p#fkHM`K<(mdDHGnhvw@7HsVnbxql^a^(_HoN} zfWP;qd$AWliytd;jX0PD(pMc3 zP3lUxL{=$RJ4wWiP|Tx?QW8zD-JLQWXyh;p-WnMy|CiHvmjmP1bozeEnnCRQz#q1BHRDYdeWZUmmk?{ zd4w-KIs&!q;FIMTkH;E$OBH65YVkpa4>uaylR!kmms*v=!XHV>RAO(Wq*YN2QLyw-CU2a@VaD?R9whXZVzbV&8 z5N{>1>y=4h_vS|zULsFk(DmQvyQgn{{5E>qY>X4W@NrydKUcQh32JE~C$M(A7Z|@P z`kUl}uI#8be>E=WlLFL1D1|(E&W`oW*C?ej*(23Q<7=ib2jHwzAm2^OgcP`_##yTG zaz3Uk5$7Y^eP|xv^Wa_RX@@p1w~{BI>3=1~%*xO-IJL>~RTkaH<{P~SH#|BIU5`y6 zwtN&eJY1W6qiciqmz(LNv&mh$JFCfoE5uUB_37u9@&A16b67+SHlL+Lsw`A~WeDI7 zj5WehLmzJ#q`7@3l&zu~^}nFQ9Mu5?a8}nb+h4m1UMfxKB6``|T3GS^7MmXpzs$aL zN&l5X+IrD$J(+Iy46X#g>j%bzi~G$MBo*XB)Bpe=07*naREIZvK9}=32|g?Yz@6ws zi_lm&00KZqBKHnL6+qwzp`4#FmKlhgWBN*BaKLK8F6 zBG45?Xd=^h@%D>CpJvj#nIO(cT*|2%Ab;@-=gx3FxuG*B+Sqwt=v~ddUp`2$?RZ}q zfavVDX3AL$;#Usf8$0((w0V)YuU+r#%;R*aWThY9^`?3Lj;@5m@mQJ{^S)#hUir-P zJ{1+q1tM_9*di@t@-vlto4WD(-c*3kS+bwB5Ttz^Y?b)Fw|or_aBV7^*4Vq0_7wG= zd}EZ#4W==io^sKn+F}BwzQUgZ@cQeiQS#2*aT|MLF8MBN?Vnsu_xKBK@R9(2-WzI= z@(%^U`_bnI_|uPm68)%$k%^>WhYgBRhH?`}V%%R=E^a>BmYZMHQx3pYljwch)WDPA zOMX(ivxI23TVgm=vdOLR;uizXi%|jVKbV&s{E0XC+vf7YySC(N46nPyDtvl^--*MJnVHj%nA%g^i82dCU3JEz$g9U z*8xi5x~20rU@~+nuv%(raCb=rw-Y~()PiQ~BBKCHEDgT{7fSNystfV)y=ac48E zc&i&K_=FD+fB^n$?|&R$I@?EXVq^r>Si8)#ijFsn4fCn$)uS3?XM6%b_a z4eG}qf$EL*RZ>*XWw{$~Y1Ydq%juAPG)SqNmXHsScU>eVV_xmg(RF?y zCltBQJRFCjldK3zOxNd>6Hg<-StPm=xdhx(D#m`4C;XF>>{#4I|`K zS-Bz~-LhY0P2RIj0Kd$kx!kw^tTBcPw`=}&Wl!=Bou0M!M*;lwR_*SB0KO)ulU%ub zcxC0s<)$;P`uy1(zw@C_W631aO^1mg6DM*ra!?7&5Vj;LHb!wwh5akqhY< z@osi~5}6!ok@GHc*n(bhZt-YKgi_oSq8-zYs0K$5(h4Gz;G-b3Hd@{MWtV*jd8$|A zJYZV`;MFy203stk-zH9ZeFye#d;0epfQS&y3BlpVy0^o6K--)U+(A!F68=~`c8K4H zn|SI8sGd}sU^h9@Y}FmQx$RUd1~=KsSh&8c*k5wmI%Tf5?B#81plmyAnJ1sm(vhJ9LcJ+P46B=T`1+qX6#v z4Qi2t_AsPj)rgLRAN?Xe`pg1~?hMLe?6UYV49k#9Dp@rn&xnLn3Lk(h43LX45!iGcgBH3mL?m)YmC}|-e(U=x3F+!(t zm=rMa{HU<^m4@EVaqZbQe!pI1%rnneJX=6kedTA#z$)NtGo% zz;j(S8W!O287PpEQj7!SOvu{|-F$?%Jn%|9aI_~K?Pb3L;u0OXx@J~8Oim{C^s?h{ z^;Tod!AO_2eA~+ zpl<`j%v;hEA}6TQ(@pc`qGe^J8YckOGK4@Tk$MYHKmP(2mRFFHLkSthYxCkb2r$)d zVeiZo_RjPW5fq%?vqU+J#Mv7nprL+*s0rePHv!lNxX6!n6z;+Mav9{RqrKnUc>v~i z>Xy@0WLmwiPL2rxOQfzI*FMViZ>2uj7jXOSOiU`5n1C)6h5PMS=dy+-@sTJe5TUc& z*h-^~28|-)>ug{BdH78=y=yM#Uf;_1>V3<}U6X{Q_4virp*Byh*?r%zL5H-auXK`h zlN#S|Ad`SJm5^LK4Ys>?5#{puSV_$6X5B|IRq#3eQ zXv(vp8bjX#Syd+Pc;qnjSS}iMY~=vf+d2*4YmG5aZqMege5=u_;x-vMG72Zy z$QPHs;w#>apeAV)HA33hs|lRkS2N$(+(ON&)Zidv=Rlg@6{yMk>jUXm4KgRVzw>8L zmrQP75VP{i-q_Kv|E~I+>QN9X$Gv@G|D?jm?FKcVbBre^gN9;7C?S{QJ8$_W&zw<`*Q$(Xp7Icu{r-Rt;Y}R@?E0us=7ddoTgPj|E^Eq#K;xx zu;Vuw4x0KzAu_fqktm#ew*t7TPPFkO`X(xcXd3tnQjLGlK6$7JI`K zZ~x}6!9f6RVJFFlXRuKuHnz%xuhE59MVVKn9mLNWW41&wON4}&o2$|^vN?Q*`>#Uco0Pj@>zy9BfRklw;kAv1M@Rt6-w!qSch_{>Fp5Z zp>an4RpO2674?eny(BzO?!l1TxY(;14X;h+@pA+QzWkW@$XZike0ZroP{5d^K4cl8 zlbfTJn#WNm6SZly0(E_h>S}`kqDEnxddcSWv+MEW$~I{tSU}rTC(fH&6gF}ioG@Kv z?!Jrg!Y7iQGvMSg?hJr))KYfa$#QAxKtnYz!_(vUS4xkrUOzY&Li*d6rQ~Kf5%7D; z?^3y0NCh(GfzwHdZk&kQAg^aZ8YNVxl00M361%@;h?7X7aZ`-ZD*AZiEAPhF-#L#N zm*|JhU_(+qz6($z_bxN2+RVxVcl&hU7rUi?&=~Veo4V(=@k7@ffLm+t2k`N2Jm>RO z8D6O&qv5$W9UA}0ae2q?C4cy#&*9^z$LI$w#FPhey=d4njmyM=0Iar|)rPR%6NOu2 zCloF;S8agDpL#}{%F>s@`A|qxaa$lvQ%pqxZacIOvz-=_kZy#e!nq99>P?Mm9S~Jm zrj&}T9)zTI0aud~C%~)&p68GE`nQHJw-yNSQa^=5=cfUT(^SAC%~DC6rD-a@8wvn! zCBg?j;}V-dty6)gf?DlFj-Av+9LMsN(A-N5z9LL_d)4_>SFEPsCsrowCloL2_{B-% zydGlo%qw zX$$<~@4p|b$t=>S<>XV8VQJEfQ3T@<*)A(GOXW?oe56rn&gFNEw6s|4kMPtBXOTs1 z49Ja>g5g?oJVK|;v46UYV@LL@1+C45MaKnf9@ke z;o>ogG6P9`dcI$y(n*fj(;c$d<-8D3|Et{UD9bPyj<7oDV`X&}qcj!XTlPRObRh4y zDv zyj`U}YX}mHfg~@_;sc+13Img1Z1ra3!x_sGlF?+Yyf-!8xh8bvwk0r&nnit=lZc;< zaIRnA`E!dnGaSeR)S;J3mf^_U9A-NSrl;7MCj+EWt-lS}mP&8n3TGMtrJR8a_5{Km zfHy5%sdVA7DUHF%Q70fCo5=Rq(u-0%o)`IhzCQ>s9FDNGvVx_RWsLJ2!_mks(_KvJ zIUBF*mKI&LR@~FXCX6R^)_hZw<`LQE1ztikQ8(J_HpnN34OgNy{`JjT*q^9nPy`Z9!0zx1Ts~$Cvvgb3{sQ!)fI8 zwDwvM#^Wbo^Lmli5>;NkF1sjh`1XAoxM+(tmc-{K!pX%IJb&t((0w^Q=*7WMl_k7i z(s7QNUJF6KiX;1GaCm-N?%RZ|(h9<~uhdlixZtn^1?1H^DOe7X z8Tw>ngmD|xw0Hp5m84%@U3CEGVO>+*e6AS)x7NNLz^`xTY_)dV3gd2;uV!~fj;gJ8 zNp*4BVe;}99{wm!WMqlmq>ST@_GWW^ebUiX3krf{2&2lECItX%V1(wQZnO|qEnTkYdQX~$8nisYSOWdAT zm+Co+ihvQhfJ`J{E)Sb4#8~MMaAsiv3rmY?fJ8GS(Y1TFi8^2cyi@E{f0!hr{P8d% zXOgo9Y<;{ZxOTVgi3DbYt`YAJ={Ki5HIa+apMbTsBE{?^lw!`};NHEM?sO4|eog^^ z|D@F&uLW}toV@sX^1~q~$jLiJsiMY+o>vJw`F_2peDvsoN3Sz?6o%)~eR6bdo?;?* zu!iqvqFg3hS+VH4K@-GoVs}7${ zH05?Gpn{Wo8TcZ+p#)q&m~`-e&ct8|%7lL*;Visw;L9CDz^7-!;bk##KLxtF;a}4@j+j5da#= zOz-HROyrbmPMInRUX?9UCyca_wg=E?+n=+Rko=JZJ|L9v@ zkHc*xM)Zl(pWJQgd_Q@NB2>IOitx$nu?*mq#+ave6tC9V*)yR7mwiD?nKAj{8*{!5VVS^lDL?8``F^Kt~5U3(P6yz8qvFT)@Q%thl z1fw)bJ#;QT5vojZrKi;EbH#+7P8OZ+LD)0S?z_2;TP zR1RDJR;^|#0GELf0H2TvHu-xWMLR$i-dyOWS|uVN=%P$XWigy)VCWS%q`IW{qRwb> zoCvkzk5Bh)(Cv0HH`T-KhYyO@UJ{V9a8i0j=owLI2-(w^920OWu~`pvy^j1m zd8WIB>*?SpCy2=jC{7WX_@%V70p4)eEqLe^ zw~8jbQcNzfWLL*x8uuMwMbbHu0HH!oL<`E|avTP^`I&#!8DCf$NON1Z6=7~f< zwZIpH{x31D$$1t-s)#o47rk%|$_ReI(e65X<# z+Yu0F)M{8tUAQP(_rt$w+c!1e5}mX}+J1dsN7$OlU$X{3`NDGYv&^ni#v+)F%B zJbfY@uQLZ@l(~|e#Psx`f;_t&1BpEmXd|&^d zMsjq5XLEEAPggx6a`udv*Cq zaHJU)qrRsWfG<9?fRB9gaXfo=5hI}|tn|S=cK9G>dI_whXET))24!k76?Ku5ZV6q1 zke3NI6KtL%bRgl?Ha@E5xqkKwU%)WUkkLia0iQ&L)cdlS!g09#Qw8L#!V{@jj)0Oc zk;AE6uAQ{Rh-=Qt`8q91`n1SJBQ5V%rq(0l+qhy^s^q0 zvADE^rPUQlu5u+Lbdc9~REbBOoxOZeXp?|VqE+@r@Y=s;4{kkj1k=49@-%G#n&;V^ zcZ+{$E=8e`?pkBG1o!n)Oxf_^GD1o9F{s4^+hlEil=9jJ2p^f0+zl!&-Wq~5T)A9egZPp>o&E0p#3 zLIu*>#{`%|iXZvbSBoxO+N=2@xTk~RI%HS1)c&eP;MUro0Pt_F&IB^a z2TmqNyi|$wh{Z4n@gLs#2+kDbwteRj0^ujC(aS=g_xFVs1_KcMUIu>5DUvoSQ!lDyYjrQ^3(gQ$ONV5O^)1O2k_eUdII7H_w7eE z9-+*0v|CKdakTZ=xO(8keW?h!DcM|me>?VK)3t=>(IkF@jUAEB;>4?BBK1-Cxdk~F zF-PO|jF6@|qPQhRR+=zZj~ZS5aV4QeX=IkDR3X*G1SF&4qF~n@XQ%86g}A?5R%pC5 zemkoDhl$lXxyWP!Xfr1yO_dY0vp&A<{+Hl2$EML1d>1o)osenJMq2UOef=|I%uim8 z!@DW~ZmoS4fUCCbaKvo2kgQuY)e#p13HGpjAp?Hy;g4YnU6-UOVQ9`1hIrzI=VfVc zhC>{i?cs;s_Ga9B0AiKNJR6(6G6DLDC%%G@eezM^v56@M_s`>=yIzc!96cyN&KJ|# zpI!uh@%P??<10CeAjVWX!i#P_BD^Eg5u%b)08O#TUpJx=kAV&k2~zAj-s-ePzDWM^ zOHV(AL7K{gWWrV@L-U0+0=ABS^a(wBxDYB^aV*j4{M;O-x;?a8aaABwo1SP=Q2>ML z8RrWwxdc}rVC!kF5tJ0#P(urS6eO!g8RAXC35>3Si4@L+tqw+ME>sC=i!^7$ z;~eAR5IH9-S6R&ca=WcIt&h79^M_oUH;B@ZtsByj+#i&?idIPGbWWU!B>7qVMH-HO zLq1ZPF76;0_Hk#=;QPMmUhxa3R$lHS=POj?jPSL|%9;h|)xgd5_IaN%=Fy!#n5zZg z?*{PDPM>VOKLu(veN{lvhpOg0Qvu)rAA9;7-tmbqVKwN=5|M=s1kf}6KAt*r8W=9& zfkV^yiMM~FEdMy51nn=Lu=thV{X_iWyZ#*Lw88C#w2dut#IZ%0j`3ATkKy~jc|z1NETTzAG#?72SVy$wRuhQC&X~ZKWfGC@o1eq{^fY>{7Gm1hieXkD z$xeASmgqj><`YZ$gvY7!z-9zqIQP2AN;(04cPH}w%2x{)P+c-DzR@dGN@S)HzZT3W z{CnQnH^*QYNZ=-D3z>`@+xw`JeTWET|EoBB>5cEuS8o(&2@X&J2i#p7%SG z_Y~7|F~Ir)RvfcQiS&2nJ*bLrTNt!xyF6aOw|~O}xc6Xywo?xAz@=`@H)7)NFH)(y z*-_ns&%MVO^Nm}uoy*$9jsv*0maU5Z(`6mymcLnVXW!*oEaV#i&KsY;-Bh3a&U-(F zFDw^W1-b8t;R?G^HPR-z&yLDCUg2r(0uxOFbTzy7B`jMu*8RynQ{0Dkh9--jp8 zW4Uu%)B@zD z2}+ET8D+A9k&!lO1m;kg@MCl;Tqz@1SM3+LUW#jJ8&89f5B2H<;lHKB4ks|30OWI` zXi+`5vH(tQD9dFZY1II(btIa!9ha$q5+@-IF>3%9dW1>{*@kXM=L6-X$?2AHjK!5z z3|9LX4F_0VUO|?QML9ul8gsjtwD+E#dY2{Hl4Z#(@Xx4MnV!23?zgELVyrRzy{+42+iHt2KOQtS&}VTy}mZ}*8f|3 zpEEO07Pj?NEM@qFeh8T48`Bj*JF21+GN?mB21)1wK^h~D8UnRc5aaLO|1Ml{_A&`* zTXWz8U;G)irOdW-EIMKyicTzrA4+_VZY=47APjy?`kWLb9S0k?Z^JWd*Am1P3ZYCY z$&?*&0Gc#@yuc%b5Cp@P32XIIOzEjTQXHhQX7JrHNIN+-K(p{FlioryCc|bhXIH79 zszx_k=!ODmcoIA;rLgmWHSjVk7o|rFgP7eD1F~pdr-=k-{vpn)k^l;&YKN&}!SWtH zZ|*dBFUU+GwjD*1rSrO*jRvMno-9R9V!jp<;{DP9{_+NpcA>FNxsw%e)SR$|PzmP7 zkw=0#?>^h({ZMw01NE8+Q8~>9COg0hhtI+BhtI;1hfT%w@%juohV2zMQ((=O7Vdv) z6&`qc9o7#u(eO%0*aP9_m^E!O#+QpI`Hm=SatGrRnn5O%SaS5UnCu{>$npV|{7~u+ zjMu$RgsUz*5wi+Fm@?!cCvLnt)|@wuyi2S<(9!9A1#um9j*;r_Lo z&SJd#8 z8-IqXQ^f2!b1=QPfUH$FZsPXQ+2Gv?;xbVMJ0zZ&2z0Vy)hbkLb=d**^z>l-`0<#~ z-!J$!vnQ28GeIMco8+XR(w-jb&j`#!XjowjIv)W{8e`>UA&PZP>5tRP23H5iPY- zcsKr30$~YOEP&vCK26yxO+=U=j0-*N|YiML|S5!pyI?h zaqc8sv}`U);+<(O%viDRh918+4`F|N_S=r*9IzNS_EEHlm!9YOWdLs6!;kHkx3}>? zb96<*JNz}G6N3PL_{28cyKlJ5HV<8V(}>{_KnYg>T(* zAL?NVnZs<`Mbc_X`obcOWNwt{VMa$%EvQsSzHt?XvZYF{N#iS#K!kgw~msb8H6{Wzy584eFGSL~l z4foh~BHALRWg>8PiMk$xw(H2^W4kN6scY?q6c+o)R^YUaA_;!wViA44edw)}P!3o$ zROrUy*j5Ki0;$m(AMFjNLsg*wlZFX*T`j}tEjm=Iqt0t~DMLWMG5_QO7w|m{VxoP* zItE!N640of%|7h9q6oWTe>dAM@zkn`zhmSz8s*6X|S{bf;jw zMPuUlKK)u947Xye-aLR-qmG`ailwtB;Sb()wlvY$W2_$r)^FK~6|0`Z>NU?{bFT}!r(XK+^0FQ5taqV}1giTR^;VeY|_=%V`z84dUp6pih zEEcgW(IyuRoD!Ay##>=od!@>+HDyD{Ez>8Y5;g@n(>s1sTa`>t}oV}1<#?}L{+ zj`QF9@9>=?@6AZsqw~x2{80c)_vl0W>&>I~{tBf?NH9Mq&PrCumv3KzX9pW_84%!M z(?}JYH*Um4C&fQ}=n70XnaXV|HsP%w{WA=D{YGY%p;xg|7K*&wm#w7ZXGnyi#jH*# zZj!%8%B9WS96?&e>|%@`e)FF((FJZ>z600(_#V`Q5*E#wg#K~}hmpxHJ{Ah?{6vB+ zwYEvUV!&ck3o{?VAw}ZVbiYXNi=o?bF%Tw-X5xf87-SiUOU05%x3Uq30ld|yY1bsR zGI%P+q(LD{Wk9fy#m`d_uwOXhJwiF-&qzaK)+OQCGy*X|NSRHERya z1xLDJxqIOClW`IhQEj%cZu3?QH5w@A2`*TA1m6Cd#gc6gw}2ad{4?C}zdy&CtwV_2 z5+Y{Q+&PlhPCBcrHm)GMya51z`(JnBp-olPG9Q!2jl=B8 z;{_I>L=|;axLdNkaVOPX0X41~&6+IobfPNc2`)MHSe!g95Z6t67r79V!E(TY*4X3E za>sEFNUS>`_u}Q{eDCrUx|0@@$c>&fTCrbW2ma;f_hQJcAWm|`K>-i1Uk|5M!*4A< z3|GH;Df&&){-!_vEN*%HS=2b(M5U0yn{M00_(&=A;Yul8<2D-^bgpYQ7qGjYpOUR) z3qe-J``-N9_|O&SV~Du=wLijk_?Um#B#iGVAYh@-$b4F*y!NibXnN>^wCi5OWLeBy zV@^iZsumkK*K}DXEx1{N-Y~%AzFtfo-!Iav6yYLm&+`;!;b)pjhHV2w7_K+C%@BqQ zvpt~;a-ql)^p%U4Gi?eyD$S9_!6iZpV55hg4RmskM1N&8&%NEP$lqHMi-~@19hP>Z zh=XR5N*nlKy@6Kdz$p~vXEmeqV!J6t1k2V?g$hR%Jp)X1d5el%fMG^Z7Ff>DRXZ^* zYDvsxg1Z#zuoyiS>0Xs;p5VZZR$X>REqaL=GHQyX zk%q}diHnUuT6zt(b)DxE#Z7pjFK`_(=L7*(ZrCdF4wbBmE6+O(R~$P-_)K@K+=5Sj z=JVJ*7@?WSRmgFhB74jtISm@RBycHRkgyHj!8k9&C$4@QUVGNjvJf=MQ26O`+`9Z( z!N$k+^9rCg%J9{a1Kw%K#=$EMv}$DG12DWfE=ZWVWcKlb92( z`yx9Tj07s1wc5fhsb)fLBtxZvqVHhpgmIWMj@#cN+%!f)h6bC60?YbPO>GvmNRQk) zFpOF&mW-EhkW5N8YWOZ@O__w=Vj!#=m{xTbVPA;M+ub6*t0ss9lnwzy`Q*EF916zm z`Le)_v?6R77)FEMkfec9oJ=rs-GwOb-@(I0Ak6%+L)GriRNsUDc=ph1(8tSHSkJ`2EZj+ldt4GnFmOTWP~e9~5o3TqjyVf^h!-h#JgaI|)@Y5M>MMrr~Fa2rpVRI+hYv!m_5)aIG%y&FAZZ4lS+q6`-CIyJiF z%U$^;xScaA9d358K`b;bX=aA;ns_fi#Xb!)+6OQtG?Tg~!$ zZ5CRRc*^l=c%vQ}MH#btWh~L2EXlZ_CU6U7Ni0^beg?=QESl1TzxmyB#qH+S729z2 zAN>VtUIopRh9Uu?Rzo2U>c&fcVZ*0VS7p3Xk&=)KYYME3G!yiqg}?jwyK(WUN6WD{ zM8F5W`ctfLWTLpaWd3}3aYHDE;uC8CCKVOXIicE+WF-NGXb7jx8;=W)TPTSVL%UqA zKz0XJGu1Pe~9(ovos>r`2_C1HW_ABUoKc zQFV*bHos-ZAU5q7#xXO-WMSocN->nu>Q|;NzmIG!jC@naU65>9DMcO0bGCkuTd#61D_@>_1w}5 z7HlR20}&^(ZP~CkSyt>y0*8s3{G>%FB%~0R%ro?aJ{HcMBUx3(iJT=UQvZU?^;EaH z^rxgA3u#~!=7Jxhl>zHEZIO&u_`y=}bj4w4*0d=Sz$;+@B$2dHtMNs5A>xIHM|T!3 zU6^7CryTG0Q4EGJA&0W2Qtk~AylT6 z@Fb2+96k)*3A1==#s@4us$qq~F)IHndLm+$to_;!OKg&UPH{FB8-HzLWB?-@h9>5h5;Bka{lGt>1*ffjZ7zdN@9I;gP~VVW5BeCq9o`p5BBZ z!XzavR!XKq4Is(FSxD2Yqx}*rL-m*SpPbPA7tMTg1YU~D$Ts}&Z~hcZkDi5VZ`*|b zz5g+>SUYUy3XeQO3OGPr_YsJR5;6DKGj${noVyj8Ms(bN#1%@m>MVAhOj=pn;^nIz3E z=y)R?i6Cv#wgu+$kUdhF+mj7B$1t+Ky*dj!MU+0 z{;^>v^Gmq@$!8IyEnIs1T)gePC6avn!++d}&;HLH7;!2>Efh5ZB#5b+X&6Ml+#6c0 z5w~XWCgi~)wL&yhiu8(Qq{Px3pyFmYXVDyd=Tq;MJGhqc-)FDG&R`OPLIuanm;^s* zsxgV1Ar;3SX4X8eX5X@dOcRv+99eTGUVq-HIBsGAMcH;7)UEWtDMs(t4$b`*!1Fx6 zl8Nm8T6xBPTpPd{u#? z1aNZ2ulmI2aO=v=sQM*jts1;?32DrLDmj&L&gocLDV$;i`7MrMikZTgW;dLZpszWE z8~*B#v1I8ieBj&n;jyiQnA~5HjMfn$CL2;r0GEj{s=-<*cLpcd^+T2m2{eMUN=tNt zg6ks8GAx=s3;jiANxDrIxm=nmQ~HzoFKH&lOXB6y5JbF}{B3wx{oFbYmhv@*W|$@z z-`9f)y}jZC$_5^KSxPqf0xuifcMaSfiB=7<%9^nYnDU8b@nXXeDQd2VnBJvch!v~W z$ob`L@^O7}8fqo6PzYrMCc6T|qA|Ob4!fh1jZ5as;KM?)Q^1PV&tmJ)uhp(NTi_Xc*u9n-AjD#q&i{ z;v2U;g>T-w60u*#$@6BR*Hbk{Qf*T&mc)ideuaOu>z8dm)V$B~2#aU*<9AP9h#pxq zsmv+2<4}A3j^jAr-5)2tKLa=|(vI05C%t#a)Bvubjsd*mKFQP9lVS-6{ggd@;EhbO%am{rP;Qn=+arpE}nABSlEoKT$$+6m-{jL^k ziDRA2d)ND=M#T!haN>p(C_;|;Qzv6G)djhtaVNp+F>r_ErBY!tg*T5G#iX^S=?$o9sW}=m1QR-M^ zTd*+3#fD`)ewSd{f{eKenK&M*af;_QZI$31#l)9Gp|dsO2rcd~q|e_3a28@E+vRaP zMi{y@=sin_rUykl{?xM=s5a1&44AssHN5^+XJgsS=_n*BOG`FMt=SZh&H{7gI6)SK zh^4!fOMxE2@=e=zV5r_iMgwT>8Zrm1m_`*vID`@eyC)89bm1j{ho-hb zh=XuZh)r7uv3ctd=Jo~n=ifh9@Z|rz<4Jt-+ApC-iD0_zFnH6%fsZ^anhvN84z1FJ z9mT}L6`Wnht!H@UErpvBkLN);tb@M1g-cF89M^vAYDsdQ*be;uS8qVvGXV=G^kZ_l zq;e261>r&&MdBy(t%KZ|+ z^F03p0AJc4C%pH^R1946HtMNqq226>C4hhHSI^?{EknqB9}Q`=DPq&s9oV#W02iFF z1Rp+cu53dIp?u-`pW$z=`w40uhpWzV(w$_i$>cJwI0CB}43UFZAR8@WF(Fr)7N;+1 zX~1EXB7XI?PYI3i%FkYpdZ`CXW=_HQ(34^y;TZ-PexK-5a04vZsL14-?WhJKD;nDk z<4AGLn%%I)IZZH=N_^9&!6#!PXMW!0yD5v1GIT@-UAF2zb`A|=#}HlWQz>HFx~OWN zWFiig#@ft7Z50VD*70XI57Ww?b_a4v>Wx7HuPjR<6oWuy0D4MAl*0fagSjwplBr*aMe|XK>ca5gQzfKCESj1s>?)Mq2ZOR@3<(yl3%$Z#jx039>W3Ol ztXj7L+lL!)izO+@lFIJU)=xgKpW|m#D_isd;W^A~9W)W(@h4Zx`!70i3Ep?sOnKKe zU;1x+_vT+B_cF=Ug-h>}^UX|JuoR7yqSviwDkWFy(i4v-WSP>;cVtP z3dsnrJZ&+Kn?4R9`TJI*VebRMfj+`}9LL$`F>!wdaKc}t4<3Xs#Y{!!(zI2xlguI# zRR{R|Pandjm^8TrL7~jCi49wKVr#V_Ma<8=;dtSIGl1W{W-DI%(NAI6;gr?wrz_Hz z%xGe`VL>oVW;pyFk>3&=?QYaA#I_Y#(4WB7vYm{y#RMVu>+s^$?ZV7 zf)nRV!{S-fFrHaBvsw9`0QFXk`yX45q`(~m18gA8CV{Ivj8?OOLMhZDtMF+}CTv9w znT0z!`T`%lg#fdrOqNANRqXU$2|w2eP!V5cRyka)quOYQZaM>qE*_>Y+5k3fO%=;e z@6vG@>)=o&J1$_l6Dj&0dP_xBPAnCLsz#b47nQ+k4LhoJ)Zq3Vez?dxDX>l#rE;T8=2mu;#gS*fBJMCXeT^z?R~e`Ll4@Str784x{L* zQG}ZC>SC((3f_O7w^B`o^2y^f3$?rqDN?fCJ(tWIK@nRAt9W+9Mhw*&is3T@Clo|J zHH)$d7dUqI(r_UX9G*CN-DLoO8ihQ=)vvz@7tPaz&NWo#9Z5U61nhGf?`1GY2SlKHd7X%lr`~{PyabyvuK*kk*mITGuGA; z^aUY~m^DiRxcEP@S3;5mrIv{JRqlvR5W6!|*FynK%&Vk$>-i_5muQWyT!-T8ImdAh z+t(+)&u>MZ=N|^}cl-K8_v!Hr9f>q4(-)~pM-FUHfY01`2WsVhRjw0yR)CQx#beK{ z!}K7Brl;=wHgn0NR*Tzvdul#+%yj+!33Zh)a`6XCdi z-2LcsG+kf#**pVj;}_m8uak5?I{f(XX_`#LLHZ^%17yLHF5zU0ILsD9Upgoeo_~;NgZMg;F?wPKBul`%< zyh2&-?Z(YpC6LqRFXD5R&PE^zdu73n$OQ2n6rEg>gN@Y&Hg4V|U6&tt(`7hoy6&J3 zzwEsj^h$6F%IDA0P%8Lha+W86M~IRCGq|*ckGg`VKuk;o81RMP$FUuYL%p9w_~=!? zi)$`9O_*9Ax$Yi3v|%U47t1(e&K&rprV4LTshFCD6MEDDE}1`}88`@?7`+(5TQ5Ex zhj~EBuyFTjJUDO%`>5kM`!qK0(*T|mgafF=HRZtFlRf+<%Ozz1rXz?ladpDx!0Meb z{`IzBqgv=y)xVtE=}=@{f4y=A`mzST`1aS~6_X%*SK{E`zU>iw;`9H4;bIRWt_sX1 zC};`e*JIZomXCrUvCBe;oq(o3fk{n zei5b>S_o2pqrw?%2;sKVVKLDQv9%fDzQ>RhoBe zH?7?S>d%P}!wCQYAOJ~3K~#0QQz0(3=p^TwtdanaKC=cpYV0rt;+*Jzs6M6)o(!ms zI{Z=zJCYnLSFS)mVtnH5Z@{UOl|DHCviG9aGXYV`@X7~Q5bbV(&5{-zTJ{M9sDfyg z-D7#`mK7`K*XHz-(UeMXE&#DWPQT_U-gU)=_|rGPMrgSozVUwCzjg;IUVue&=OV~s zd9QY(X2@h=$lnc~WR?`Dw_u^X!;)M?Kaxa#z zUW+H6c@CA{@hBE5vMA9_hF+UN(MO|RN9d9-tTaP~22`ji3{)kNcrqumFb){NO!p?S zQZZjJ+T2o*vpfBy~z65V}P7+L5xpob<4D4tdNQ)Up8l#dm@z%?K3-kMX z5j5-Kh00w^lW>^XW@rn(-T{L|DVJMrk7oInDI~vdlZ$lM!Ucux{^W%7y2v|;`~X`9 zN3i1Ab?}NkB5_O(epoKbv#x}p@Z5LADb}oBiQcq{uYCNCqTR#8&${^CsP|4nnvpWd z_IzeC6fDyMFr^HX?oOH{FTnOM5c;u=RBajd4*n>9mKjP;ifex7QhefyGldU+^>^;Z z@@;iY2uqkhV;Xo@Wqe5h=T{R0(n7y{oygx(wjlsmNX=T9-(SF0=PVIUxLw}HFmw)v zkNlD2IDfsbPGp}2aFczn2QYbGo!ovo&TcdCL<*W*7JvG{I^4N-JsLq-M6B|R5CSXu z9=0{ASij~O%m_Vv=KYro$S-Z}zK^Xf;0+)AQ#`U^JDOoHl8jiMX157jl4a6!0&vfp zBccAW&n-BezFX+`fmh6!h=2UdAEUPj{Nm9~__v?jgU~PFT^F5&Nd=uq)YIVik&(eh z6mf7DTfq{lQHDG$S&Uc`uuL%R(q5^!C}@90t^1wm8G zQo3G;S1wH~LZQ>4qgkYlI^9pKduVn4TlLV#`qGfxfog11NaqYp5HcKcHI7hYXgc!< z=1o%pidadlQ=6`|_Nh%k!eGgB4A!bxvwj^0sw0Afhs7eIW>bs?D#-A*%Pzvqo+84i zj-spuU4=+lKa`g)_sO=;Gh}o9G%%V3cAJsgMl0i}!(UL8ii?5B+Ok$66g*F!cQbWy z*L@EmB9FV$gDQFLqBWBVJhyG6hK=i@;N3l7G_g;QFrUkn5J#?BepEuIC1DLt5 zvhaNwz&}bcvawFg1NJ!^z@=V;K&37!USXx2&PIyf+UCI z7m+$4)@<5_AK!dC<{fpkz%|l1VX$_ZCTN&3#Yw9JA}kNpWiA&&Xd?dXeg<%M zl+xJ3m^g}yIx{|YmU7P_+TsrIi9f5I=HS}Va? zu9*QfpvoeP>}0WML6_s*SnJ4c#-o|E6#qL?2*P?X-N%VTX@~@VI)aa1^*i|B#ivUV z^S3|uW9)P)m^Z!`)BAhG?^3zz-S%(_!SHx2ijyuW;#Z!BAj?o}4dIH@kH#xz^t4;+ zU)pFnDBtxl$8kQhFV1XV2Jj64X6%cT+P}vzCW-0FlIN~n!ras^JU!r&{G)UI4ze^ zBb37Tl={$WG-YCQ-ZOJ!d+}Q?eHGqyJt;NL*2&oT}P?OwvRSL#$ zIqF(yBWr}*YPNqDXscy--&}}dxeqD;C0&6=Q%2c=9be0~7?p|9olw0mHovCuX9Azq z>gevDRF)Av94QE;fm_)VRA1y`M`K;3;;}f(7c=>h7B$6d;vp(LZ9*7ib`V+-c8ZT4 zC&OiD9*;#cr=r()kTz@5ams~GOf-bqWS|jYo@mA(ow9P@^!$bTEd^#3htkDUrz00Z zYsSE0EIUSRi?e@gS()2ON(qmU@^0aMdu~E&`g;=@rzUbQs;Gc6~g(c@XuH0nBi#_{dv-8%xHy;$lMW zVrDe#(7fxZ0etI!euSUiaVJ0>Z9ha*qizIcS0RdjSG?vtyyVzXOq2QoZkEG&X5bLQ}`$q#8Q64Gu;kbxf5sG0^vKPMN=}p`5y<6|V zoJB{Y+|w(QQ)rCLK&hc2%|J@(7M8D20Ie^jQuD~Q7Hx1AI*rtTOgRgmm>}M!z_p(a?TWP;i<&zI z2eE0}HVo88q&^|A0?(argySI0b1~XIdGP|AfBa&ENmHOE&=!oLlCVomil}-(>K?`1 z2P4I5RdA_kBUW+}yiGCF)Eva>PP$cA=&HqA6SDA{?)Y@NqnSXNg+OBW-$?V)8#5d z!`3ngWvKp+7NN-;u?2nyzES>4-3&qAKqcFWn{W7cOaky#Kk^*v2yoJovr%A& zCGmWb1W?dM3h^=z4SkU{2=eFIeaZzQ$x+HluN}g>Uw@8Zv}`=Hb%n8yru`pnUf>(v z=Qz$6_x23-$+hQs{uH6Ly*-%&_IaHdrkbhTR#LN;?*P7k`-2z>TqNXe3!_AvD^$Zf zm7mvgA8Vgmhpah*34Vt6zTsk=IIVyQ%nU?|liN~A0cWrUtX{K58ZeLtvL&24xgRqo zGUV%f2#S6GwiUST{zqh@9>3@aoOslHObBCSO>%#W$fU`^6nSL0r$S5P1ou+S5;K0Q zq{BXHZV}gh=SEbs07oBnG)f_@tSDAQzAcNBO5IWeToy)EgIh9gQXVBxYwLR$kgli& zLv3Hzm;7zgYx^@Pf{l{1?S87ixdU_5yDTfCEe$aG7_yBQYM$`z6e1F59)(E6xT2fY zVGD@X!Jh5)Y)N-q>>R0L{gzD_u2uC?qyb2=aA}ukm`r1ovldQSI0qM;c9N(;lJhM5 zZP7t9_r+Mw$xSgzf>Ioodl(=zwTn)r(q7k#!AYHIsvV+)&oac6eu(O5#8puptVIQ^ z-8_VKI|fnDJfvX-Ppw^#p*X?(iifXWb(VAx)2!t5E8mB$v5%%#)PkYUf~C?Q6=5c+ zQ0pZUZmoKv*zIv~A#_)egrZU)V6JE1$yV#i$Z|A8|5mBg}+#!>)NXdr`7oGYFoHWIg8ic3}7(I86S&>ff(%7-P z7JHZXNwC{@L28BLIE(i7aC?1Cd7i(S&5L_`A}`D5MOeXR%`P6=4E*r!2T=_?X&+{0 z!O0?so$y^#Y5E|}+=w!4+_Dv|kpYzBD$ZHD5bye}6J>%Z`rQd~ZDN6us^vK2;O5Wo zetHM4zv)hF8L3Oh-nplpj1vx@g$Y59tUfH3XXFD{>n%7e5|MK)x)l^a;?~@S%K$DJ zjcveiQF99T$s?=q>*XuaTONm_799!CjgZAH*_H|ez_3Up6Ez-@f+3rKOS6o))4O6g z%;4UcAIg&Go*Xuyn|6=R??z3k-9PEyBq6)2@q=(pge9SY+rlIa-omdJT-OvM1&+{@ zWM-`RG7%`#uD){zhMP^1UFCh{;>s+S@JgfELRbtDIvKp?2u@ru2N#~a45chaD9=E% zQCl~V^Jihy1alUIxr5>2$NMK@R8mtgW)))`@Z2wjZir?pLd0UI&*q}KjFDDc#85rM z!z)&!n)!&r9&8w?i zst*b@LMVz*iZpep1TlLCSp1EMm$L{Ob8Iqi@KA||@%_L5IF6Y&13!FX6TWlPuP~4n zF?ISZ%;+mikAamku}!X{Z$)Reuz<^e+Z*4lnjjGEB2Mgh71UjsZA%f|8r#)K?sZSDkt|=2o<8%vQ^lZ>~7`vxC4r z%h%$r$5&zN;1Eh~g2Shc$7|0y1(V7J39u|WW^pXEK4yEgMI$sqTP${Ms)mN4or%n* za%!bjo!jqXFIH@?;y-`*bJSuNlc!C^{KKZ9Kmv12f|$vM+XXJ7$a)M?SN>x z)B61iJ6PC+OdT>y*u2B;(dRa7Mk7fOk-o+NVa2QLN{v7pn9xEAO)Q%=5wAV>Occ{x zbZBVMp!CW%IZ!fH>+4CQXa*ix^h91(ZjAY}ccWcZ#HEi>*fcpg+Zpcz7q%jrv5Vm- z!Glk&!lr5q^vx>_XABK0mdWmS145q+YzxzIHPDqjU0l#4MZx~*Qhr0+w zbSy>cr;;oX-xr*miy)~_tRrx@7Wx9uakqH-;`#XYUtTRc(2srjRy;e@f)hG8YQa2& zX@nx(=o4GO++FC_uxtHNxocr(t-?wPrWJF%=YnM@OGZwX7#C|DyP80BD(u|>+>CDX zg?k4*YRU0SgS^z>gl@jQgJ1fR-N!KHg~~ zwpM6HM$}An5p(iF)Kg&Nwwu|FOVN7$i7LGY$E|U5PN(DB~WN0=USi61`5|@oP zMKru3X3d^NHSFx{=}@nQzJ7`G~lxAuoIA+X#N*l!)ur` zp@g?x`f8L?b{J|+(s9|r*s0J8?;N>wfimMR7Fnp1^uLo8%4M0G@M4I`i%bLtEm4P* z$D?{B1U!(3noT<%HV;>E?~|*s!}0Otz%T{|1~4J2P+HhOhl~i zT#2W5RHZVn3T#@^u{z8w(g@^|l4?iRM}%gxiDHS4CP1~7VaMPQ>h&tpBto7vl%Wtu z(o|icn13t6+?mrccg8d_ z%?!s<4drerNMQ?bLct>rZ?(dWir{a4LfwE;_q+5O6e7vmhQ{)56TlVn5j@1aPqW(g z;zQkSK0A>s$T2uFj7?j&VyId*s){PzN`*oOK#D;LdqnumKC&bb8Xa9@`uq&j3JKnF z*@e=YP7U^gWS|rxv;1z&@wgvhfGJQ^i{=dysM~EiT^Fh6Dm#R|3gX&mqZlwb`z~@y z7?Zu>E7zMWsudfz;Nf+fvDpjp^tz2eBgQe)Cg88$a=K*UJj=iS@^|oWKe-trUImFm z2TE$iaPgzTiDt9nze*aTuu>FGaY$xwk{h0bEK9#Rh`;;jd+@5$j>htBz!$#u1Jtt; z`o@pP^r`(Q_!$E37D#7pH(2cwzzqgx3%N87A*^LtJp6SzYv9$dI1H!FpNgWeW^_Ga zG9|lXVfR?)E7Qc)#xt!y)@W#DUqzEK9_M<;ao#Y-&yHOdCeQN)0G=M}7ats-(-ss? zH3sm1`su^i+;WgeQOrJM(|IVoSXJjEPnPgTz#d2r9u7*1@q0xh%C9uBs6K)t=gmb= zArQ^&zH$YVdL2-_Z9<7nKn*1IA@o%$g1ORofLvnYxe_3SZl=!NF;(-JZBbYW9vbxs zag)NPITC6ZNm*YDPwcGZLeOd@*qH#Izu|`%hL0kJxtcA^o-zrOCydAV{(i}#>A0?L z_1X_V3U_X&Np`JQlLsR#Xy}7x3u`h=u>`qWheL^=4fB(xpqbrQ<`w3)j_ zAKC-PKqC_5xdUL(Rxtz?Fd3jXZrOt2Y8AC+L-nn>@R8pw3XH_f`6E)-RELJw>$1K; zkpVv6RtyAMC-)+Jz@Qx_} zYyJF1Jmp?+a+pO!ARbL7q#233H3Lnt!0DCB7)~Ah@`)8#Rcqnd?IYN@WmxpeuQ=&Q zyz#6B?XJd;e&HLq;kI96BH3bMQ4B9)NbE(JvGQq4rPiUFMMy_62{#2u;>rufJo zz7v<7dL*750Y3HB8&S(k(xkTF@Odbg)UMAb48u-WaUgnrLEDIH$^y>&O3OQaHcGAJ zIrKO&4)1sI#*# z=s~~o_+!x@2Eq~NWM?5%3V}(AQo%*FwhhH1w}=dyRDuhH5uk$gTIrYSx@d0@*JWrX zy^BhRDWYbKMjWHXodGFV8JQ-zaKock3&o&-reDOD|MwSIxqT3=+(+n#aH5vD%}<>& z89kM<8v9D7WrMgvOFGCqBtgZQjr^&>LUaplhJXnmZM?e+_qIQijMWM`$$DXfxXoFK zX&O~So5yw`4{`>S6(t>$_aRL&T&rQn-~e_G4T^x31Z>NkkPMDct-;mBuz7?Nvl3_ow zb_h*2$D~7e&+9M5g@+YH_Lkx98$Y@OfB%geQTK@Y6a6Q2V%!sq$dpwNWPlIT1U+$# zQj$CRlM`^vqc)f6D(eH?oP;7)yG`}xOA3Eo0C#!52Dv+9LM?CSk7n6 zSCQvA8xKkKJcM7`tifPSYSpK{dk3QO1Y;cjG!@uSD$=5rUX7p42r@$09sirL4YGo?6+70l7L9J?i?W@76x#ajXHF~A$^Zq zd)Vye0Js~%rsNMVws&(GvMLP+wuL|?n2YAAaerg{-ibw zRr{t-oq|ad#*3*j4H48R!dQ5jB4Ss~(LC!>t(f{VX-hYyA{&%-6_A$=)K(j$6XZLA z&CmtH(hux`a{YJ&P2t&bj2_?uG%X#t{ z+OnCU;n@YnR-VTkz?CW5&Q3*EmU0R#Y%{x6<_&-5`UNx`56=w_;jYJ4W7wUDhgUs^ z*oje2hVYKFmf>}$ED#ui_it^D;%V36*1La+dYYigT@Ksy^H8+FrMg1M2?{6V2+)R1IkF2ZXOE>%!+Y=uxC&ZkYvoNh3in9(a33=a~W>XEZ+Z~vrLx&CEqD07f z6$G+aF^M6RB0IUbfkHftw_SV=j;a8Gaj94P5e?aF%xed5scGmqJctAMcE@qXBtbH! z0G{Xh+W>t15RTktk?&}HJUtNOYqvdss#g)}padPmQ?>mJ+*S%7oV06h^B8o!5*m?W zkIXgvcnD`Nor~#Z594VFoMwm;GDc{NrNLF?S49(A1-X@D&Y;Brs*4Y@k&Vg$5|e%T4;!%`UM4ysh$QeI^ZEQ6`}LtTS>H!ZKir z&>3C9s|lkp5P8!0$O>Iw`*VXyb9hPOeWiEW6c)Cgp9QricU!_g}aJC0v{PWvG3v6%U9#+Z3zal5Gyur zK$=DGTe$wya*_;N)wL2d_Gy*uU_U(@2d}9xWff-GE`U%A*?*wqh7(RN?eT0iM zhuIU`oA{4AA3-hXmCRM(U>QA~A;iGQAWkft7-)%*N5o)R5)71h_VGu~#^R|Z^g8qd z=VT(L9;zWQ&A0?^QTGvw1BqH*JAkW7n9<4@y<_dSlfTM&5w1~cK;8vn~epnBTVr%b`L$&-Y#MX@Z) zTW;H%SqQ|EFl;n#|E>74<(OL-K}Va4t*}wXa?fP}kam4tAP99Z;4uTMH<}n68WQ$M zgUl20d-M@Y5NIdz_W{A`;qQ}iKZ`yPe+@i=%IDSi%22|r* zia0&#wAx(&|IGnH@3kg4EgUta55ITXLR3uJZO@bECiZ$Z9~a$$?hIV--a!VT@UnmD zIL?`S8X)&L1JCpPSO5?1=@%VL@8@>hQr`G%NwIry-4L$7Zv|>Wk7T;a$QB$9osU)kr!$Gg_^&xFtTg%-ngd>H)dA7U3&Dya_u~ZZMfl z98p)75XKO^O@UazBCtD)X#pjxk~frPY^o32^&`8NN# ziwdR*uHyClf5HodHpDE$P|LXB%DJ#0On06rMt@HaoW?MYoi`O1o_P|=)VN}6yy*3s zrdAOGqjF(}Lf}Yd$>(i@w=`9W&WVOSX7t^=5<8TvCQ3UY7$bxt+;#(1srZv>*+}u% zc=@qLBef9IZJaxas8l|^VHo$XScAInqnf+euzdtOhN`k#p^Hx;Y2Xz{&c~wpvoU+x z1WcboPf88w11Yd=2w1au1W!D(4i7&0G_sJID>)pmgvsN_VOp<;ipMmfq)CKBw@~&P z%YYP`BL}7KX!ewbqa#cf;jD#8Zj5U#JsEv8MzJuRnW*X$WHXEo<3}NsgEoNk?2mIC z=b=4`m17Cu*8=#!o_xu{_FhG@bwy{WX*s~%tG41tkFG^M=rNA+2G5k(pt)OjkP^BY zF;SOlY%NSG1vqorV)QtP*h)&V?&Id=t8vGpPoYNs45b2m z^-$y@L@0%4nnW#OS}+4A7S2G}+tY(_eZ8pA@Hn73v6>6FUtMlHjJHaK>`YMJZ_y`V z%^*$1hOOCZp;oKO-y+szYM~ZV(a$U7qV4`<+Ayf6K%iiSOlT7byA3B)49WylS*%s4 zi}ykp4qhl)8cux#=bf|+=N@|$5HXNx5mLB3veTiUnFd0ZE{dTeMQY8=wM$W8CE<9B zJ$9SY*gfWLHr@$ZyGcJ^;w0f%6cc9C0ia{Zm<=1OkM8l@EvSMasi`z@CdM`acRu(8 z)>rF@!wPDtkD+FYE!zh%Qmu&|xbLKbA$wFzq)e_bQGkdVJ8pm`n|w-rs716J3{eV0 z%$_m@y@7*@+k(#pI#w&WlnVzH%*Aw;&ny&phdUh8z3>vRTCdi=NdGKHBe?2Sr(xbW zg?@x?YaF2jK5Q=#x*HP=ysbWZ5a!={ai4P>=YxB2Q}(2 zvB6N;T71hB>v7AfGpr@>?$FWT8LYAW6OL5ZT1(-R$j67zO zypac$kFh8iOF$$4m;+n3lf>(o$qRm}{90+(7d)3+Vt%vw1*$Bmgb5Y*k>;8lDPa(@ znUh>5Ao<_2LWq|m*(}=nPR0yPCWa8=pa1Iy3?M}0b26#w9WzYAB|)Gapw`*FJrQi6 zGJ&H|EJ}v&vHjflWg+0-Hrr-_k-HCRZ)e~(fm5hpQaIGChzprUBF&!dZpRhRP%T`F z@R8Xu3FqARCk6sJkuPaB`|s$`lYg2TH{NL8$kW!(vpy)=~psY|z>mw5Q2u*KxJbr?8vyqXFL> zFEPzUPLzwVSwwG4Nl{2Y4bhA}Y;WZF+5L|rE%b`;S)ouyvla9?t_& zcDaM25b#mIqjS~yN6p5WM@|tYjWivJC+(=vt)DSpV>GwA_HHlszz+EDw>gfpM{Z_& zl!51YPQv+j5BO#6<1duwX$yreP-7S7gRAhXbt9;`91bdCz0whFa?ol*}C&zDT^%XlgJ=$JsnlyjX_>nF*;Gr$kUN8 zFaiHbPjgYH^9s_yz{GK+IwC9yDUgzafFG!DPG_hJ0v(Wj6Udn6-f za10A2S&;0)qixKVN@xOwflPQ#syWgLVz!N4x;9NGWcSqU&c-G15i{ORC!SRll%-3| z5e(F277iQC30GKrw;jmaxrlzVKvsm2$l0bvocuczVXE<=hu58d4wg)v0H;}##fK~o zX7@ozxJv_gkT{}5SPUGLO62HklTr7gq47b#bCg^__n6&_fc?Co-*)n`^1rG_&$FPh z4qu@Rq8tq9Og54%Mi3OxXr#!CefagNO<28Yhxlf)7T_b047-L@q-n`)qJ}y%`zkws zY1~{Y%Do_rRH0@{tA!w@LS`UVZkkmq1(aj6W9HlmF&bo9N3va*yFw}5|E-Jq=$HPC z&tROF;)p&6SDw989t4K zk>~jj09^i(j(m{5$qo_8J|&X@=tTd$yO-nPtr6;8Spq3Dy4Z&=z4-Z&@f@#tc9* zdRLX$5~z5;=cK4N>!?L^SSN&{utO3z)X9ZR1eWL#U>E_u^1nBU;Vo&3)XP>{m(sh) zuU0j`?uH({4oe@A&c9Jgf#g-&#fFVI3=Arer3F>fPH%QJ+U~5c4p*8xV8zX?DTM75 zZPNjzm7i_gwpCi8Z`<=|C#;@Zht@|mK!H2b6qCvUe*2u0aoEIhA}J6x*e&a7W|?x! zuX_PE%TRC}DOgfkmj)cRsBPIP78;Q;)y09g@!DRc{JoEYxMJSM3eU8i3-nFBcIFMB z^s34W=b?w30bIN;a}(wuhoZl+Rxl4zf`71IKZ$c&X>~k^^|2=S=Ol zywn39tnX{D@lsUONl6IhJGVcI$9Bf3`wZaBjOmu6S*T{sT;%HZDK^Y)od6xz&)JiqH*BS0%@SFkN_%G(pLC(Nijb z3>_9mx%05}L}}sYH;PK%=+}V=;Ji@dqaZsuekUDtM1EBo!+^|pWmm@kAm2Tw2n=0= zJRgs(-GJrKZ9~fo+eKvtSi)iysv_G*$4wxT4r0b_b!VhFO(=!^2R>qfMG_H8Q}&S> zSNQxr&r|M^_0p8(akqEu`FC=6;Yp!HKW&Qg;d|b27AED8j#=G{s`k5#hW3N73;rPy zzNTNtLs12b+iI=J-~=0b>O z#O-xiyevz8gfMO5l%+>uR(}P>l*OAESsKF&d?YL?Nye>oCCxlK=OnncNd?U2dp85x z{>D(%ENeva2@NFl>J%9!*AcZsa>64rH^kSm12SlqtC|*x6_G_%edi%QU1$X@|jz82R7vGn5fwqn3ng~7` z)9%=J>8_>wc*-dkgJ;VBvMGlQAuYP7^r#t|I^QtX z8=*2TY7E|mP@HU7!?S&%cDEo+K;5qwn??I5`?g=%hSKf2XpS!nkio_ItI>2lJC5{z zj^qJ;bnlZGN|l00>D*?sg+LMlE6c0JV%wmk!paKqb=NF(XQGQo_p3|qOTN<l+=o?POJjN9#?~btkN1n7pz3o|zTF98(rwW5ydtkp%E!u_Rl11|VjTQcTSf zj4K8R(*|C1`iWRNZzc+910H$!(&%ZPie&*=F|RBIJJhEmZ92T!RZe?7_Y9{UZG$~fT7Oz-AK?&e5YZ*}SeP8Bh3#T4A z8<#GggdRz2G`W!T?V@QO0>#T+2hSajr_dusEA_D@1u_+0aVpuk3L1r}Vw?Oq7pq-g7V8~7sCIoH?|~_h3N4cOv<>LG zGg9V_?vvz_+p3V7`H>E2h(Ts2W9kh;Ib?kzgWIfPc5exu2ue)41)SCoqz_$hmll;|fnN6|9}j58{22`3S|j%|YVvccfZ& zGVNW1x8-GbUx0;8GU2xyI7NatQ+}zyNkDExC8}a%V5kn1WNC%e#}MpSa9(EBIkLD8 zKWX6fS1iVBPB{TVvw0+`>AnorIt;%VNVOTC&WzEF;jF@ksKv@KHzuE!Z1O^kz z4wbRK+w&xJ7!*)Ph=*6N$K&g_0R`@2=&Yj{wf)l$h+PoL=;pQqeJ9LrP`CgQCV4Hq z=aQ2#-XP!>-07ZQww|*q@_wMtd=J0xBaY+z{fm9(B}I`u&+h_o+KV0RQ2BkkzcO{G zzzV8zeeU|3(Fn&O_K2n_j!Gs9EAT2E$`;-jQ+kRxXW7xxHcST+7H;Uq!|WwyyS1=5 z7*>qpnGJGnKDP}FFX`6rHh@dmG%$)NmrBEna=)vMrot$aqN?qfgdPb}3XPL0SFJbT zgk@yK9^7!top^BNTEvA4sDh&F3#CJ?C=hXc4{oX^6WX$EH_|ps)>G|VRad}m|I}>8 zO-Gzalj^sbzjgX)Ms8mnMv1mvF#`vDn)cFdKGV$FWhY@CVN%)0rRSc3Ig`doGm2=M zP=~`Sf_yjzdom^no>?BXZJ{a_0+fn{PKnL>f3`Of3ZZoOFdZsmzWY2Wo|b!*Bmj1_ za@_pLN;Igal13&0;SP>nzcy6wTF)5c*xe^LOP_%(`+1C>q>6W6duE z_t{#(KKcFwc956k*7KrIBG2=A0G>Hur+omvs5^kCCV+q8hFei}dyoWW@k~_fC>FUK z;n9X}20yCev||=y{>1TcnzTWtN*aS>qSba&{BcANR^byHpsbEcJIL)t2HpvJnte-- z%AzKnc%oQ>xH4|_=Q5TyABOEKrCv95-Ph2uu6lJ zW3}N8OVzW%yBjXC@Qx{MX*;C(yasLEk#ryxdz21F-U;IJK#Y+B**sdf^bl|>-D;xZ zW;kx)T%2{>QuI0rid2pi>pA7*tGSGtPw;v2x$?}&Rv}cvz)jqn1z|OLumV!Yh+xbYZf4p?$e7!vt^ge5dc}*@s0&$ssVM+yiqP2&zg*|O$KN~Oahzvg_-Ve#G4njX2Ega{_^S`% z4+w@VgOm1CzyN?R+;BSvoT4~+XJkoa4t#R3og7i#LdDN8x4(pw7cD@6B2dJ=83aVW zlUmZyh7gL-3lG+0lP1I5*8yBR0+n6TG5FQIxYlTjUU_M-GG{>t@f6Kt~51f-j?=g3tJk9EjFq#ue(HSH?+2KLl-qRo~R&~ z79=&8+tTOg4Z6+0HQ*RLHjPDpTdcN{7z?IO!P&7PK09K#D&K% z#iWAL(8v>4I-uebQJkPyEFz6nCdwAxOs?705^p#bV@={r5Mq&4#hTOuQgqFw3({9M zN-ILdmU9E6NZ653Lr+jHBE`_x;O&#aZyaOnmfMJK zNyggM>TipB`+RU7kOQ*0O0{;V)lH>JDsbNPt4A;pQQ?w)u)Np0Q0a5g8=}y}%N@Xt zIwGBw;wJi>7>g(M;EFRAOG~|~uo(F6&=24@IgazHF$eHG&nE!baX`k^0s0a?Q*8uS z&vVlM*-HQU>u$%+QV$w#D6Pd=oC+tFgFH{`IBND(oHB0~!iesY8kR+a*&qX&9V%l& zsDo|#U>CEZd+hH;0M}d9o#~o9*i1I|4N;1ftQ09?inx^OXA4i(m=7ozXSmSiDN->afLe7$u|O%zyrpQ#>oD{=^&suMG>n-#LOYNtE8|doQTs-9 zZz7~zyn`~HShp1qJ+l=p_5_$tVY{$e)(IC+-DSNf^16R-jmug_BJf!;YhirW#2>u& z3{+GutK+xRh4>tz5DM?(M8|P<{-zuHf=?pP^S1!_kNx{J4(!pp12_Y5CxG99oy8v1 z=}Rem?;={QhHS^nUW)ThT!zU`jAE+6N~Bt?!kG!28oae(X4l4@(LrG^uXz^?ww<%K zgQhEuJ(7j9v4;?f;iilCrTKcB^;%^(PRzvh5&K0vvuOu@e9PS!YNZ&76L_TpVlq=0 z6uH1jp|%smI(BQ8qNh6A_AR!po_|L%1$-5s_oZ<}o1Scd=jRw$*)-)knKabYs>8z1 zK4#GZoU(K=CKdzqQ~ot>h=7>HUn%5rky5N)mQK+{H`{79_)w6^p{k%SY?FYEJd%xS zfah^+Tf8ol+C|va&eMjB_VOvdY#;C5F_Ci0GVjjF#m^pCiMlH7nBAq_CFzJc*aA2S z24UL5xU_|oso7$le0xJ@lBPpAfd8)JINus;0Otqa{IZR-{qV(nkgEPccMlE1 zv{U>1b$4K(*ee-0I}*hUn~^+j;Mn6{yOQ6%*H9$#6}&Z`B}z^4aUkfOj8$`SHxfo`0;JO z#IxIXqUpJ)(>5+34bO+;_>$GCXcYgu!_W{#L*5Ug)gdBRrXVJ^XUzTtyr;jTRUBkO z?zhb#@}z~L3;0nJg}9017cIc)%Z@?CS8Wn9e?(=EY-QIGt1h0rXv7d-XYo=Bl9{lH z#QR8A?-Zq?25w=mn4+ba5DPAB781M2wF7u}O=EPHz8{9^{yn4>DkJnJGRHaMpa(ZS zx(4e8YI38r6W5x1AAA8^r6K@7j?j}vxboGfU}4|x1NbO$t9B&czqfcF9{t;n<1mqa z!I-k!U;bZ^j@|XbIssf+CJf-jz(0T8ofs_kqUi)63pk+`a=}H(Npb!O$D%h+q-@MZm^ znj%XlFSBpT2-A=|_py37!>^Vt=*`ORwsN}Z~j=m`~@Xue8#WOp+G`x&S67Ri!MV&Bq<@4 z0CmSh-fHrAg0Druyh@ zHy^e|(=9zg#RX>e_26XEHD^pg*=P1lbBP2VZMqon+3hM0M6_;WAoAgo0wDxf5? zuLccO-Z0hpd{jyWVc;+m*N#rzJ#~~1M?30tGuy}VtPZ}<@EO?Mk`+Az>Iu*c`*72* z9>Q=!FI8Xgaot^7FVqhB@^W5RcL4X&6y-FNm zP+*{>{3{6yE8|tT1+r-cWDeX(VTPbqN$gm<+(zx2) zrPIBsX*&$PVA*J_kMzKOPKJdeg=gQ0o=L$sEXwZl-p8NDGuvxuxgiqiArRYbQ`0$k z0=Vooc`a#%a-QSJ$vwF8^!XCNZ5OT8?XiGYHwbp%Zuma=rayHY=P&j&fd8KnuX^5v zcTG$RSrG&Ohwt5qkw63Z|7Y(z;4Q7H>(}|(Ew4NIrrZ8W`LRdo^#)u znJ>Qy1Cb;Oh)dOe%R)_Z2-8VG1{o#L5s-w2;)m^Xpm&Nq*1C#Ec|elu(i$7 zRw}@@?MRW5I}7Hw33N0+=I_QLFG0`!&((pjgStrld33YdT`^Agqb++2i2*3~ju zn9`wkwWUbP&(+sRIQ(QP(DsW>I$Tf~b+hrR@p&3O zPtyzw%D~%Be%4b0xP1hZat%B1OMYvNIewb~JkN77a)x){1@72WH2^$EjX=akp6~u% z0K8^=us^XUuj91mA0<+;9u@Pc4=x4>s`>5o72JRj)xt(HV{DPrQ48rd&!fQ~Z}YCl z0=Rsmo0~e}tZRvQW3s?Vs$Z62v{pl<#td{bmn$SW$;7Dsg``AiULd;LP2WxhKM0+V z6Wt3#iM(TJ%MMXZb8H$M#^&J>Z0PH=QMg^;EXA;^Tt-i+j0JP|Ko5<9sSH@Jpy<=^ zBGXoGn|4xnoTAFba`9k3Hpvi#q2$k#lzJvC$l5%&Rc2JpYLz}BKW8fd03ZNKL_t(2 z1fDQh3iSRIYc}dw%NC#!b*uIV88IsI)q3o#08YsT7I1S~%~=ByQZ^t| z)GJ#6C+modxfV6`n8^OI%|Soz%`{j~31y#i%=PPd_iLYvp79ZQqsO561=Dm7)oqL+ z<9XbZ*vj+F^ZXRLj7`R)o{HZg!_THW>c+!n0{HiCMW0s|jfk#v6o)U|6VF<>CnEX^ za@*~Ct8KAv{4gFrD8@MMxV)ULrc5jY-tt7poYYRL#@uQa-dY=L7-9Dh4GZ`>Q7BGP zOVJ+FT;o_IjWU*%Qf*zlv>xCZZ4?Y!n?IUY+l*qxMy`=p)iS8-<{bZATfC6~ra)Q0 z1;mN)QlPXzqO}Z-jtSoC=b1~Pl99KXGpN=#50@cnLQu;?-0~&56{z7xv{U57t-ot) zk`F(V5;NHm@?q{B&CZ{9^zCByi;;}6GSvkIb#A~fKZw3pteh6&R&0{^%%=7ZY`;H-EayHkwRt?e*cB5)Sx zBm$QdN{>XM2h1wtB}X0te{@&|i3!;em}t?*8tzWlXCo1_7YIA0TCdA}sR^xBFXW9$ z*lHCFo$=uhrp64v&Zjo#0)C>DdoL9yp z?>x^$K6TIlpZ(s=81}nlyLiG;M_|vgk1o^^m{eppr6rxKy^RjrjX?hr_p?3U=`=+| zoGQyvXJNA*3uj!@$jk@Z)^W?WX(TLc14ygT)ApR({jQ^4+H%?!U(srq?4oA*uZ_B0 z^9>t@7=0I_NV+sbw#0KM!2+yJ(X@WKXnV-MdYUOixATyn>@zadM? zBYqctaqHa}NYsMQNtcO-tBMzQEQ-|>ozfslE?`mH_yv^H5xn$}xj5mO`!z(ZT1s7N z6WEYKn6^=P*%(t9JEq6I=seFUTtxw^o&U(mchw^1XTSYxjCdvVbobz8#~hA)WEeBq z3Yf)U<2R*CX%;UY0~6$NclN=yh+45=nP&ptjK~S*;z%zh&bEbooM~?>xVCp6u7$?! zWyku3${ONgyOof3tS0Jy5tWfr_`1m2Q1X>E^h@49!APf5sT6A2<4 z%fG9+h4w{+sQ6vD>(LdsfAxCgQAvI-G7H*d-!!}Ez$0-r7v6(U!xbieat~cu6))I- zCSLLEgRH34_|`U(Of_C@`agBx1}1jOmlNrsUxGKOO_)d#gNT{6UYH~`YGrTR=sl-*;CU80y*_l zBqFy|LoF|A?$8~&1DVKOGwV3 zW2oQWT4ZZU&)AD*2jVUb<_#Sk73mTvH}rlbfRlF=qGlqj9SAlMM^nYFOWQ7k!r)@WIt&< zk{$kxg|*RAtkmof)tGeI?G%;YksNtbJWIaWHtRIq(6JPOeRj4Y z5PkRo1o-i7_h2NaHa-W5w%1FF?MY+@{?d2qx`ufkS~0VrO1f+*uVJ4s##>H#KDtGf zuob~|zU~A7{!?SjtDXwL>2EOeFa07q`u%EOEx<%W2PTz%^xL~IRLgM8(MKUl5;08m z{8VUD70Pe=A$$=cq)^iI25686)K1dL z1$|`#j0JEAfPZFB>Dq-2vdzdCfZ5a>1WpZ(#P_lEk#eZ)tU!qYK4U& z`cJarFJNxLzuo(A;HsZ*#^c<^^I#gJ0oo$>ss&74M9A}Q=E=1fxAkKTuGk zi_-4HoABrKc}sfC6?09ZGRSnI5^WiF@dfz9(luDJzF#8ToVq9;{a&qMNrzTJv3m17 zkpc)sRg>ewpokPRvI_p?wZ}>`51AMeX|%AYT4{vs?;j`p0w($ehZ? zh8L}D4T7hbFHrZSPX4$8s{Xv$*~pudDEWyF-G!^V%BGEl+t& z(!D7dX7S(2iH$j<&614?Rhl``-2g5rg%)=v*_DY_57SIJMooZw*Y)GxrK^RBB5m~| zA;C&swz`ywEsfR&l8V+Jo1er$p&7T%w-vbX8*$%1^s-}s`pR)Ny z^utpXqmr(*zxY-Dg-*~CiH;crEjOf*t`&N+#Y2f)nf~Ce#fnuq;BNgde~%ISlO3e{ z5#;%YVD0kUu0fX?ymb$4~mi(R|h4h*4U{TVDs=&;ARg)3f~VzX1I{laOO!zi!OL6p?t8&g-RjZ zs0jYfa9nMSdH)juI4LS8?hJSN#P^^=Qlgf}!VI~u02V#G66M~Rnh&-{1oC^*@1Uqh z{qSi|BYZLd*Gi!6ShRvzEnul>70SUjCxgq4w=z4%DEe*XMQEyIO8{_@5htZa*VZaS zw#~erts5ycbKqlV=M0H-$)%>Y}FoGvKD@+B;cfu@)lxR08i*t_Fp;`e@yr} zKM{a8@3^HX*zz12;fqoWTkn5NvyJVPe6s7*u1J^D*57nA!Pd`7mEAe;#-nv_RXQuhNs42hwH>}$b!AFe%nW<*vs-S*`qW3wgi6^Y`=_G_t^lrd zQ0loW+lZ->qVM5_&pZex9^8c)*5Ej$9UukJ8WY+DC=;GZo%(`)V+_5D8}mk|Zk{g$ zu%c5}wWH3f0L}=H5>CFD3b4cMt_PN&d(IqnXMFQNExdLeKa?{3N4jH-K*e z;MzWK;AQHrlzA-NQx}ExKOe>`78 zgmaHO7{x3_*<%45NNADht2BhFQBM0~Ut`QlH=i7UpA6u}X@6@^aRZDnG9g4!hBOeN zIy#HpyLbhn-fmGN)ZP(icF@98o5r|3_OaMO+!VNOVRnzbNlhPVPKmn~iIiJfsoQCa zp)isIY<14DO*$6Twb-=vC|}l^=0<2tTGIyhTOR?t0emX}PMKH_UKYwTO}!YIr^eNW zW*JF!hzV#{BPi0B7-%Ma-T0a1ppIOG=)E5%}_Tn=zEc2#O_H zu^VMEyZ6%KrF}Hh9>}+TBTfBlz0YP=qM1sOJhcVgEo0!OR?LH;hYEGu9|r>H=7St-F=(kNtj1W03G&0q~TJ+uNNh9Y6qnb8Qn zQ-|d2sf;MH2|y6~5{YYM?I9oT$2>EL_q_fULMJ32+>N)?M&gajmucRt$LQ}VQK6-c zbNv74)UCIk_x;A0tH%TQmjIkQ6|U|teGQDkoofwOZpMJi)~pxr$2=$?Po1u{b_A-^ zjutZ;(7sJ5^q0Pqzr^>CyD?k9l`}O)wk;-#94RaPs?rFNByCM@xWBt8(-4!{whP~0 zpm?fxvePWU+xGaj_FDpTqHRKFCGBQaqY?H*=zFBOhUm(8J~pR5ZusN9sD)j~X~EY) z3Zc$HU3jFRnnu!%7x>f#2kHrRed<`Zel^a1*^6-6Av3ij(dy`AGy+M0h`APr+e{-- zjnT?gKg)smw<65N$#(-w~uVJE}{IW6TE#m=vrjXbAHygh69Dh5E02h8 z8OmyrQc_d^_gKu#k`VdQ|Pu;j>rQZ$UW1p#8 zy<{KF0WHR#qNf3GL;*T0D~KDBKeB)>OQ037+OF5M`5qO^GdjNR6{qLKupR}nF zk;()fTD1XrSWrEP-2na+FVzib&8Rj2TyVO}M&&l8BB_?ve8}$byHhjf$pM@iegtqT zJ2EIY81)MH?cxOpERt-utwN?OSQ_TQ6_rw>bV7C_TQ@pX{332!u^tbt-hfzAWiB1o ziK}-3vp9&0R*}R7X`uZANF>UBc=={A+K$sf>>X9`nYX?Y3|A>IDvod}Yt{hpCtQyt z6|T+uI<9T{sM8CWK86<>WB%X({7nG9+PPP<t<<0<|0H{5jK5tR?X0kr>cA`>t(1&F){Ev?tI2aMA{)ZqW+h+O=rdp6;n*Q#B~! z{`H&1;2{R-h6?hXJ1o6d`090AYT?d-w1gCiDd3Tn0~k$#u**j zpd{V(1mvb(4~4wOcBVDkKvee21{+fgz~5|)`ELi{7X!Gob1!Abo>^)(Y^AsFkZNY6 z65jFfaslw1xxU>I_)`SnE`n~9^KCxdGE-byMZlX{8~k~=8^Cw$P~YNgTL*Cd8s~sY zC3v>oJWVsiQ3;Rs595#bKY}_HM|>{Ao!mXSogbMfESfW(rcOTroTd{I9$2vfNx*z} zib6h$IoS~2eb%dS)NF0B_iQ6ygH_Txl$DSphx>7Zd)E9xhu@-{{t{!%We&i184BUp zC$CC+q$Cl*?|gVUqV5^+Jg(^6qUrW&Hw$Gesp)etRoMQAFk!IvRoNywt8rKUdjj;fCkbbO{lg5RY!^$4Hz= z&YQ;9%wx~YD>&=g|L8}K>tb<=D%V5xf;vy7{GTi{zhqjA7s+QZOd}pOHic-0NTCIj4 z6wLHfHwD!Q0;cN}&=KN-2Uc!|2Gc)%tck@m=>BcJj^@f7lSC|7`-e zBUz|=AGLyNFsMdF{PgBqF@zElPr2fqI-C)OBvM$%VhTlQfK2Cmh`kWY2Zqr%JPJR} z5Jd%4lT17__YFqy?{7Ut3YyG^)36-UlFw(s#0tNUsTel;*`1{t$Bw<-sR7`R7-J4~ z06q$67sx& zq#ois-})_n_sf;YGao0P`YfD!`ZM5#2`aUX=qeY5og#AKt{~Kz7r*wGe67yTt8-(x)fx+x zy?FS6&A8@c--MU$ha|~R>KVWXKm51YXMeyC2a#n75^ik?0=ogcv+vOgnMq@#fE2x6 ztx<{SezToTeK6}mfd9K=5mr@l#6G(pJ2&_RRs}%SC5zXtcuH<~g4px%*oGkt*R@2+ zKXiMFDg>%F3LAL_Qee&ceo8HUR-s>jaacX zL6(&C`C$l8KVk;n@!k^<6b6L#BV%7(GCK9rcb`}D4L0r2S8r1XU9`xu=djM`@?G0Iq=m#}cFP7>Va$*~SqJ*E8{R6#!?gi=uUDioJUZ zc_Hj|XHjPko7Zu-R{eDnX^4wKD85Oj&ocbbhN z_c!1l{`sXi>X?OqSAiibrLpzh1&7>}xn-ySuDN3ZRW2GM!b_1|Xh6ATI#&4xcRaEb z4{jJm)ho0Zest<)?BZjaYgD6zI|ynS`B=7o2$jqrrn3_zWwQ)n5TKr|X4Q0*S_T^P?xeC|kBox1h0=RJu4zDpSyyZd*Ym}(KF zIdGaA-}~@#%;=fD8^E7rfO>phae^?4B-&oT4!GN%62;9?s8X#6q;Mbmz}-t%V$s?m zR7^Al-koF52xkTvLM0fOOaOdk-w^sos*=wx779|BjO#UozK@=wk1j995qosuU4Q*7 z%w&+A)P#{ju`7n`4WO1C2}Q6p856dcyiAdC^9BO=I{|!pid@hRyNm{a>t;-}P}ml5 z=lzdi*6evQAVg(z42@9PDbu=$Y452K!`LdjW)f}TMk@QV&$hMN)`-U$T`+3%k;W1J z<5R!EgNv48?(6`ko_Z#}@THq%EBoGyUV&?`{TkvyA1{32;dtX)j(``8N+U(HJz3AA ze6YE-KcR`@9<_AII+;|JL~s$fq)@DONZre^XxSRvvt|&Zh^#C9gsxzM zA8rM36}8GlC6Pr;A4@lEMkS%|Z7P(8DYokB)*k)zv?mq z__YAu(e5`)%g@<7mg@&}H3|OjN0zTeS}4j^Omk~2Ug(OiMNM0Xo32GTE6}5bAl*Kj zEEHo~EykxvvIVKfMI^ zJ-8HCeQ7b)J zNl-2zdbk#8r5$QJK7$~qy)rFFUuQ4c0l3t5EPzW3y^eDQa62Om3xPTEAjE^KHsJQ9 zn^5(N4gPrNZltxE*sLgW0b(Q1l1)Px7G{*vfVmh+sx$|By2~gQeE78y%uMPy^Z4iE zMf*qSk|YTW@G(5L;Y;3ImxxC3QUV;;!8s)=nV%(qe+|GJJNGg=aAphO+%P(SN6|+y zz>0N!7`5&sJ0*bIbcHlO7`7tw#u?>?0_1Y|H5i|fxbj!q@0$3k z-NyU>IsyF00A4kLAu;_vYWr{+bR=#g$!+xv9`7H(TRzoqNE3tI7O)#37{h=;oiH};`&eBgrHW%8&2IHuYBoY@X`wI zd$fWpKmQQ={16v?_H~#&pDoY8559Rfe*dF~5Tpq{_@UQg{{zbK{1kb{2%Pe>DQfjm zN!jFL20^UWs9d)8!dz*Uqn&=kZc1En8vvg90oD%3xasaC(>?;9(N#vl%Mno-H&0Qj z4dR^RkH+)%?-l<{O)IG{X2bJaQjXfCImK8gKOuns7Qk^+VsP!Ki?DUFR&_{rYZ=dA zpps(k=0Q!NNMXeBKX(oQmmP-`VyGcOu_>kpBc+Z>YC?J1WSTJQjsohJBti?M#Avm~ zCY}f%yYidZyt<10=6JaDy(gfA$C1Vv9$p>bB8kAeasDU%26OfUk{pPKfNReGA^KPK zfow zo~?+{(JI1-&M8jg!b$IsW2a2l8bqh(%QgVGYqV?y(ct_x001BWNkl)Nps;_)Myz}{#D({GaJzmov| z5P-v`!qx1sYiO9NyRDJ2DHIQ*39xcQUkiZC#%U)5a3u&T8--A=UV%BAY$U&JBy5g+ zrZ&U`5hZ>@G>M>h%7JQQy=>tmOn6p`Mo}__~1*? z?XMyHBO~uN4Y7E2giHSO9`u(Yyzko6(7TXDP)652ZP1Yp7+m?D@1nN3iobgHEWG2q zQ(#2%t|HxXDcLBN0pQr@jREC2;=7~o_UG7k062RPS;%G)b9vtges}*$;ek(g01qi` z>``$s5lQfBnqY2_;EhKghT{&NE4*+SYFh#DDHegRB!I66Ft7a)F%3Vt6#!Sz5LE;` zwssRzFO=M^v=n;;@@%I`p-3K2By$Pe)}yk;pdm|R6bofkM-v25fH)sPp7-LnH?6`A zU%wGieFPu)=hJccJ{9y724xAX)u^Z3gZr2Ixa@QHp|9xUgV((Vy$kB1?#9rCi-jMD zxcAos_{x8L6H#FB&;NWTo^|951l}M*YK+GzJZT_l7+Ki?W}|Vt8=8irZfaceHUhX~ zp)lfPPsHlM8vgIzWz(XFxwLN>gB2Qy(3nCgg!~hDKFWmxN`a4n8Yg+3l8e$-R!k~5 zFsS2$XT20%DNwKtZw+@IF->-S`7H!yJN0fi5WqXl%HQ!fzf}NN@;(84$vRD;B$-jo z58;s#z*}O%X&eP=`OgBlG%m6xy#a%zcrVSacxcFO02CI14^Y_Hx zo_Z8!2YpDZn_!{{UeJX!E#t0-GhBK7gXk{?IR8IS!_0kZ2t`{XN9qAyQb0KduKl;4 zWAVLfFtaDZg&#f(d++6=UKv0k3P1^qW(s9Da8K$4*+l?+sG10~X*_^;7mFwdWLzc4 zJVxM}9xUYU(MP%XR~JqivxH;LA5`MlGXT zJ;BWZxU-;|=8Zg!26>53Bm&ol2WL^mXoV3l^(6|($PLec&wS#$c=+DUnAc@+@q3QP z{GLJh^&ylCK5A)#T54eYnYhnJ;F}8pF8u82n7N>iKyrsUQl2aK5!8JQJq}#?p>H4= z&2Y@~=HspZaDptKzE^MQxFn5Gn|O51aT1@qbKq^xcV!*92Kpyy@<=dX zBk-P531y$nXbCM^mF*N~D0m)By@msN0(|iF=Ls*oS*&Cbks%kR+7v2bDmQ(11nweI zj&4TaEBgjfiP?qbq$(vnF7lN8i|($bCylK&F`*{5P7Nc4pKD`JntAZUF4Qu%&WE`D zmJRsQb>BoG_waYGdkJ3tf^G!$mGIJ3INYPP8gdiCk7nVnM>AaZU-x045aPq1c^zgh zh`CE;mRurm{w>IIgh?4c|K3Xc=-W4;=+$xFznqO{Kf4EMT7@r-6QVMtkC}dl0^oc* zHaR&>pMTrHJ6Rvx1pxf94Fed7wLITY^T}D)@z7f?qevDFi~b z$CI9eqxR_$e0S2ahEcc_^qZJ4S+8Uw-?PgDxYJ8eks3DB0_z4wF;J;Bbby6=C&Y}M z1Hc^#EM668HLuJhNIlZAQsha3axe?^&A`={eGh9M z9>D<%=HdJgos8~oR{iTD&M(bIN^G?(-gr5H-e|R^5w^}EO zFCMUQq>hb4BetcM;bRUz@Kj%T+DG8zxvC#x;w(<)zg@>|aRD*(VhiR1EDU`Nx zU>AtMA6&fwbp&Fh-3s8u>=`}XhVV5aAjQn7aqI^0tpIpmCC2)JAsd13Tma6YN3AHP_hS}tY_;9b48qixCWg#Q5ocX^ z{f+WFDMf$S5JBD1loKU_@Au%g#Z_GPe& z&c>|yDMA7842hS?;=rjAnj%n%&=UYZ`08W0@q0f<$xm?Q74O6zdskt+VVEqE7Jngn z%5`e7b@wrWC$I|u_yeofi}|ujFeu=<2z*9w4?===n!wLuVWuRW8dtCbn13t8BY4qa z````FKLE3wc%9_YHJ8r9=u|m&T>x(=!aBm5HpuctZmuPGyl()Rp(cld6s0DUjEyd~ zk#?HqU{zgBQzxm%!mQ0sP$pJ#-s(P5uLrp1>Kn20krg<2uEB-xIs?7Ias+9=^(OI= zTZ&fb`H1O3=yl_srNG6XzYG1v2p4|lEX-Vxg1)ibs_OZ)frtWG$tV!f(Ps$w_lv)V z&1p}-n&nP=WPaZng`HqphX4JF1TB8#5GB7Q!K5z;x1ZuY#aM~yB_z-zUXEV z)6icfbP~c^-@cL$^q?MihzD0bj>Mz=g66Fiz*EU{ z&zjLI%{v5ev08&CuJvBXz7Nft2YHH_@enRP`=yv4DJNWZk(sa#8)xg}6L9C=H38fz z(rj%G6Dn#suzdA;>V$`e)C3E29~J}(ktnkXooUY+Kh>iWJTPw47l|AdnE^c;kB>F z%mvg@Vce`zoSY<#V5mKlr3Rr_LXZNBZtcTYKJ`nWTEXA{()Jg)C^(}ZD+d>)j)m*(AvQi9S@SsRl)zw@4l$gm z!ZbnXd6?bXLw_EXh^7jsjw~6ME|_7dt2eFSLS?5&FRkRpi9D{@sVas7;*8*P>dbNGX%SQnIi}7wczfR8gnzeHrODDW zT_N8+5_zpmCy4%sLCuS>X0VFi-1{(UK6P`Hz0}Ery7VlDb4Sc^t0@o<_1wdfbp&vB zP;-26ymPoSZD%mMx7z}^V>jupO=TriLYcuyIjv#OWC-V<^HMQ<;Ibw6ZKLtd-hK1Q z@4^vyi*S9*NaWzBNRk2akt8uf30QR>LdS07 zbAZmm<(K~gk1tz~J%e@l=ml>^*0l9|so?GBy$pvRF%JQYn&j)I)+xpTxY}&A05~IUCuE_F7rDa*fa^JRYrS1h zZRh#rZ2)lQg1P&Vg0}Glz}F7d1i-5vl`E$%fLBvs+4>Dn4&XUmE>-1He2Iik%aOz7 zieS%rPz}BLC|-B`(Kv4Z9u#DLD4lf*sS!#9zU#HpKS2cUGN{~Wuimg(xTKk<#;y*) zGvOOe-w2$ePqldr!oVP@Q%p)qn@E!ozxlt1@U{QG6NRLX_x$a%aLnPo2*Oe1Nd-k# z_BpA!#I*_F3aB)O;I_6da7(wJq~f7FD&m(vT#D~~`Ok>*05f_v;>s)DhVC8$IRCJ* zNV4}W-kEH1=90^(n&MkF3U9DhR4!M6U5lV9NwkY1_%;H#j0ui)FF@4`EPy{E0IsRC z&c&dbLJ{W=wLfEyTXuv7BlQ%^Hf%&H_J4Mvu@QK|Gnm=a4X**0;zzs}B zlho-C;Or)21nzmcY%L@4xa`Kdbsj!()fX|iVHC$aV-ZE3BX9@cx$#l+L&<^v{{AJX z*a*CnTM`1e)JL*RQz!!BzNAnFDs`;t>)QgrnX8KoEP%VpmZn8Av2q~aJC-P1sw5te zq&3XSD)`q|9gjn1`NF2^?9#QxQx`F-T~AJS8vuO$zzF(B>d1YHT4^Pl04{jY*hqD9 z7`J(DNr4kAtFo)00-#BKWJwpk_O&~3^RI5f-rY4^{GPM1N2wp>Xaq6;uU5y5sEnjm zw^o(yrBK9K$58Ji1&w%AeK0_r#3*%zh$|jSd5E8U;}QJ)JGY`_>bU5V)3N`7y@=Ue zM+%sA>S=JpU5BQ)3UP_CotrLFZ*j&`1M^>WdsdjuP z4`qU}6q3n!h{gUb5bdJPBUP*&7(_}nO<|Dfm?3~O0-w>{1)t43qO?e`)*6YJb+fpM zROp0cOPMG@u{wkk_nU{aj(dg_GwCkX;oEP0^dcv_>lr$11AuQFs$kPl1qdP)bdsE) zbM1DSuucx+HqUKXPD~I4^uS~xh=aU{#Sir1Q=j;$C=LGO=?CKY=kA4&I^BkD-ApGZ zKs}Xohfo2zZEdTF$eVsB8m(JB%VngUqD5UjVt)cPv|nI4Ef$ zxs!+R8#NQpD1-qPQ$5r!>Khuxy5SK4aPI0z0hUEyB5;G5-CZ`?>t&c%-HZ#)c{%3gq`kJ}Q9Ahy^xR_TuZ3BS!ja0E=U{nA+v4ZZ5 zz{TNuT1ViFF4*4AJtETz-KbQISfs66Uc-?G&cX%%_*du&*U_Wfw#t+4=OL}sP%IX; zBeiV+Cl!m@;+p#4WZ}e98d!=j@ZlvH!lVZ)AE@J+%dSHSMZErRPR5Im+ZV-h4Ov## z9C#zLZsmQq=+v}G)EnkDXS8PBMm4rFe$wSs* z(X3Z`7$b1c4@JXg)8KFez!_8L(mAPQL1wyVc9*U1Wr~c|bJzbMH>5658TsKsAY_Ih zjWIJB#cQ5-1YYs9IjT}Pb@C`;skZBx8gB)_byKFX2iIY$5iVV`5hg4s#g3aT*VUz5 zwoZ=WCq1_;GB!+de|P`e6ZuSPK&azRT<^j+zj+^S{moq{)cSGx``(BHXRk+O)+3?m zu<(W1p{c9{OS+l>fV(Hh0&%KNK#rEl;D)wsoOm^Zk{9CZ*Z&5;zi}yMca?F`#iwJ> zy*Yy_nxmw@vLD&4a*8;vp;#)2hv(R%wP-1=OuICV&;`(9*wIj@R1UcQz?%1RocIB% zCKLd_Z*4zD^T1mEc5e9dI=P2qR4s}oo-g%QR%q7u4`5@prYRIg;Ax5=pfzABGO|78 zA`F8Eu}D-TW?H1xz&J$;KMYZ+#VGhb3V9ue^n^J7)kmSnPJObr*xV= zyK4n>$zrmRC&ZG+M)1+gZ$K31IP+x(;k73oiW1hr_Xd#)yMu$91xFgax~^5Bk+hjY z(XB7Dt5heH0+a=C21MM-dYLX5QuZGWanU>J;8VjfN6*1q-}(v|ZwPr_LAl(G%4l60 zIEuv*(lnMoqWIb1db|_N0`pOsKuvtbsi>)S#n`aKlcd$;%*9qX)0(eJfU&)R>`;!AW zX;RXSxwan(tJ@qZT=l0>4*UrL+(uk^R>E*4#I>LNE|xz$j0HVDuK3pzF*Dl0vX$h% zVQLKkZ_@CbKu~)CF1r}n&(Pq3Q-@$dmIx#KR5;;zYT)~f^nk45fuS`-CG#Se#}2ZpRCkSj~o74IPCYJ@7hzK51BS zhq|vf0o*<|8`ALU5x@!Be_p%mJ7tg{f== zPN0=BktOJkB6O7s$OXU|C@AHWUa$(_w)jo2WA;gK_br87pj;iqtDZI=XB>Mlica9l z_D{4%;yW0?KT80=6u`wDeIYyi zzr7IkdJ#9?xEMeD?ypeFQoQ>uug3EZts~6V1EK*#ik7<6D-BOujy2)I=)OGwXB1BW z=l9UyA(M7zok-G1!A>_XLbX~&u^0ex1g{GG*C&64NAFsXt}w@?A9*8Y&xys+-t(9a z3XsH^fVp(lN%qpw3LW!=NVQuGix0RJz+I&6_MokO0?i0K#P1g^#`579HA9V&4tvr_ z4?%`Nw0PJ#ox=o7r3F~Bat%i9!Xq^jVUTewr06XcQ7Qz;b3(p>m-1d1ao1(kD1dXf zO~Ezh)ya-x8qr6Oi7`JL#QXpD1k9Gs%$6O2-R#4_r@eC zBXIT&ScwG&EVd?~+B&vpmnpu?LzkZ;9C;jXKKaEsc76$^mK?Y&eip=AQz|>)5xt85 zel~z_?0}O^p;J5ofLp@`0yrUH-R7zoJ4`nKA3uo3q*L-D(m25N|M64YciZFGYle?2 z&VM<&y;X>^VG+A$N4Db zf>%iazxcsA{N&reLRcHc`R_j$2S0;NR(*)*W}gBX<#3q*w_9ROp|IHHB1W&8wh)SxIV}~h{lgU* z#M3DUzO^X84X!ll!QFQb>hyc)31;duZ)DQ_C7l`o5l}%H=6#@|37tjU^{#oY(oSttXUTDq?(`r{-fXg z0Rus|0C;QOe1~6u3rkc)DLD?=%##6eoMGj<4XCnL!2-A%k~1}zVs3Abs0uo;PS|b_ zgF?zcB17ui)QLphs%{trkuX^@?g$IOtYiR}yzWGindLz?ipzWNK;U+d{UieTGXdP! zi5Jnib1I9(ZQvyi5ronzymP1DG?HS|;E1p#q`lU;Dm7?`dIzojA- z4@n#&WC6$u{V-x>!-Hb1tJ-S|Gub&Bw5b|llBpWurPtpla+cvZaR#Yf<|`^`mBhz+V#>cHF;G@odADDq6&aX0~-Ir&YK_LWoq zi(Dkuv^*6%(`IEy(2t-!5Cf|>Zblwxu_UC;Se&R5wnU|>A<)0(LIaucShyG4Ha78@}^L{Ng8%U}liv ziuW9ceP#|K0^90qh*4^vy8T{^noy)AB-7ZzheuwBPmq=lX>z;`GC#oj!69rM8kSvyC=6QJBBr)! zpSE|;4DBekxa>0d(jMQClx@AYv8x@&PAMD3Gv|bO>&eH6%xs}ym6;<+$T?@-r5V`C za}v2_ec}$lC+YdkvER>XkhJ>m0*7*tZ8^?Hkj>!OJpkE~dBBRt`%uX;M8y)~Y9^a| z-?AB8&P>7E0l1BfTfs-iN8?-*vIW}$z^Mt_)b=02ee(*yW`dHFa?vDtIA+j1E0Yt8x*zq&8%gQWZG()SpP;N%xuu zbr?oH6Hs&X(-QIl;PUgois20z4moHqeBcAG zKoHfC#C7T9bUE5)RY`<-HmDZ;u>0*)?&~hp^VD=avWuK(f?ji z4e*=0?njkL6`w`S&OSSF3!)yln`61=yw?s6U=zJ;rMPMToxKKLF77*fb8iD;g=NtfmUvM1ORc5=&7z!(gqtJW{hk{!wpeE~v2EY6q)=KT zCaZC6z&($75`hnu3ON6hr(yO&HsojU zS(GGz%ZO_~{vdN8Oam;wV-VL}^%G>3D$Y6QSR8-+VetJLJdf8R+|L%W8@I-ME0%9A zMXg;G!5x6RL?Pd;jwSxld7(QPN~%`<0v;Vq@rU~#}bnA_Yy|O>h{HuBt*-dz5=74B$atM_3!c>yCdO{`$a~=(3nWzIekcbNtX!lxa+ki5yKBy2bH=a4sBYOk(Wl$@`DMzo_uo;6j4|xy)wzZr& z+6KG9HLq#1!T#COld)mrC6i?WObEvcv3YI14!bK9T&KlNij=*@X^6m3!<(stE_~;P zM{wg0e}(S69~ZsrOdK?K0JDlU)GINfQVGK}sWd<&ddSYbo;h&6Ug60S*gX#krFF&J zmC~F9@epxR!rhM={M#27V{@T^3qE}YW-U}BV@;i;C={Ztw7PHm0OFz>q5!W3Tz~a# zc<|1}DEj^Q=oRM)H{A0p0^s_FH*U=c001BWNklJ z%w#AAKIRs?;Ikk(K6kerH^W6O%Bpz!+%n#Ea8=I{OIGQl`F4xFcM@2zxJC~xPTFw(2;5fdO)jYiJ|@ospfFHKvyzmA z)M%M#Zod0=v zl_HLO=Dv9Qc`t$I4@irDYfVCnuZ~-!%lFv#)83U#-%qI;q-!DH62LXV$bV-9e*5xG zcwp5A#LPPzKL1Grp|${!KySYuq2p=Gm}l_fg`!=wV&f)^#0hdXqPbn3C^97IDnytS z6{Uzd5ddegGxRcaRW{)xZ+r#zQ7Q4Uye3&$?9NcGE?#srQw>SW2Cnh^G zca6h>whAdVxg5^)wnnFF`1sjfk6^f#YO(VVL z+Ti}($}S|$in#PY-hyZzkVPqSKW=OjCYFC@&R;dm!vy%#O)Ky}*Z&q#n&O@BJV`9r zNF(GTmrA6?B&fFK`#Gg(C84v61GuX5IcK7=0Ip+O$8&~SP{Pd*t-_LxgGj9N%~Sz! zjz_xi5Wp*0j%D=1RH5SL`;~V41U;o9dIQcEyZ@a4j^E2ad|bg) zG*TQjO&uUKWowZ}NC$09{4GCni81Cf2jFi4@YPBA+Nu5}Edh8ec~J#$Rn4GMwvQnI zzqofPZno+>?07R74(D#KCQs45*mw_s%mCIT~zy8-;ragxPfDN&uvCA z>YlAT2#P)tXr-0Gyn zYc(-BrW|KAuA>k{@DmjZQUG@;6iEUpLx;?hAQV@5?aX8mRa$OP@#o_YkA}GBt2ba% zx)~q)+y&^F&jR9z^1CH^*OvKq4q3Ro5J{Y%%n4cb@Y&0Mi)Ht(z}%i1uDJXkP$*Ha ze6%HZPXVSJf%Ml3hhY~7a5p|}Kw(oT4P22OjM7o7ehD|-y98^7sz{_CqVtB(!d4Q~ zWom$P=mi)_QUUOk?ouu9mzT>3d`4FpT^{F))E7Ov&z=tb!6^9Q(|tW3QefN~qC6vauDHLG5zUk~?@+BScZ$GzPVxj9=XK2p%7arD4XIcy#g! zj0bQsP%3GLrEAuT{4ERW%4t{cRmw8Z$f4v>I<`eNw~d>Sr)B~a(hz~_ z;RhHALR@(Dd6=<37t0X=UKjkd3*a(;*m)P%!J1mZ>p?nX@arEg#xK9U2!33{g%`aF z`yW(95E@jO5-O6?A!+jV5SKx zae?tw_k@x6PwsdGi&kvH2)dAkob-&~a`=&tyk0{T*U=k!=n69&xNvXmJAZHCmzucF z77}UKEkpt8ajn5Lkwyc)RN;tf-aE&pP zXYHC|w1_&2xwvy#5m$ZT`xprWTzK_6(YqgQxkgo=+zsdU)-MU&vn&w{Hbz;)!&P)g zGvQT$kA3hL=v%cB3m3$=;6s0hf;0`rh?5$+y7-1_!eOTaP-8N+|01UECmT!&*Ph@s zQQQK}d7%J4l!f^5t@mNn6r{;ZRV^ogfRpgl9Dw`W2j>QL<4FS#yQUqVU8Xq~domx9 zVpdN#3X=rj(&m)bQ1t6~?!I&IPcJ%5=!6M1RYb?AzjDgG7QdM66vekAmxiUIzxWCMP7*Mmr+UUfG&0qPm)gyeU!2u5YRn&f*! z&xq*LUbA}f%!BsB+^ztqRuHnlnAXK{oh%JxQ4J0 zA!Zbvr6|(&EM=@5U|_I>k6ipM#Di5lWA79fyyLYfrz;WWnXKbYJY>-80sr#mk0Y!XamJ~y!l|!5P|Y1of|1Hbl*>iiz30>qC-N4i z>1Ve9Z{_Fk#~j5Vm3w!53epuqfp4fxjQZ^x}S-G-u{;quGgjy?8fooh%yUv~kWFT`#4 zOP{O{*ggV%3y#ieO{QgMsJw6rxG}g{wrLo*EMASOiKY~Qi_SMqxoP?4d04h~9pc64xOI9GEydG z{~{E^@c{ll09Q@cIGMWN!w5A&BFnRnr31j1Z~7xDQ8#KyB3mxa1sWhI3S)t4WCA)A zWupE!z!M3W~P^n{X z)H&J|tfsQ6``LCLWXy-k^k?P37IVecDnN|@zNAY5yimu5SHDjHyzbG!SQi2X(Dp}& zEFLVPlDjUiF%!vv$Q0ox0Y*0fAG_!asBS3Wu!9!heIGmlemIJhYKzR{Dp7pbJhlLE zo7&?}(|SenEwM0|`T_1=@i^{U(T@s3VKuQ^rPCaGNue|VJj93rmablloa`hrs8|bP zq;0RayAYzQ5L#}^#357)=$5(Dm5$=nBlpM2M=TIF3WL99gSW*Evce{Q+Sc*q=@OwH!dV~#JkcnX4LfYhWfaX^H#y)GwW0$y zieD)JR!?K4~V&A#Ih3`HCbBfF0CmRt+Zk&u5J-PT?w!Cm{ejzAYE47RU zu>2hzh$_~_n1T_wvO1XKQ?V$`nOE~YaSs9f^WVcrA;ASM0{3G0To@WkitTSCIf0mK zlvI~kvsDoW0cy1r0SYK&Y_;#hbszl^y1WQ~cg_oN>tOHwU!^_+V%iUpJ+ra@aJC)&FM!C{gWk_1s0p^%K?pq?D(o%RALAO^Y_b#iZZeraBO z3yqZaE`gtVr7`Az#{>9604v)6><E)>ZwPwMc}SR-;a!L(Zl z61i9-z%6^)EJrBK3r40BrFeA=|g{dVZbwu?NzW$k8amR1&#h$YYxb%{9 zQ0__Lg`*QyqM058{Ryv<<3|Bp>6BXnI8!Kf&WEsoo9})I%ZCjrh(yFq0lagE1`(Qu z@Ce{ufDP3O*7j{yK{YmcNe-OzOaXjWxr9QX=EO}s!1nIJQ4_N?5l5gft)d6Rc=uU< zjYC5R;95JgT@rSIY}s|UIrLkucwb}8$}s>g6Ex5J0L*Id)^^;dw%m=3QTE>ALfnAk zb0gzqm~_G0m*dVgn=oo3WhE#-O~El?RPC$zuGOTJVxL6ax&kwjCXJ4uuWUiB(8~hA z->oxdp$2g`4qmVq_MJN$CGyT|70m@ZJqL}2$F9)hr-*&wdLQ~(nMUH%$w9+3PdCC&VlbTM&P9g<1SRz0{`}*FCiHKPB`u;y!o7GA<0K1mE)KUO^2Ws_O6xZ-Ettc zf8Fig@1%dOC50lA#MaSW_EnMt=X3N>%ZwN~{Q9;5i*~= zBz4N5IWIw*aR$jh0AtIWS61=MJMTw@k!Qd(gmxBIs^kn8nnlO)Kx*H8>w?hwpd7%e zU?D}GGSMNX@cZ1}8Q6dRd@P*Tg$MV1#1L@nDKn!QK zU{uzYIeI=M)hl;JIWD?EUSMF3Ki#wvH+<<9WR+1|@S)e@ki)vf4B40jVGyEPA#c9` zkA@T}wVFsTWva!|zg*F&g)TW|XU8^NSc@kpcUPi#BD+f#!Rbt+sj`|EVRK%<&u_gQ zqcrzr+Kk0((cIDT*{OqLS>}rD6sSTtjLoA;-Ie(wM#jF-Aej=~qo*YEkU!J*i-}yj z7Ql5wuB@{FDPDNUzWDp+?}KjX40Rp9kyTfB5*pgy+!89Z^9XM;#+>9nI3B=R#AGpZ z${ud$G#-My5o=;=bj8ysL2r#*Z^_bHde6#X;J1ZG#C3Lc(s_o7vjj<9 zHLaaJ6M>s=T(n2TFOumD&8vGpJ1&dJ;t03@aV5U;U%x{!ui+Vy0{9)vN&?_YBYY=%8vw4kz=;94$^q;1SK|zK zG{AMBE_JKu+z{gt*JF_NX?U!W0EL ze=5b?6n44Hd9)3GnHUegz|a6`b*!m*TY3p9Vi1ZtQj#nF+m+`SpwiYo{fxMOO_t z8GW*7%7u#oL#H)W+njJMo|q26Qyc6ABJrTMcU7;5hc}Jl_Qgvu!WQvD30b21*r@>E z`q~X@xrZg|`b4i^He*68AmKpWqKbisIpqi*dp{Zg-sZEDlWLKa^N{6Ux>0eWc2zdx zlCw|1zGZD3;=WngT1^0_Ir=0-;BPR-G%$L61Wr>2nmbJG!#)K*A{U9Z-U$C$($yA^ z8Iacv@au=x;WzgzM&30WF%`_JRk1*#*CLC1lE$DRs^x8ueF%C6j&*18>rx5!Uu;Z5 zx*;2CG$Np|4d1c2oLHGtT0Zf`n|ehe@?Kt)8IvX?W?!q&%gdN_6!U@@b=eX!Jhr_%?9bxlmtwYN|fKq-gf#I+xw!Y27qfE z-|)S(ZU5?ul))FeCs%BPB6=m2@|~~Tj$3}Y7+zAxMVGt*2kc)!wKk0I?gHX^6=_mO zp%@@e$Q7qXD8I{jYjVY-o{Boz?hF7v{yp-(q%lk876H6~yI1w$zLjfHV`Ljd$TQO6 zrbYy=j46Xkl4Hr*O~`0I%BB$0 z>=-@;f^&ANh&i*AVLBJ88VTO zv;q#;$fyJX^>13RRU~Np(~8(W$Zu;atv+@mPA%HnD2;&(gd}E^%p;josnn1f?)Z)G z{6A~&bH4ArHc)OiA3wlg zhf2GAe>dOAer%?PJ*Jb&X_OxCD(-G?WgZktt* zLoR8!5z1Vvm7-po!0or~!I%H!8;If#KKa3OaQ@j_;1%=my}nq|lIG}322YN-Q6mP@ zt(G~B_RI2O`^b)wlQO#CsI-TsWaVy!9eoI4+52sg2#sq>>#yy9l~f_D;npYj;PHLa$SHOv zxC?tsybeeI`wN_C3|jpRPw$%n!kX1-sa}~9V~rY`r1Mrax|e@L1m%G7 zqK^xXUx)Wzcm{a<6O5})xM~UQAe?1?fLUYA0+Pvd`k`f6{xg7gEc-29j3*8t6V1aM zTDchEB2G+g@7Oc=>UHZaIWsHo>HcGofx9N4 zy_(7yXG!idMdx&F1HK4Sc}S_XQnI71)HjpH81aGQH?GBrTQV*o%Pjusj$tHtTp+Q9C6=C^{l^$We`x<@~&) z0=VFjLtSeLF5(Hw^NJ1LNEQb#ua^dx+6jFASN;sO)W=)TI~(u$z^hS^AQy7_LWj7t z{MLr9QtXCR&+vM!0E1f2MPKdb3>Z+hc3hCLsOfXhui@HkJXiq#H2}Z4te1b0o@A@M!MkPlTetu& z*Ve)(WSv~|y=QUV{g0zx8%OTf5OEBaI@q>hDM7$tXO+xU$}zWvg&bn-*lg2h0fb_M zxaAaDF)M8vDsHWrv<3-1a>!ZcYvdVSeh913Nn2g-BU510+Ht|jH&2crBqS44Z-plo zDS#9B@_)Y%x8Hg$ z_)zQb=v)DXPdpj--@ShtbNy5XdUUoVp8oEm|K>q&EQm1+0q`ZYrSZJ^L<1QMZbXPa5D_$ZlcnT)fA~@iFHyT!o#F?ZzukAHy&F z;=2(=2?Eh-A-jjiopm*r4QDr<9EypZBz^e?@ap~`G{PVHpGsa}$HO%Puj6lT{4V-I zLv(-0*2x9K)vD*{u~6*0Q%a#U*zxQ>^m2Z7-}b%ip~l%OoRxeHUcZCMtb>pJ$i+BwEl{^th}TsH*ai>|tHfoNzrZEN7*f3lKL-oo4Nw*I zCHy1HM?`BZDcMsKV%MhQ>6>y8!8iEY&5z)YeJymurd&6NS;;JoWK-H`RIw_9C{k*n zqbX^ORnDo)z}e`c=cN7^8So*KLG(G&OgiA)5u(Rn4;M|)#dr*!WZcw8Q5IaTCi7Zl z*%O|+#mu%jqF<(cnIt=Q>t>w1Wg8}Q4yb$?bNdRMb?PSk++}BCZT$d{cV+CI@CY++ zsoZkvwWw%SO1%_T0ixKpyc>M<1Nbm_+pBLgLS8`iLSzQ62b3H99yYs!q=DTJ6!^W* z|Ebureei>C$6GHx2EI2dOd+3gpoVQI8z|()=*T`y3`6a7`Q5TN;qos0Dm}~Pp8`GF zB0^Y`l>pA2HJz0B#$6AgUHYhV!kF6l&Meqk2(HpcTH?#-ePQsX9LCeTpOw!=Vt^Q( z7+MS}>x=p)&3Yulax!~N1;JGa;7UAU3zM5wY0I@D!)V^e+g@`je&nnz0;5<(B|Cv^ zH~Gpk@DXFog4le}RrpeumSw5Li>L{+3N1-yOyr5d3k4E*cx)E<>#J@;cXU1GX}Vx? zxtTH>C26$=Z{o|5D)mS6y*C8X=SAc=wksQIa1MgRaH07*naR9lbhP7e+i4kGbLvY&_8H`iXnG+^coZu#cF zAn4}!%+LNfUUTd$>ct+RAMy|)JBJ1mQBaqIF6+hcLl35I5T}V)t}WNs@TdoHEsb>3 zOEu$;QH4~r5K{eeDR2ivCw!!bAZwtW82sa3-HofhekaBn0Y3Nn4`9uj7>!8AZPn35 zx4bqkE&GH4ygJ~s#K`lKc(?>`8%wGIT=tLP%IY)uY&XT#_dkxF2?ft3&Z`030T9c~ z09JSvE%~c9Ksp#hlU=*Fu*F%KIyba(% zk)e?%c;m@iaM@c$|;xSGwp<5;PP(%^6zoE3nQQGB;_B>T66z4F;D5F;tLV?^iyqqrRd zzD|+JJOVs4GoUs-k9WQCl~|WOj%IoQ0el$_Vs0Q#C1rrn)KI5!Ly;l&`{Mn?8I|Sc zk4HOztBim|@8MXq1YAAB^~Y+>$b_a1LZ&6e(P8M33K~fc;y*m_|z}{ zC_L(-7aeH=4_lYK_L_l{)uRTr%e{I>c1s-2t1k}Vyq21Q+jcPZwM&C1_Rrv!C-xxm zIRv9BmYiA^s-C_6hx2}`{TN3dxe?V+i$V$B zB}JwR;^Jyjz^q(~Ziwz{SH=)}l5BW8>lOC!fLnd*+ab97E3}11A?;*8EWq;GW3c?$|elc9Ph>2V2>` zLST6&O~i?2Bng^S(K3+b7+fpMz}d$lBa9SfFCg(Cm$<!Z`@qSI#<8zCVpgqblR6Je*QMz~BmvM?wZ zz;#TYP>bT>O8aMtIxzQ@48JTk zPTq>OMH}lWM%9~_!$Oo5^F*N<4lGgkr6RDi)Ej*C19+7UVwoZWagch{*FaR(CEM0= z+ch54!p>V_h_;;_tBX>+;yzb#Qf9pLMpXehLi*Z6JavD(f&R!ilrOqQeJ8%#7J>1}a;3d58cII|=NWh`~^+vV__08Z#q3TcDMcn-h+;fo}I3sO6* z#qGhj?89T!7()@&1wYT5h?Qk|J%9_A^Bs@;bBJeg!&;qP(oIMM^tJo?-Dldk;={i2gAf zpURJn*_aGNm^?+EWM~GX@OmArDduqIrco*5#)~eR6l{{R-&O?nwb=z&?$1jifLrFj zX4zzf@Ooc4 zixpO2)=fEr#n|b~xru2%drmge0M_HMizhnZ-7vs4-@O<6k`Sp^lg!l$5L?AfUW}uM zfirPx#VMZNKP~uoHGs!-D~Q^ZGT`Er$)nA&fGZ$+sp+ zDSYgonZxwl98$hV;H$uiY66+YsKTBGY6L#3DoR~INP*g!%boqZQ`hR;!&4|)0v~F!m>moFqo_}BL@(RrRlO9fA zKaL3=CjB0QtSbhu%6d`ui?l>7AKfui1pjxMFE(Q9;i7abw|T8VfEpXizf%uVlfIG^b&%`E|mNNr5Aryw# zRCJMa0Lc+chi&|WU$6z2O&;QYV=Ha4#Mn;)b%u03GdWwIweg1^x(Fl8BYYXDvzfO} z7c4Uae~U4Ort{DFdBN3EmgPPG8&(OqJUr)cRv?F;CmJv+iV{SL_+n@Ry1ZjaExb#H4?|pAUnzdnkX7%duqE%HO z?TBgs7*Z8oFc?BLLpF=u72;~6hm8BNV3~VB<+a@-7H(5z)(n3ZimDw^13>0 zY>F#MHHbv^5PQ9Szm5l{JGlFaoyamP&rHu%`P6D9D82Y)sxiv_vm^m#u8PI$;mUO_ z$pppRLJx77OV;nhM?kJOXD^tjcs`!ku@i+CDt(Y&PXf74U{a%d-NYE`fkBogvbKZ( zK*I;Y#9cxr{K%nDoMh>GSP#OrO%nqzVG23)Bp|`W1cq#A1Z+VHGmHu>43c4*B_kZ15y?E7*<(ew9&xCNK+lG>Gi>C<9uQSpj?o08Z>M#uEY%ctm-(f{*8g3;|^X*`*=s z+e3<(k4{z!Ou~bUN?msFf*FZ+*i}tVemG@HTQTGqFJf##59gn{4QrA)H1i(qf)Lh1 zIe3CF1kw~CH%Ls2xJW363=*8^lmIRnHZ`_2U=vg3p%Vm6k?Jjzu2vCY1D#?c9@sI4 z&;7T*LA&YWv%mid)JX)Yb>LH!gb9^}gQV#zBKy>B;d@w93wgg`W~6g7nrBr|+XY$C z!ZkDuq;5i1LaK#AR8g`(?vrxLfvGxzIKa){n8x4!kH5!cJ;i4({|HWbMH4yZw9&`G zC@IzmLpiuh^SR+vt6Pza18(K_5*!qgke>zp(4ln0!tYakJy!u8JOe%`#j$#>FvvM` z1M21pEXM&av4TZEXyWE)4&ag9Q!s2Q@wq+?>v%>}FUa;~mL0%tA|kyfg&qjoFv!tm zo@(n_mkJ>a|c$S?fL`t~Zix^CUImYq@#DdeKV>N#&Cpo5@JFOi%JRUJd)_=CF5u z2B{2-##z*q1|C9fP zbh3fVzwmQdw~d>zCC_tiDdHwn=t0HNmsB$h&I&<#K52qEOm5JRn)v1ek7L(-pY1?>MOG|?|BAr6+ALqpN_pJ!$t8eG zb5wM)xquWpBq5NWl1Yx}Z?ktHoP`p89^>?_oABi0k7M_23+>WFmuB7>dr@`ye4#NI zZ#JYdF~Zoq)6kff?}svNC+5~~(U0XR7WEUQdeW4em;k?JC9*yFN$RA|J0onDFX z^A_HE#tFFW_1h!^SEk%>P*3yj>bgCw2>Fx77$(vO{W(+sr@_S3VZF_Z`5;-l+|*p+ ziayR`jk>=trKitn2T3`St3q`Y4{lJcUt=vC5orw}7%?2jMM$o9&ZE&$X z;L@PgNw9Zn8hxIxVsVyX)7mxIGBF9CjFcqRQ=d3HGjMy%6Q+;=WEV-CWN3F|v^qU> z;uP#S_y9LIB5j=cH7k~PN zt3V-@cmD86__24tUW^{nw2MH7HmL5zyEDwH2M~yzN6_uAn7jaKQU)++aP3)-#OEZ? zRg7Oht2{)i$Km(VN}>YbxZqt8UUQEgLMuEp^tS?8*Z@w8G-jQCP)bvry_Jqv$N#?l zUd-ekd_zM5K2d=H(!2;EIUWAxYHrR2TO>{xlwbYL`gM@-T?PIvS0JWXZw+vwJD`bW)o8Q1-vwmjl5$ z>zpHyW%W=TL`hXOB(NkfOAsMu!eIjVSs!CX2OoaNh4}uB9_sFlvuC=f@#-B|>LA!U zV+_5Dmma|7?aGqERs#>V<=nJYe~u{pX+w$Vb*}{O+}^_fx%++*;h|qSHw-CJa-W0- zO4(LV0=V*C-KWx1S2m1f89bpKa;fL9gD!aUxya*~Y!WVOmUu|ur5qYIZ(}1yGGrrxkYZL`2-EF0W;;C@PKc?=OpKhOdJZ}hjGS3)swk@U z)D#4fO>s9M#3G%6*NSp+(U~O1+Q>((GmY179>J?Nj-lS4MU=%dmCCY{vbBUcXnw(< zBVBvhJe+2u1g%~)(R1Oy3hvF}hys3CM`~(lWgBt(!vTK(D_0tzM>?fWmde~S#EZNPT8v~!Oc;Knp& z$jJ|8)zem26|xr!nk0K@lmY(o5AVg@H{XY5*u`fq|0uQ|6CjFGG5zqRA)*tRwlh+} zvt1U+&&>~MSuyUh0zp_u8y6G?NXjs)mbg9GG}dHckZ}(IJ-ciNdH2H1ei-#N7!5Oa z3m#aDGzM@W%{V+3VJZXu>CXGnriGeZe;y!-S`!pHD5IT-<^8z8=rVBKi(Fe|z%W4& zPbFu!Ar)7?Jyw>p^W#fZsW51U9$ zD1&Xp!)5G?eWya5m4r0F#KBeC>AHBqyt#T|zio`U6(cM=G17`bkv_#icoVBMF}f0xMZ`U~jlm%g8Tf z0AJT=AYv(+DW)ikQP^$@^Kd~5%}_X_mT8h(8!w5BK1x48tJlYTFUDM_FJ6BM87};v z1asVT=ndISb#u z{{P_n&OQ?tT>NI7a>f|F0n{jf%n_gEvSzCckj%){?~-LcgUG^BdFO?>5HYU63ijR& z@#&$c7!RZXG=WYK)j4EE(+f5yL%Fv>UPsXae&f@Bj$}H+X(w&L<(Iz$S>8t&DeGWJ zzN=>1ZpRLx3C+NnvGW+G_NdCSmh3H5f}qQ)_0GAUVb)w_dok5J(Xu?Echc-1izc>fzt#i-P%JiIOR#=Rj^%F0M%cD}m@ zJn+;3JoMx<*ge&f3ekvexHE9Ew}rh8dA@~Js@K+DO4UK0!1tdrX$>8QMH*LuRE`e%I($K`|6q*yuPY7UCjxl#2!-NhzN~Imj>o5d4Lf?k zSH5v8=EDZcsD>b=jROO?YGKoplAUu6;HtsBmLHBQ)ww^hHjVVpeUe&pY_R6OP5kq=SjF zk0<~-tZD*6GAckXoO8?Ka2rkn{t6F}HR zoW`g%d}LW$bVU3pKx$%aIdMJS_Re#0_8XgGEZ^sK4vD>!Yn+i#Abkl9PPU8|Q(+B8 z)gYjPRtvM&L9uG(Q3v&u^)V$5%>zvu+9E#2DuBJ{2zgo}Dm^@S+iraMi{C;m_i@=} z=i$5yPKF<)h~o}Ck9d$%pJzSJ5q>w`uN8}C=REC|sh|z9p<1H#F4Kf;ka26>ZYKjQ zbfSkuwK*wHFoQ#CVZQEyr2e*=pIM-X5CESqY?7Mb!Ys0QD3E1x?^Dm<-n}#E_%(6i zp|o-?RT}#uibXG1ig@tZZ0SI@mnJq!&rS4xE03+G0>Yu9_iqaZY<3>T;{D!rVvG0M^-kFnsMB8 z_hY!?JNIDE{u**jA}b?=wJ~hod_1;4wH-CTz^h+*3NF3qMBIDNKHPrS-I(pPkoXz0 zFvf;sNAc#1UxzncbOLGX*_0V>NEvKf;N zj}~3GkLMgffI=rcw2whH1n(>70H`dNHSrh!<#yb2(}P$yk>NK!_c7E)JBT83$QMs~ zQYYMI+5$OowBJb~IEQ<#IqUGVz}3A65cX2dD^M%jIChPX zpLxf*!nYpfV{GChSH{R3wEUG^n(A?Vh%0xCG3G6Yy1IviP;3DI6o4-t>cw8ne^*N* zPXt^3=&F0Mt7niH%E@vhm>qQ9+(=Gl$)Jt;;|-gA2m7>DjC`2sb1@F&B*EOWQ8G|sXQW0~|ZVM-k1C3x$xV_1(ae3M8s z%k#+8p>T{nD2YvaBk1OnX!XW$^KIL4({~@m(^GAj`UE<;hsM|_&N%Z_oUrXg%pHhv z{gqc^%un(0kNjJ#A7`lvbUFpL@7jl(@4OFB?Kyxr50D22w66UA3txk`zVj8B*hKaY z;Md8*=}AWJ?Cw%x(7YC$tYrmcRQ^|_c3Dglg0fYPZWPVPBnUbcL&=DlO&NF$!~zMh z`NhkqSv8x*em_KiH}E^3{cE)McX82$XW_D+egm@N0DR&bI6!`xB>iRRv?FZ#~1V8d1-ha?v8=~e$AaYz|AOb z;yf|?I-tYB1F=5RDX8&AP2qtB%mjB$-KD5p65DhfelH!bSARXlpk1lu0=qU$OKA$S zL?3O|Fw&@_9tP4{6-i6cHPN^$8HSsLbaz*9NvBt$8)=Kug807*naRQ%ZcuyI_ODxMdi8<$AEI;Q7K+<5E#c;JyIC5X=@v+&1KoO#a4 zc)KCR#0K)VW&nrCU zuz98034Fr6lQGd@ML?#9hpgyftc-EdDckVYS8WxHS%$|d;M3rs9@Mk?T7%GDEoI~s z;si5cMylQbdlTU9$M@m(2Oq_BH6dzYl2)wl`8mQC|4sonnl6;!xN3umZSUAU6Ow|4=XZV*I<65D_Tho}F{} zhdaNAmOp}kmy(&eQJyffNMUeLCKe?o>Kv`r;gsP(NcB*3jicvY76}FpWwFqNmTuZm za@o2(lbE|KMvh~tVAg28hRLxpjE&TVV_xQJrtI=WH&7t3i#2g@Ah~RImYi(ncoEXf zV7lGIRKJJmZciWpeL#Z07RkhAB21@Lhq$m?F;;O-Xk>H^@`aY?$31K`UA$@A8k|<| zV=V3g84td3B>pBm^wd1Q@tu3{@RL)>(LkIR$io6Bzw#8E_==M-Iyo-bF$={!k40l- zW^W(Yee>HG$y0ptV;{t(F+#yT1at=v$UFDZPjV3gn`x)G^S+01_x+Dyx|JYfXFoDn zf7}Gl|ADh{&IM})8>K!~&O?9@P_Fnjo1Gci6M+UR(V!vpWSiKE0`vP@E|8sIbeW|) zh-Irw0MYwN2rDv?c!*N}?GHbH9kxHR6KmF#`0Qstgl4maAnXYw5|VwB@DQ=CJ&yYM zLL0%}-(gItO#Us<8F3WIO8zU2aEH(8Ivt9W+251VQE>Q62gb;O7QDDD5Elmf=en4h z?_l4|G-g`V6Y-?VOHxuE6}l6ykv%zNzYHoE$BJ3mP9FsD!F9LHr;?HvydLcJD7}g~ z^BC>Q-gX{N7!&!j0YK$Ggs$ThKM5~ERwSDkPSj$Na+Y5Xj1DkCkKs6=W}C+}yKGvz-hYwIAi;nDs)SMhnp zs}?_gDFOWF0Q}*~ZrkcSn@uMMWuBZ@-1!7Q427l65}(aPp3=r(q*)i9`B<}w znoL%v5|rfeEY%2u*b!fsMKLQ>1dXp4!Vhbh?Y8mk%nas|6s@E{pYWT{B2Eia8H7<% zwPlk?cM!(UKn{8ojY~%1rSsSt#5iyB7>)^QF#RTO``5>D<;@Ra=X8lQT8Ca5pgB5$ z6HncSlg~ItAP$c+_?DT&Lx!KP`7pgZ z`F*?wI(^{&2lnFDJ08T|nK|T9fua#3nk;bfkDQBh-*y6PRM~7{MD2C;rxZqxQORD( zJY}R>VJQ2>EBYv^NT|dw#xy$+Bu+kj9Tf``M;~$rMjEa$%_ZfQ4F-1fznx|dN4ZJC zbW~Ih z`0BcnhR#NcU$4$ScG?mZ-r0^8@E#)H>q06|PrHG3JHL z9=#uWP*l?L=ZS!}?KMD6ov(m$qlS%9?m-FM4C;JapKKKB>@zs)U=-DeHN4na06F|v znQ2@(3>M)hj4@w2oU6Q)0KSox#^Jo^k$#MrCvb5B`17moz~lW4X*dd#P*a0L0qVq} zqEc#G#%yb%K{GKe2VGD*p6QXP`r7#qnau#gD`mm$KlH3!I4v8-X$k&#a6`pFvQLNHeAgVnqEmUQr)G>&Y41eDx#f_aYHCq8>_PJi_T`o{p1F zJyl9t84ij((SM+pOCzcaERYqk;KRFi%;Dy1Z$y;F`1ob-!*T0Fgoe;ZDtt)Z1u>Nn zyoq*L3_2`8eZ)EN=o7nf>z()GsXbH3gAi!|_@f@qzw`|_|82)%WDO8-_^m9E6n*%F zvN^V#Q<>2QajX4Zt&Fr)DFBxSNgniq!z$ld4}ROs^h2p8e5U?A;L87f7q0uK$Hf@> zS3dJDoOp5_UeJZ{Qqi2&$yBOB5Lq99fj#G4#98+^`%(lCjnrop?XJ@V-U;8LzopA1(v_XmU z98O}(SZwDlCU0rBT6MZ~av_$yvOVs?j(#UcOVlxX?iU|%n!yX{29%)|w{YGoPsF9K z+JsugaK&9ucP)pk8+Ujw4BQTiauP%G-eg`mNU_4`cLxLmwryAFy>z5j%hZxz4yOEr zg~3^RT&lanH72YYe&s_;p=>h7P>1S}KZhN_<%BECuK{@1Az$?fKY-VOA&BBtfBLnX za3BZ~do_4Dbxw%eYJ*3b!EzEZcx9Mm0C!TPgWIw659=sgLtjaE88xSHa!^;S(-lFwRwkM{sP#v)Lvi#vWv}a0B8Xz=2L5 zyQVtmBpk}H^eL0-K#n|@S*2zOdC^Cs-T=`O20_#cG-xq5pW?xr9>&bmCCa3ZbsN{? zv{#;hV~(GIUn6ZZlT4R`KeDgIUzGR;gAWhQR2nt=_w*$Lucv){;v?_J*0mg-=_-|q zvb(8{GxPp9*CL<#=2TWJfF#$Fe#f2+x83y+?tkP7^oj(gULp(Hc+Hzm#s!zW0jHiZ zf|z)&N7>*^CM%hZ3j`&>M-3dDnw@S+3zG;9Pvu29k*KUBHA9v_$10E7EGCe~R5lyp z3!nK0=63gR^6{g1{p*jzrEmW}z;6RmS@4y4kdcn&=!2SyaZp8rizW|(M@yzJdARLy zxGb7HcqWE`f1{Vml3@QSbF<05@OW!>ULym)HBru8iUKAMV z&*QQmdNWQKVM~O^m5YGxlT@nd=k%=xUDpL-%X% zwFa`bJf?hk6%+->^+U|HQ#?D}LOa#rpM*myl4+`eglHz0K*X%K0Afy&)i~arNN3$I zL!@&#c0I5QXPtUB){U=6LQZ>~ee_K5b!y3w;zvOtKd2)J>Y}yIpyacz%p>f7CdN%y z-GH$?#?OEBz1TECRzXYI%)WY&_Br(#gwph50Fh0@hEkGXWON+uo^2%g5oTKn?z;DT z`0kw#ppyf=AV3=AIPugicd%U0rPRf#)g*J3!JRn9h#A9<`+?v4^{>F|H89#J@vFb_Uaa4oA*%P0=Lw38%_}mY zZ1!!nP&9x`zBlZ>Sgm*|&#hITFpYVC8Uea7(C(#T9MbA^<$vu?7ri9aL(6U{NmT5_ zvBoY-os%h9g=tvviBX7!WrX2GZ5}qg11s*vCMX+w6e$x0%%Lc+>;G8G=mq0OOW)ZQ z#z-ZAij|>-jQX684Qt4f0wYC%lbR8J;s;I#ZNefM;88xk%d_f(f{R>8=J#SDtB4Tz@zUulq~~dh9P{Vv>uPi(<4^ z!u}wPw$&TFDqrUi>IfQ+Z;!rQ~*N^ zt<`dvT8Jzs^@%C8^5(-b!dPBIGq0hRbDY|fgM!Q!RSRU++(W%lN0L$*E=L&EB@xNe z9wM)aeLMQN>038oG*9q}kGuz4CwV~i<#X`9C|ia~c&rvk2ULiOuOT8qDLLSzw)sdX zt1E0GVzUOf-}ek|yYF%AnVmt(0h%a9bFGi_-u8N&d+{q!AD4-5k;A2Ng9K`O-KB&b zh$&g89$D1X{BR9yWi9b@5@ui}B;g_s(I`Uv^WQv(Yrl3M!qVUsuN=cKUH%Rv`7DAU zMHq}CA-7yAfZ_C~*36F5$ir53Ww=&*{TS_D53OE|R=1B{l1Wyrm57=INP}8Td$rjn z?(mK}=yW-Bb84P1G83xZEeNq?q40ANj$>8F3P_9@_;)58%s}N3W)s-;c(h^}3S&7o z{gT7RV54cTL7zXIh#2a-$RIr%m!!z1r8L6NJ#i~8IeU|3pYX6(ismqY9|YrGzyMwh zf~zmB*sHl88Ih()y#1Y=366y#l6LZr$|dI~aCR~(In4yj38;wDXeC8-4c1}n`FSyv z{l*wV)rbAFtG!(D}5{?=*omGZuN-!4&56cWJ8sQoVRpChG7p3m>6*fMSXVdyLcbmVqAYtlg+b z!d@948&OVbny}6gNQfPJSyIx0A$OIsRX%#9hliiq0lz+ixpr3tcj#7c?cIc_Asa~n z1)umQUy0>9nH9N@G1J6o*^v1Z1`d|;D(T7RSd~5Ljmj(Nh9rfm2ytLn4>x@4dW@7M zKKYS%W6L8ci@@5Gw_8x5j&w^ueA$wLn53LSh6c^QNsCLCUkYzOZ+& zb@<#Xt3Z#wxBJ)OD-QF0_d9zv2hVwdPyKtwm|tAV#a&JSKO4YZOL>#kek`{&{avno zY#KM*_c-F9AzgJT`lNhu<&JW0nSGN5!g7%ku^g_kT(imn?3{6i9NpFa+=Ih@(8gbQ z`Q5Lbotw_xE9N{xt@80P(JLo-P0v3DQfiq~=Y<&~n}KB*p`8>$$9r`9P6UlH%(XlE zZ^C>~SxuJK8gw=5mqSc4HV=O8W7KP4w5%b>n60QioMOt=%t?zwHvmJp$15W2-_^nO zS6+{10eteK@5a_~4iS;ArpsLqs^$J@Fc%G$Ai&dm`ndj+ zhA_v!d&fBfpXiLmVX-)t{rQga6JKkLxqB&}VOjgAEXx}KoV%1aTHVK%Xv5(8C+G3) zyB|hIwK1n$Ep#M%3c4~=Ajv|SGa)s<>x5FQ?yptw8;ZEE?k7F?tGOLD%%(J$Iygm} zC(O7d>{`Bfy%u4lUc;7k>yY+3pg#in(4gzQ3~G>FK!%Qwg35BO9-f_=MH$pEGv88I zabkEbfLl!%ml3Nt7MT|w>SYaMs3GD|53^6{pj#Tg|P{z1fJ3{?*0erbvnJ|tF;7}8$%#ia&`XLU?_VL}jAHjF;eH87K6P}zVOmXZf z>v8FiyaBI#U0uxTb3c)0t5iWen1sJgGir4#XZ#jEyG&+jMy-;?f$EX-*C{Zw7x?2p z_$J23n%H(yh&Agdl0?Wyhh?Nj(djOc1kn6i6{TZ4t}PInJ17Q0R+A3>IauV?!}jI- zqdfE@8mUT$o?22jxXQu|Gc04CS%NbOZ{HU4d5RJ z@Rg;$+3GxA@hs6md14mV-}g8Yzb?=LF>ih$%_x=cEt^CHkyQMN(x+_1v5_c2TO?$) zfyV!SaW=;=fLFJv!y45wh?uvU5UX~J1^{mPk$N2))~&%vEkr?~A<=7~1qfwbiT_)l z%%G0l2c|LI>LMvU^wM0W+uU@S!{l6`;3kqW{=!F81Zb8K8g#2+V~*5BT3!tXO*AO+ z%ozr7q7^ml-_^tQSAGZ0GQ}r9`aT>p$^hOKl{mrvR}g=An3TDPAYhQ}3pJ5bhnyJg zrxD`J;O+;eaLeuYW2)7LKLT_xg*C@Uc=IJ^;f)ubfjS3^LI{R$-Mo;COAQ%1&aRJl zhPbm42x@k|gXx)hwB~!5ooXZQ`ltmP1yA;Zc~L7Y$_PO~nI+ZJQQd5{>>w;4Mg?*X z)>J&nQU@8Q2a}lg+UQZ|F4Q6j#0LHsXRWTzuC2bxknX47vHI-@myuH1G#SQ|8GP(V z&&4L6!#%|6T{C#~KhsO#6@SVY^XE(b9Loyevhd1sKY;a1eZ!SMUT->OW3PF13O9al zJNkxHe`Zr`=CS-D!y}hQmhMocx;cBaAW&68Dy<0|o~zrAWV@CsH29p0w3HWQ%FFyR z&rip4Z5gF8$p*Ge71!jGYoFzaf&l9#C$MIG6kd^vyNNhRWy-AZqnZS4X5UZk*(b8J zoWkoSY<%i%cj8$C*;{GkQA@^$pLwVwLes0GRzxt?d{eVVDS8#c5lH~&oWcNJ$NpV0 zuK(7xXrhl#e)Rn|fcLbiEQigqmz`w8)a@XC%=Zt8V~ZrLHm^CxT;y7bJhEdNH{5XgiRWm2npq=iPB+S$Vq!q}i8*l+U@?r7oL_dJRgBE+Qz zWWo)B#W@RcU}pr@v0w>UqI+B*41GjFs2phvB?$9Ovfj#;aRI!-E?G$c(k-|MLaCk> z3`?REr{)b}{U%gE&C>X9#Pai$-R}Zx#>cRE-6U%4o>PlM#IiUHq?9y5Dcu}+YS*)f z3r{TD`fQwu&bQX36cKWhr4qpDypkJ42+=@IGI9QHIFO=XfM%4IDIwRF0#OX$39i42 z0lX_2_|_2)4KaW(tUQ*pc6hXrA{j(%NILx&brTZNAqr8M0C7^ntBuKbdtz4~x83;w zzW3-3wDUfaW*!8ZP;vbFumOI@)O;`)8-I=h-Rj+uKG_)IrRJFpC^Igh4z? z5R}5~sn?t6c2s6H;5w6}K@VVAhn6-fg%sDHyoLw?TXTv^+p8kQFzn5^;H}rJx@M|@ zU;eE!+BbakvbXkfZp&dmN2*8x`L&s8c{BPQt&}bg=|zSZ z9QJ#@3?BG9#+b{O^EsD&m&>v|mA<~qdD9g?rz{a0gNIwd-(LH#nDvgam~8 zMXNC`c%j$ndy2&xvp|X!keV%5=H6;b^(nPXd5&+BFc$=jWkDt32PJpY(MwrZA{^b(EQhI03v`fM;hD z-15*vxZ%P3(GPRf$34*|-*VD=gd-l3GDXyAAm^AbNG)VGuI@@?{~F8d7Hc_D$2dkW zy_FD2l1fs*3Wa|c3ZJ8jlBOt$KrHt~2W2!8NdR*_8%GITv zJr!l7+Y}PKnT3bcf)JDADmBOk8=HYwWA>^A@Jh3Fm{nQy(>AK)a2b@0#Ht1DNY3Xr<&hYXE1lo?72dEpOFzg{L2>bM+#` zSQ$wmSNvHUdy1b^d`0KX9FLk1%3cO=V&D?MiGh0>z%7Kb5)O)79XV+AAQ8$aKM7el zq)dwsqB^>iF@t3&-=DP8uJ2(E9(MIoJTr3uUR1(w0NuO=gk<5Uri#!k<;=G5hVZ9( z&2`{NhoZESBVReE$EGMoTGcokQ?}rpXB~r49?_%$ z`vH=am9xU0{}=uIy)lLZlFRy8(X}Ycl3tng%zROQc+;s=MlF=T{`TE?U@k}57>A!^ z0wHAdTNDUc8%1hu#Yn6oMmpS~0h<&(;>qF*X|2x&MhwpVMU#WU&q|tb`cgLMet`hK z@PfL|mThb~o|z!!Qf3T-IO&Dkwro(%7iN0_RnT;DuNx=W@$7!|y&Ae{fs~mzgM3H< zdlh|9ltZfw2A*0GV6=z?N(pF!t6ew=FKo=|_0%j1_rs`V$glRHH-3r|B;m zV5F#_QL@4bt@4nb~yV-NSWPU57@Q;Xi!jeb~~>Q8%1lQ#{CxC@*)> zW+e}5A0dVJGZmOc7V5x!#BH zjb+%x!9^-dC1dMS;#*}C(Gh1h9_shMB9WTr0cRNjLD`iDo+Qt<_r5*IB&PtK5&}-ihTs zZ{X2st7FPru$D|R52Gf>>5~TUy5LnTuEWZ0a=7zNF3~Q+Q_yZ7=Qo( zAOJ~3K~xo@8=f=*94LC&o3yc~H;+!4q9isQ_%bTa;706PBn|}Eu!@y-LRMvnbzQI_ zuFg328gr0`RZq&{DyI4xMGe_69RKz?R7I)L2qsT4IqGBMx^dC9VMm!m`Fx&78C~`_ zL^)F@HVJ9XwmaBAH6wqQRq2|Wi@7Ma!jSc7cd)X9G*HWcQkIK$jRf&Un7GYmUd$~! zT{FcP(5HUvOdj+lvSB_(^9DjH>c0KV z{u#`4`=WFwwpC6W#cD)X^_4l585W@g@DYyIi_e+VA*$f#0=Q&@)Ymph5)X6xy14C{ zJK=R_@gG0&E{sKNJNqJIOV0F40tm&X*tE>N5=m$c(Dg3o2LaZ(HO-s zo7N)=`Y5ulQ;LCSm>AHFDHk!NAmrdtAs(MJ)9u75cJ19KzKwFQ*Z{r|0?~tS=-{;Q zAarYitDQn%4C2hft3<@3n}I9)hB&<_gIWPClcflgF5dFWlkjg|wb_o&+s|#29O~AH z4Dmo-Yo$Bss6PL&O&eb5Q?5z?w^{fu09%jzCE;j!218fz(x6K$Hw6Cr>O1jhJ3%jK z&;?i;QK~-Y1pL_ri6xK=JxoS+-Qpi+)Y{!wIw7%f{wYD+s<(0D1fp1W@C@=$+4pK( z9~Wpy2@#xLR1a3CPP0^Mh#gUgDKmAWUn)Qwp7eP<-+x$8eHVMOXWifr8>1tj*Q@#O=~GD1{56d38i67csuX| zwF46kX~H^Ou93hfvz;FH?4MG5FERRc-I9gG)4^{mP0Z@Ll7MfUq72}yRt1h(FloH} z3TS0(*m}U)=A{fR86UMWMWa85kN((&I5q_8t{AfLJ*zEd;M$uQ&T_8ovmCW&?>5F9 zvl{QdngN_cJsj>i!asI8kr=RKE=r?)WTwDZZu~CV!3a#Q9BG!Wf)kfDJB-nh@|7bh z%)qQSk2Qx~1dG_Nkc{A4GX?pR5DP~hg_@|B&jruJ{o+F~XYn%}bn*PJq==z<9LgkQ zp$#$B;MYkt9n)r+PdJ0LHBM=&k|E1$GI*$$(l1M)W|d?E>KBpVtxYDKn4~KW4G)^A zi_C09T@=eY(Ev`qi#q*qP(`*`>0$rQ4sN>Qel+tKmw)_HtR2ln=arY0vCz5I9PTx< zNdgkzL%SYgcW)khdvj%2#JL;|(D>S%m4+uXcbY!P7uF#zE8|Nl zX5;~D#+qnGJ{mR73Fu+K&&}yiX3PiXJF@O%{aEN(4*0@HK$GdRz)9P-Ao5dWaYuX- z13!Y#^_nFp%S^?zh;S~uiUZCdIl)+V~HJ-d=zB4VpB@fq+{ zw2XZYV&M$vFO>l9?zwP>$b!mCG|CvS-ZY9Id-LgNQulk{D`^R2!phNS9;_w1ly&qH zcx?{e$BWP9rOM=R*ak4W6;I8{VCP$jsI5CFF(FRPBNYx?@G;vcR$D7a*gRPJ4d#7chH5H#v z=XTEv7Tq*BTI1i(}iLA#|p7&*8ntY6Qq5@EVjLIo4>lv*Mq_xz>mMCS_Uv z3V{E7*iTr_19=CntF){ZjxnP|4?gHL@eemVh-apI$b-62seA@Ay3P0=lDvm7sv+Ze zv{f5%AHfCE0YkzrnxWADaM=tnb?c$1>=u<<)f9oHo=QBiK|`*x1a|w+&Zt-)tijin zE3~oXri45#W>g4eL~|8I3Y;29ujF+YFpJ=5ec)eY;4ss9Yh1N_6)|AKZnj;Xj1Qv+r>K8<&U#-)oxgHv_!xs6fL zr?7aiE>aCv0mb>{xehO8;8S{?Zh8x|42nrcMV8ANzy()!TF?@RZ1A=jym}b&b1Js2 z{U_HjvqL5hbr3Av{V43?8maPL3#L6(;FQyT92n_SnULkW)V2l@+uCSQV0GXgBh=6nnF{fNV+;19lvEW z*3;d{-dD;B2LT1ZGU3XLH5RjInP6nV<0(V-j*m{iFI??bKNY(=IjqQ`x4x9>aa*aD zq`~aIqrFeE_J*{;!w=femv`wsm!C@TX0YZ#*iYCz6@q_dFlZ%P-dWG7qmu@3cg$OO zV{rg?pKBnEtTawGznfl(b*6`(_`%mj1^2yN*0#{9Y$e~~C_VR=jWPe< zYQFcXX5fP`QkG8x*tVJnGW#PYi>cyZ(=rMW>>e4 z9u9-C`9QV&vubjK^IfoJ3#wF@6QX4yRjbyD7VWlFEvG52n^ZTbmife81*?_=Kr?JP zMzju97)GAsG8JXN4j6)Bs98gI%pGvHxvFxsz|^i`2JQm5(+?+>DP#LG zy07m|dO4kHIO5LP>iIIo_Rb7;CoQxigP!y*3Pe$4Ggtc^1-h~0AQHfNRV5Ed#IDM&5D6jyMkl$u+$+Y;r)w%mCe3AA8k6o&$rO-_XM6vS@qjP zw>pI70=Tp16GINy=(b9i(pHemtSexFl3+EHe!AB5B{n*VC%UDZUfd6#a=LHXz|ud*22 z=U2#k$V=B?E0IgAQuVP6`a0+^*dC(o!p&)yx6Qsa(-_!@yoNBY{euoIil+B1T>h5tp1G6%L+cw4uG2xy@$P zDM&Lz+sYM;J1le5Oo?rqH(p>w?z?{hB@Q^gqiI1yjnuAW9(3BpB?zY=T^MV6^xI>mE#Zc*SFB$~XTtIzc8Nf*+ z6wMKt&{P%6#dd;A-KPtWkA-lxt6^O;(`DzfR%`~YYMFGN4-s}|@JsJL7aQ!dRv80@ zOdQ2$SYT92jir9*qyPAi8)N=>wLiuY3E&cs%JN;p8BLwU&A=gXN!upJWwPvRVdW2Fa>gpdPTUvO1`g&XTr? zTbqNkp|Xo5Q1ja41rkDJl~HR^A{gdN za8d{@2qiFxWcp(IpiQoQd)m0>%6m~O76x#==Ijl6qD?|phR?$`G7p zeuP*;@(V4nh&vdNzT1^bx`dJ(Tqj^I43Yof$lxwlMGI$O)Cm z{nKxy+;!3hiN{xwUMr_-rCK$3XE=H52CQk;(ctS7;}+%x<$^Vn=HWpIiP<-!Ibo8S zxq0+ct1d{o9S4D=NvXk`Ri0y$Xyv7hCUM^p77ZZ*X7j4UKCIv>OMftMv$AbBoE>oW zmtyiRfb%={lUTBFHerRs3&6H?JQqnG{W9taFUOw26#q=`bp?upIbIEe9>)||SWh?0r?@*TI`2cP> zoDZ^;$G9!*mf)ai;>xy4!$fmR4Z)73^5k@ZJ05xrPd~d4sb53igh)s&^do6dNwy`; zEFBJUAzn8o%W$=1OVYNOK@j>VWE`EUblmKTvPf*8WY8v-O-n9~KXhmz)y)QZbxF`H znskiU7d@VBo@^0 z=B6RXIrA`*HZksxA)uQ(|0nxQ1Gt1NX70ARx@XrsuD$9$G|L>n{LxFWd5k6#I&=?C zM6x=n`Is^(9!qAhvp0_}dkdikL^qZGfa!EII#qY}NK)A;?D>)pyX0(p6$iwj) z*22pZ(Q0I%a+)W?S|V55(5N^=yVt{PtBp<^3+}BnH9g$i5Y7M3-g|)Cbye5GWA{^T zQ?cYKH@Vvq?gfl124iCb222PhbP`%Z68L%VPy6#H@8$6*3893L1OnvIiH#dJHpSqA zi?A)rHg1w-+3Mw%Q+9vfm~*Xj&b^XsN%vmq%Hi;dYh9hQ&)#dVJ=a`gjyXnWt{LoF zcM#pOwZtwRdU@F~?`EY_A8I6ZkulN*rqh8d=iy?s(dZ}{YEU14g59vcGf!Rjy`7H8 zaT~sF0N2h{)=tP2bKqKPs8BT7q?4l>kKlu^eYuEM@i7R^rnEDP!Yb;Th1k1dwy3?; zgnBy+#an^)^9)4==HC(hb+Q zfQO!Z4i7!G5+g~8BB-KG_jPGI_LMuz%ugIp^yspUrkhVdx0_f3swb_|6|`IQqEzP< zfjNkovoglAphuNB^>9>=M4JVf+*z=A!+&L#>U+p?wq09>1hvWoq^Y_Ish)^^*}!e` z6uVuw4{k42qQjigt5Mc~E>dcOp>||^@N595-5Md3Ix}#uPgp4YV*@y`XUXV^otuYu z!|Ks^dj3taSv9v1977e0eG@%Dl>1Q%{l;hKRYXZ9UP*W+-biAKAn)I-80 zrPc*>AsVl>(VIa^C^W@VJNmr=e5-lBgPn;x^L*G0Tmv`j3928?^C#z<%~>`hmuIk3 z=(OWHx$OIe0yuX(0d?2Kvs7ujQe@9| zU0GJuicJa%J2PB+^1WYi9Os?Wc>>cu5@lJEPWY7J$W76;bO38}L+xS5XRKQA)0co7 z!tC8#Db{_K6P#(w=AqZFm*Agcv{8crtWNFurIXx33@ z_k`?krD$OS__Rl^T^N}0A0b2GaK~|0PWnjCbAa743}spVcL0AoWfx*sV&Ns(-IS%} zb(tT6SF7WgZj2?GD^ayeBGe&Z=x0_=m}T`C@a(2hJn`IGJhx$sJow@vDFLcPP;oW8 zC>d}VcmudzfUKle9RoXyWxl$iqzpFf230GrFk&H&-^3R&TE)*hHd>NVQNmW++Lg^9 zP3Fclm#+2p?6qk}vUyW9>!q^wZr*z(Xf-}5-BQm&^PJucTzS!K^Va4cFAt=MS$FFK zu~@pGW<`n@Gk`OfXFX#5s!`l_{R60{DL(eDS4bx&BXd^qu%>L|$fp}^IxP?xnib98~RI_gpt}?G} z?G7fCPj>pT+;#w09A0LYxlHaLqaYNv5!pY4o~p=j#6JDF;_Ra_Bth9eoysqhVs2;0 zXc8`S+`TM-|G$poOs}lS?gWy`vRn$__?@0D+xmdSj2-~ac7$0zi0m0nWHdxd(ju4920IIfA+GKlM~1PvF^WwL2DyW=W`b&c0EMe8hM-ax ziBL9(I35FuZMY$`!$-!pW+yd;E-P!Rn$-+&{HZ~Oh(c9<@m;(bMeD_(vwj+sY`K3b;fZrYH2j1-z3U>#+FxvX-A z`HrbN_h~xLQpa(ofkM6Y*-rBe>waNbmX`y#dP)XN?rYB@)YC$2u~Yr$E@oykahV9_ zBrJ|@a!3gs`Z(KguLUBp9h(r;ErXl6^qOJdu_vE}8w}w$Ppm<+?P1>j`y;I87-_6U zl5Wwq?xG?A*$+%rzSJ!~acyQR1%VwgA5h9*k+Ic<^?7YrVo@{A6ZnK`%%Vjd4mn%n zH7Q(QNyu#$Ynz<9BQH7?(h9FvsjLo;4x-~4X|Xjzn` zfTcw&S!NgjN+5DPp#%o}Y? z9_{ul{KIFzgXf+r(Kj#)=U;ph&OCcxq{S%GbPVR+TZso z#?k0PIw^%yE*o(P;F{^M5yum45PCOilMk1X3I>Y->B!`Jn1M?GHyJ)Na0YPx8-Krf z)tEpiL6PEvA9y8#!5Ay!%~%tUq8++u6`3~l2&G0bPJv^3b`R9|w(5|~;HqALNLUOB z7VI|<)sQZz^Z*44Zqa!ZFF*=Uw6!;nwFEAa+*)wrZk>$&r@}EOE>FnC=zcSMoTyLI z4b283*lPAp4Bqw)Htn``U@ z>``y+aCtkNavn&!5r|z2Yfu6NXW;|CS%pS28$bK`lepoBOX2!`$T5b)j+}*8T)YT} z9kw5GMtV}^eCm>Coep$)9E=oz#zS9xB^#q5Zo2W8SaQ!Yps2z_A7;;+i_^}13A`$O zA<3A@k(ZeiMkNRnfoEH~>3Ae2pNV_A!Y%Tc%V22$?{IZ{vQF+oM1t4I;ZmTa>QvER z_QT5!Rgjc0DL9%Oo{Nd_6B)o=Y+@(owfBloyKMJv?<2ZxK&AVRse8;UO_SrsqGg;U zl7-V3RF+~hAA8SkTsABJFuC&?Cm-8M^$pop4y__ybc1r(FqNjLyDknG?8EPzdjy8) zD{2x3y94Y{H!TcmcMN8?D5ovb(Hg)fcLmcLUKcoy^USnXug|_^fzx1#Z3Z zS9t1?1V!F2T65aqMR;!IX8h#l zdr*2Ae)qi>VPpCnno)+-(`F%gU^}XOW|S>GugDPi^z$U1T?$Q*#mc@Y!u;7oB1T2s zZU!uhaxr*$eu$A~3mdnLNDDmAQ5D&{Z7-b_*|Jqkkens;fAu+CC;A5>hf1ZfPoF!8b3Z5s6MamZqm}JGQ7jec?^xse&fj zUBLy-de3&}QCXyj*b$v3@ZA9QJjU;yb1IIS;|lg|VHYzK#@(l_&c5eCAGhP4iXbwz z$M~@0IR7}chkX8{P2Zh?rjqX;WkuEQ^G zzYl%0YB=+v6Oh;1XgY21jJU{1Z=K2BG$3@4RIz_c<0fj6LMF_*Yk`OT_L+l$Y6WhQ zB4_Y29BwW`Bh5B84UbB(QtQuYW1u}XU{H*n*>*dlb_)Z$G2`yhyXh6hnvUn8+qo=ayN0i?W+n>Z@KiaEm{4S3 zgOy(tIA;EAyyc8TQ4#m2={U1Je#~j@xZK{=?Wq8MB7h}(e8_k41iCPbivDvNKk?iq ztZEiW-3WP{Va21v_{tYFn10; z5}7r!*@usXYP=v*ZH>}bHiP3xw4g+9|bD^jaqDn|ASzPxZ(2tTb3# z`QhI0FvVO$DHSzA7JE~gQ0It+$)ttXiLdc}08@S5M(NNTmd#S#P7B@>kpq4N!6gN;!Ur=2uB~`A&p1zpFj8|o_cmOnvBQg7%sWw zOq_AnB7_wWg&U*v+eouEDt=9hYcV@MC1ASJP~&G+v_}H`?3Rac*X@rWp}&|z=F1!$ zf6_4+oLh(EtM{U)3bLh{Pnwj;`)}RH^|;vIPB3hBFt;#l_- zP11MU8Sj=a+AW;#ZC%M83*ctrQ746ZDSOqc8^AShrC8OvW{ihcZAR+)aLa^Rr-+=n z`0{73#xswW7_8PYZ_XBc^bfB@SZu+)zg~*({OEpcXoW~oL*GyzE`RMgIDYXy$Xq&; zrvlBevyNSYeo#f8Q|6WUc8t)k!pUn`_v{$1`TkF^a``5}=|hqO3y)fe6HYt^L6!O| zDMBXmae@kukr|O7WBwrb!LSq5l-a1($%3K(X60)&z;^RmwJ_6wt5~QpQ}%&%BWvN* zbCi)I?muKqkju_OC9~)8Aan0D)Z@`pvf@*7CCAYV4+H2^DP9jQ;w-_&En6@;))2W@ z;zpuxPEj*I>~!DuX5bw?o5{|!Z9pTvnE4AHew!3TyBpC(O-8w6HJ3~80RO0gGT*Xo z45A}gHjT793!(5#3603Tr+Axr4isL}^CJ{iPloXa7oUNBBSL{XItmEAXkNEDj&shQ zx|%&Yj%8V%1mM0sb@99Uy&AwZi_)JiMhoD+r`CcJN`Y4h44B0(nwu;5hrjy)(uRYI z*T5^!J_2vK^cXm08ynj-TyyjN_}QJyk-K%Y(or07+yS`w@|R-%f&D1m7)jPfyi1etqvs{OE=|Fg#2?aDb><#c_*|#^DPWz;oG*Om;^g z?ad`Ezm3kgQO8h^OVi44*(}oXZw!hf$lVve=l?N_tiwhn~TptrGk00hmf>dXf(z!+HOksCh3hCv0&Z- z(gNjos$F9-_1+0S9#GlEyFVd-?^N*C_^hL6=#r|5V|?>Wfsm(9RYPXo{HfjMb_p^E z8F!5CRoYJ6UA(#%{Fp2*rd+`cTmyKwk3e={WdN^W*JX-R58W4+F4`CUMxTfd^i+l1 zqk-oIuX3l}aI)h#dkhZVKaKJb=PaQwmwYW*47se?5eB7Ea}zrdryq;83q zo_7k)Jo^aDnI9s_M;I1Si6Zeiq-F@&7wX?geA2 zAdWqLAr3$C03?JjDh^VIdKtOE5jp|Xtb!ewwu4n#_&Zs+2|9*IZB_oPnXPW0IVuHm zH%GHdV!HI24e-nN{RCO3h)3&D0|ube_NmJ z@(Gx=&j2!y0i4B6&CDf`^w`JQ0;3Jvnl-ZcXtYyg)@T;3|8v2n8!il)mtia) zL+WP8J;F6?n$q(N2#QMwsD)6rJ^dJ)qc9NeHv_n^8Q7yEO;$8O*3y}3gLkE0#bnsf z>2z7@2D|Yf&17cDxbVBZp8D<=Y$JHvBXoEGA8NlbBSOz)Cc^cO z<6JtK15CwdXT&I$WqBxo`vFmxoZ&BvfZHxlrBG!qaOZEf*}uo{)ZQ!9&Kc=u>`>+^O2SVxc#2xxaQ_xV?(PhdgXKG_2Il% zo`S`v?~ei_h{SZ5f?3SRV&RfgYSt~QaGeS~*GHTH>(({!{qNt3r4OtHFoZPqaOe?- z0fAh^#f4#mTHQ)#v)H%LC`oyAGPK+V+D;1z zgEz5r!D^XNQ^?4gP&0t@Vec|gCf;yq0ttKx;>^S;kwuOrn?mFz9*_2=Q&@xfxVUM! z%3IU4d%4}aG}$_|$887BE)zuAB#M9-O&sB;n~vY2(844Ol!SszEC0lDYxjIj;GS@; zyL1hc_>eSjQQO352?;HfN)cR`^9&Wo#T;b#z@;Zi(~fAsbJxWkpA=sAdK8>ajf)+} zSw4wjoRW{uhyX6Jqb%8e`n4&!s_8z6QQ(u-cL9lgqz-WBW(WrU=dg$<*1Tz%6r{Pd1Tkh=k# zx{JdX?}s=2&ZXFQmTm%Ezl9(o=A9r-QdGi0Br(5@_FfF)1^WB?aPO~%@y-9Z30t=0 zXvGe^N`xbhJ_08!J_>#a#A!od4a(OhNi6s}Cq_m_hwCDu6TCc|O5G#wEKsQO0YSrs z#EH@H8i?IC5@{IX5y)!c2r<*QH3QqxsEqM#QK;3RT4h~BpEU(f3SeAk7z9MOyQfgM zRqMOOmpg*FroqLQPNlVW`>*XC&wj!xNA@0}cR{hAS9rwkW2~|yG{ZKsxN38zy#$>W zc=I{?*)C0dYV^D(`*`qPNE4MfV=11^ZrOIyLVxJPYYyX*(_Vs?E~uf}LwOfBRB4^x z>jU`P9LM?kWXEwTK0jjuxC!E40PqJ>abeSXj1CJ-GeTz1?2^BG`Lk$H2ujrLC|X4$ z0cN-biY!CbtH8+y@x%Z8HSYZBy{KhPeDL>Pg)@)!;pc1Ff1jG&yc5mVARM<}RQ*mr>lEy_U^dc%<_1j!5gUkjTp!4Z@zb4%3W#hPVb`N(UP5&f zz*(Ua;@&N;ndTPKol@ww-Hr5#Bm$0F;FgOBEe>P zvSOSNSrTGw#Kny_JdB_I^nMgYfM%THphFhmq|+8-XikJUZ;05IPxD_;5>#d4=n%w0 zDzAqI2)YSzP`Ei#r-eq@K+8>#`#af~-c%nr3lcurjmbXx(ulX+TRI30?p zR>&YuZ%Z)==-#<*Ld^hfFn#mSolw#9{;nnTw(tJL41D6>4Un_dhizc*25D26G#!(Y zZOg)9c|7(I2D|UUvgLHQ^>j{y!_Uq=1KL|4s)wxe5H6(Xnf%Q~B_6{SXPtmW``4sp z-Xm-x34qEBT7J-s3p_hE2=_UTbIOjrb@#k$#*JfHmJHqu;xqTv$r$-SYChVAkNcn9 zge`3?EHe9}PbMe2_+v6NPaOnqMR4)fSb#76{SVMsvl)vQ^y81-^BN3R*25{*!*M8t zA0TdJaQqr#gvgwJw9-1Ry=4h*y7LK)CJ{V8!eK}5k4s;B8V)~V2wu=eUc~Ypgg>bD zBs$}w(M^Bci~reJpsoZLSA|}`0#^p;wi_WIzT+WA?Oe_Iiwp@ zJUyvBu8b8@_$Wu4IVsxC7@B1REaVm>n#ioutXm3RqPoa{qyb!sh+W&XF8`zpH`oH6 z>cjFlYR1fht(fu}?GTlM)$`OOR&S1A&f}tBcdBnUIGP!^y@H^{vwMHqc6K%1P_;uv z4Gd&rD2=kK=$yi~35{D}^Lsp4Z~GCn_t0?z!S8*qgqI}BG0LxfA!@|1^Sn9j$UR&c5JeoOjWwm^Z(oPV=HU!X_Xslu4Dz z^N=L8bt@70gNU0BRy@Mq`wZGXpl62(}%l3!U@^@JyAvJJo)b8bLcXDgnF5e6E z82VqQ)72DVxd^E!mAS_4Kt<07|4jEYBU9QXPo1nN9cMCx!nBQA(!iA$osA=BQEjlh zm=b=YGz3Mt#H@Soe7)CkoG;I`Q=hS;S(fGJ0DNGk4VX?#ljZ3XE*WkL7muzT!@7|c zNAzT!BQ~qQu;x0W}VGBHVDzJ-F%WW$=ICJqFRLd6cl94w?X%9DmO0`dfvJO9Te`I9~IogP-K2mDp3YE`6 z?3QSh)H!J)6DEy;MnsF8E&6mGWps+fv0kxoYnGrCzim!H+YM?gwpdk=U`Hsz1n_Qv zG=ZWMPz{7)#obMlOmEP8Axkj}nRMFQZP2#G(TQ4CodtpCshzBL7ocZn*eDZzFYhr% z9QJxT=v+^2V8Y(P^uz9%Cqt1lvnwNP;(GA%5`B4$QxDk(uQ+J|ybP%OTx)eF%7Q+j zFUocb3uVSeo$Ze47aYf#k+En-4`o@FGqBa(a-UhcwC0*LGXNf6JBsxqEfj?(t=(?q zA!bugNOzJ#NGpT&0YomL6b^lXxYdV$_|#2U`S@z|dzJEINHtG zbW$|S7TRc&h@)7i1S!*<#~>~dOpPlyD8?*ZR zg;Bv*z-*XqFnJ9dHiq~gfBh9?BYjvf2l%r;IvIWLGwAn1q;Uc_WH+W3j`BP~5RfxW zOq*&^gD9OrtX$W`kMDR8KmFCC7%hj8djU>8^(b6^`OC52e9C9gR1!#%CMuqbG>H*b zLbT&H{4hX~6TBve+{4PJ8@T%FTd{QMGsv^GPSvVmhP*L+61Of3X3|V({JIWF>W#RirNw3+UK;i3IKhg~J`6l-qmMb~hj*p;U*t z(+Y14Qlz-5^$G3H?OlEp+1D`7z|6Vmz|B+ixhc+Bd<0&8*Z?S=Z1gG(+lcme6Gmx9 zN1bu!x&go$j^jMJ+5~ zM2CnVJ9&zszMAlw$)#>J#xPKi5XU9rtd39r@9*HLWjaMMl8@bjNPh_NvSU>EcDpN|txe+lYy zA~f<%D1sD;nrW+QH zOald*W>Oj?7ggj%gc233-(29Do9@G153E8G?28tF6Hi-+%da>CbM_(JkpM-aJnNu> zIBvml=>$X!mynMK&#g)W&+-*x_{pvJ;;y?MN0QV~xP3U_(EV`283zM2YH*wI>pmKB zOPWz^5m8(6Rjp2QIR*yJ$~9POMs4}iY6@VoLzC;-wtfwpwgumQe*8V$USRE=E~qWX=$NAG@AdPhFl$tBc768j=}%6~z-6msm^1cjd){NOz2~~6CPR(+vOtuz zaPjGjaN>bg)Qrn~cf30z*9EL}1GP82{@8Jx&&>1_-8+U-`LVPr`ru3$(B49m-B>cT zFrQrV=t{}J**(bsPMnazyBc`ttAyeqDY_#rWmZ#h;$bk!lRBPwB*tey`LD7qedXCl zm`=Qh;60`I=^ z6uflN9Mp=n2$3MpJ$M2ACylv6L52#u8w+V&XRgm+ z!Kw`<;%K%MSl{%f3vlKc^Wg^>qH2L8X~XllGss1UBukt6;JFd9+(%YKg1s-fZzX0bDa)3siJ7w(cWur>J7! ze5WT3LcP4|ZW*%|O6kqW?NP+sSr!gLN$TZjyG1SLZ82c7Y7|#={|F#7y41TOjI z#;;v6XVpC+JkIXOoSG~d8+h16l*wYjY&s)fCY*i;TrU&@WI`+K&}=8bjki96`yPH2N1t{S+J21G zE0BvOw}3mwSx1c?d*6&qjq%B71HTt#%LxvUZQqS&&8epe#J3*O{KZB;oQ{1rY>Q!yA%hW zZqZnVJI_(gTR8o&eemiN4?`ap)jR`bH$@(&muAVDjX6O*k`3T9GW0wM;B3cn*b=>0 zyk_JmKHtcdWqB+B(hKMA$q}9yz%7Jw|6{8H#l?#G;KsZ4sw{ z@A6N8=2(GBG=w$lflqznD_H+*frIDH#^S?6y#0zZP{*@KDA=&=cuiQy_!~k1jcdk7nutmDy<1#b;xR@BHvK-1q24q(ML0Zi(|RIt!Ovax8}W z35{o{M3gwCm0K>#f;`_Kpm{Ob2P~|*aH1;i|IIVF^ZsQR+V3E=3J*E;xyg7jntK9- z7}g0~V)+Gf!*Os@^6@TegWR*IB}$4eYMS+HM`dC1W&`VtYkRt9P!))#9ki zpqf9XsA^4@J4=fI^;W~h0%v=22JY&2TU{El_~?uQ7kk>HNf0-(T6XuLyE_dPd=EvE zhtS6RE;|haB~X|BCo>p_oYc;VS?I(D87p0E6kT@p0;cP8WSpGiIL^b<^##*$+`TS< z%L7-I7XY|rItFCtj;UdSQ=S2wf>sYb@to+QBrF8>1n}7dbulL3E;ADo2nS){A#OLt zK8y`2Wv&d6(h2au0~_)8pSlhq>Zlc)@%GoBh6_&VN6p`ev`kQxY#mZ4h0PKo^Xib5 ztARHPJe2JezPRwXD7_Gg=Si0C76D3cE|xq#hHqVa2bQmEAfxJFt;A)QosaX+J5sWG zhY*Jwi@&Di{XB2!2jX|p&ojqpQevd-T<7-yCr>Vg}`k~M$hkJ zP$qS-qm?4>H2UO{sayJBZvZDoPw2%`6MOE~w(ydkh~A6(TJKH`P}+3F08U6pvGJbF z+$c{fhHu>NWjnFAVko*$YG%#ru}qOtJuW+iVr~l6IKwWW{I9UcP)QrO@T6n$(!*5i zTY7S-u;{U2%Yfiy$(q~Kl`iY%;xn+4d7{fM(fUWRU zoC@j~X-D|!uU6uw+kS)9!#)t!F?at#y!Q3y;^Y$tgsbg&3DT@3#=*ic5l%WyiZitH z0>jM|nG*tj6-(}a9CzRI8w9~DR4TJj@2j9b;2^AKa6Gp5bLT;fy$a6@0LK?CbH>S5 z+(wenXo6dD{*LXWS_q~f7~B|f-a;NS)9>E-tr}iTho|VFFx2*RZ%PSN^wLw|tmk5q ztP0&_Ucje3s)1F=XQvK~7F_v-zDfm{-|dOHH~H_>AT42>c zEp*Gw2PZV!WuoJbH-NaDk7qXc_{rU?aO2PJLzCsuii6{hUx3SAb1oJf+z-auBpZY0 zl^}#c*v5}&ljCCb`i;m+Ri|^jeze8mOiiyg9H5tgA#`xx<8IQ@?ge$jAl*oB~lwTRnb;& zPGbfv-I~O@^`|6-Jz`SShVgv{aTaYgKMedpG}~=^KP7sNsEo3u7 zzEE-K?FVpyPq;v_mSKvxyeX{HIB9}<-o%yXoPwkG2}CNE^&R2;JC49?DlTSsrd`o8 zse9Ps=*&{I`mp0TdnATT;x=|Zx>pBq6U6@8>wim!3dU7=yIpM%*kkaH*S{1se*-*k4cxK~ zFONXSDmf=+-yQ|9ES}u;z0?wta;Jmezst442y>%I@82hBv;v!ubL$e zv(mDP7WTn|kB{Q3-@XHznl9opL0BvB=HGb*&OT?MJhl9;v=~7cIieXp)=1E9mk6U8 zvLZ#2C!)RLFnIE=NVW~3D9Y96rCeK4@bfO7equdt`|(3~eCay$dHW(PJ)HNlML6{( z2cZ@w@QMU(>Y)-+DwkNg$*?^~?Ckg_aRJt9W2eAao?s+tVKix@nWt2O(T-Mrj)oOJ zX`C)nA~Sx3v``nLB#jXUlmj4x$7b-Q2$HclE91!)@=5!$?Y5~p;fpu}bScXTdzoe? z&6Q0DELAH7(+*_M<|Zu+cqQs(g15fzjoB@qb#PuMU@o70X=vIz2m=M^G#>)70m@Z(=Rf*=3#NsPu7xRpN4KX49S z_r~+E@aPb3n4%~f@O>IT0F6c)%~l(3=)&V-kg2OWo0aHS&MkHru$jq2kSwa$w8$mn zF4*uyn>q^kW*Oo%K`T$Np*?~$2rv@oh#eQPU%;(-7)>@Ktg>l|A%~oOAHGPYYG4yX zX-cA+TEbL4guC}RhK0f~>u{m6JHG<1sn2Nfl9-8ype#}4;@Q}Q^G-Y#FFSf3`UTVG z+;u^}4@o}^*ISuYig8dYutoypw)JwKF_Is1vZMOpqEfOkycA-8iV zb$$`0HECSXA|?a)!^_uUIL%)$1DB1aG~n3OSc^!uy@J`F@33jd=v;d~+9@#B2=PDu z>Kcr#-GswukKivpawYmb%Fk{>RAV;V)5=AAS+x@C66pqVvzde)C)el%mZVg0Z>< zasC3e3e6}|2^!Y$!7BS%U2c&sV1Sp7P{qIX?W$}@Xr&doXuv}w3vt`MORy#1jQ;&1 z%s#M+G3uX3gCg$b6bx|uEDNj3tkIIDHu&tFFVjRNd2)B>Cv%S?WTcF;&>I9ulboJR z=qnQJUv==dSDh@Z6VeDd3fxP{yyD*|p=^L|E%^4n#tS6u;c@$l<2di!!{;z%U%$7` z!tD+~S(e`b@ViqsLfbsh)&bl$@;tm^EryfrXW(>JCzo0Rr?jqf_6MdTP_rWz{xoA{ z%RK{ejy%l~1vTVZ1&=@0#Hau6pV5aJPC9x&y#F0%z)4mh5@Td)W;1Iv@Q7(m7ih&* zes&qB0uy+CC~OP{J6fm_4idXBQW^+`Yf(Y5&g^>^ZtXBt2>BuyKy zyW&+i=Yj*_S0If+URYwZ*+8ouO9sbnL6#Ed4#a6bY5VZX3jX%5zK(bl2+I(2`}=V2 zS*PIWh4T@T7tb?Fxhp6Ugf7}~3sF=>qnV;oscQGBxCC`Aa9BKJQIvt2*|sdM9RjkI zr6ttjA`N`BN*_PF?J3;89t9b2|ufn2J z4w7zEFC^5FpdF9OvG~~2e={e$CJ(UmS8H(fw{J$xtK-a5PQuI2IFvO`RQ(uEp1@-v zw9rgC$zr&H1HvM%NBo;i2Lq@&-2O{_R3%Ed@bH4g*`~|X)|R9%W?%l7izmh=S)_dh)%EWEdmOF^r7GXtYwaQpJ$%OFK2KR)~(b z4!dnox9{BgGuoOzp2TjC-GSE3J?vW1X$HLOFNHX|*U;O2$(;-Dzc{<1n#VY1ZVj)0 z>Cqw;t7LRXrUwkT&zpKv|vQCDU`c1$#7rf6H+kQjcF$uNP$ipZ*|j9v)N3 z(n2JV~<35{j&f zfBC1|vFyIbQO!p2u@Alu3lA7Z)!!s-^j_&9qLHy+#teYku}NcKYuTksksfn=2+<&9 zgM@}f8G-EeeIe^@ zqL1R~@7)aKzpyCDu2GH~7eKDCg&$!}41D=NuE)mB8?j*FY`pJ}E=3V+MpA4+RH-1# zbdl8deQV%h0y9-13m46HjM1@Cj5V5QB?*!=7tMASLqQQU(}J#rW!sLgjy=?mm+Nv> zDAyO04b^xjWF~=*Q-wufGIt1f<=Sb>Ybwjw;PSf?i;Qa!&y(LP!B+1t?=5#OUddjA z3{I9}epuiguQ&zsBfTR%YT;XRx$O;_xOjGEmo8{~An3d(gSUN3cV!mr6`z?dIHik! z8w}i3;F)JU`P?R~YP6BK3X3Sx$N=6ag*c%$OeT9GrHxRBJBYCn;D7z~H_=$r#{9kv z|KG`Sa`D4)gq`myNh^Mhx^q#1-AEC*{9MhBK!z>&|U?@Z5LkcKs>$9 z!*{Ry1(rOz9Ay}Z%HnzFpN`8fdl~9AV00At=C^;2+wXZCK@nnBk>kJr;X7p2Bb~1- z7`RImG{&`#^F~@$gP&Q@Xbvq{zR{mC31Cn-62Jv3m!>5;204h61hraScL8);EnIAu zX^uF{&}hdJ$ocnnlAz5+jM#ma3FkeKofUcPxd@wiCV;a6OG6|XGFs#gq5wV%t#OGY zH*{0cQMa7DoqZHFfNR#Q*)$iMT>24A6H}2P%wzN+!Ap-h7#AEfA2o50{*+!}#p~ z`~iX-IP;|0c>5dAKs8^5&>KVPxzgFlHXml7w83Jxqfa@|o~)>QMOXgIQ=-P|9?wnoL-CA_`5F;=`#Mbv8wb1dE|kif9$t+c^;U zH6$tJ1YG>&&PQ;|-4CLuBzVK`o`GW*?FT>1;rb5R30vxo7*nTR-sqW&W{VN&;*P+0 zl`m6x}WgRLvr~jGz`HRRhIAmbpS3JSb@5_bxuAqw{S=e8oy|?|8ka z3YOa%@)vyoH*m@nQw)0`6fvCd2Jn>|#_-hUk!cO!nSpKskNOpTxcRyj_|I?Mgdl6- zs@J~^uRLou{BjM_vL$*eUg08(+3xHK|9RW3;GK$}nJ42jZ##LU^*<|wtM2-xShDGH z2hoW8kh=Tf`ky?38-BhNEw6^LSn+f>D=<{)$9ZR-ijx=3lgyh!UU^2|HJf|1Pc%(3 zX?0gn*{EpP;N8*UR_Yr&R|&6B9ES91%JeyKzpb@|c0xWrC9lm$N%}9LU z%BGX)D^`1n}J=% znHekpUW>4~GzgKy&NKJ9V`Br9bdfsnqAE5wTexfK!*CY+$@{2JQS4X+Gf^=O2z{op<Ii*)fQ`6alryvlK2N0-yezE!FvUT*HE~bpcZ(?qtK=a}ix}6$+5%9o3*F zep`xzk-$Zi!40cur6tyn=J?9DZ^ruOFb-TefcJdpGPvOwl6+ViirA6L%u|ZGvLIVU zMHYS;*mzDfXLh8qO5!ycLbh693z6iB6USH4HRVG~!<3FW3#s(skSn9afixdcg4cmB zlENwn5a%UwFT}5wK8g`)>u`~@H%N9GlX-OYytqg(U<)Zy{xb(Vg`+&jqJ#Fq8%{eI zJ_Ed5XNgc4uf2{9Gd2diD4KM3WOOGp3wGrAGwMBMSx!;gy=mm>Sc93~8vrZTjbO#_ z*z{%Kga+tINFgBx>0y)kN}AsRi=|UX_zJ2 zq5DaTR1K&i)k%|ui<^>z)ZuP{7`_JfBB!o;fU(@eeUCnYc2JWp zU(ri2RL{v6N=SiRVmKECE-tB@GkNn-kz&4|MAds7sj?PX%A+dV&=Z~ z`u6yp8QPtAa(CviGxxn^S<))$vy(f+?FaDZ!@%jqE}fQ>Krorgg`tPh(J_Pp6)6PF zM4D8wZnc9?{O!M@Xt_AykU@OxU8ke&JO|%vp)3<*q~;0VdwW;EW7C0!P+@ow3l{++ z@dAREaS@rloVAB8i3_rCM@Fn^$gUp7tVTA*5?4hh@h8J8r4iISo; zFLm^{O)%|gqp{o>&5Bh-OY};-RJsWfCx}Rc3_LXR5I6kd5&UAw!$^DwSH0(QEIi&t z>5d=_`^CuF@!H5K&+Gc|yhwz#Bmj4cg?5LcnQJC`z^-Jbl3iO0ois&h2HrWxaYL;T zgw4ja3s;vNo51tm0@p_?10G!dEY`O&jHVD=yrduijXDf{a#!ZCZEWHqC3ORKup$v9 zMqd9Q61?iz{c*;^edV6A$jW;n=S@nh6^WVD4q#W#e1|^sA;)n(w?prIk-TZgp4b=3 z#oEg#%W{%ZwBsQZOC#iOpAQ3{ssJu@KMT)K#1Mg;;n!R?J)?L1u z%ArP5KxP1E>5rwxGN){>i^Q+v{-+Xr^M}`?jg2_};>Eb=(xXv0W60A8KDB1@F@ZBY zKR_I3@V%<}F0wteNNV$GE-XAhO}w?+Q-i(EE+raipxe68C}ed|>5%`Xa>LYB(a%a| zEXa+E%!}~TB}Cw4MNpTVCsrV!uSHD{l#1Gqep z+hCzc(@92Ey*eV%nx1?HE`dz4RAahpJTWtNKIRpCcgRNg zSS>B+WTLPeR5E9?71pfLa116il}x;a-3*dhqp!6_C+XOyNomo`&~oPCp%p{;)aQSQ z41IXl+uw$RX1NH<7W|GJYmXFcCubdBOf}`e&bV17v2fYNgOM4#((B0QkV0I+!YY~N z5jM4a{NvYd!j^axhaVl{?eDn+Ze>i(B`m5evb%g)mwJ=+3-)b(Z_JNn0h@3ShfTW38MH^RMa0ZSYq|SHRkwTEmlQNI33+TL?Aul@Vym@alW0;EZ zn=yA`DlTSck74ZD*tNN6=RUjR0i4+uy9)>FHB@|Z!>1~MtD}vyS2&qkl?i}aLp~PZ z6My|J46ku9x0>Ov{^T6Y?%RkY-Xfae!ZxP7YR2XsZk-hhkQ|FphD|58^NSxk2I+Yi-Gsh~+l19n@v2$+s zJ0HONs}UCLg{=AhFbSC9f)p;xSWSao|=Wv zeC~(HC4j#b2hAdnqcsj%u&S)GtWBuQbsN!5NHnRgXr~LagM~Mm53umaYxiVfYUK?$ z(ICEe!!q2n>|vCZVZ8hOufxHI*5L(-6y?N5&83GDE1_hUsQiFND)Patt(zSPLNx?u zILtJA?j0k8nU71wd&jJ|HL=@eOCCQt)gE_H6#L>OgjFnAz7ngqkjEbhMKjM+Z5T3i zMc(Sk6fwC}(F`MVas;jiF9Qbh7Cv&tY0@rFl44iIyEoUi$;adtkezuxpXa^TQS)eT zG9aF!>wcamb2`3ZFF9semUQKy!_N-9c0PdDqY!J$ZVqp)07jP{4}mQ{h!2sh<} zxcklx`077@7eSHZvI`gEii-|KkgrBHBt{$~7efacMlcJr8RfQi2))6mMB%D)jRtT+ zwrn}!%ec5ZC6aO;9(`&^0yrTQ3E;C?#B3R#MGG41aBJJT`KkK~a~~}BZEL@V>L-g8 zx$Q0rPhEW&0VVX1^ZoEjeE-H@BaaH4`^tlH&V|Rp^>v{WFGz`k6x?C}XYjVn3eAue z5bM2e25{BCrU=>iPDm5LZKi73(sp&~Igafr6&)Iie7QdSz?BZp((|!7$#B{ zfrn%|-|{)faY#n^FaP>44WUfD`(;^v1i+_XcvkFq02d>(GDF4pFj()Kf>wGXyf4_V z2mvQA*w9n}PTOdS8*J32k#T?`4e+gR+=@GHdj@{m!iV2+CeB(k2Z-0g%^L_pa-S7O zsZ=8Qsr>BiO$(c$ar?Tic zl|J0_@NclDl_K}mq=W1bE;hvbS?HC9B{78FwMUnq(q<=Zf~q+g77o_%rgM(#h*ha) zk~zLWC%ho-($v7dYv29C&(#jStI&@fUqMv5c94Kfc0vWhhH&SZt1yDkj=n=ny?{+nVsvQIU3>b{^kc*ziJca_cig~ zK6C{R9M}Rc+lU}w049!XSQEyqcl+n30bFuHb`6^1A^njh$S{-|?eV1C2g_FU;ZvW# z28lC(cfVZ&c)$Q|bjr8B{7&RE>GnhzLjTS#Mx`5a(I6i^gB$qpqYxWM5`67jw_xq? zFoJ;sAODNDVrU=Qu5H3ti@}hER}+lnJR~JG8MV#2w_PN(#mVtO%+3XKsGf^b{gjCX zPKAnC2n`IMGjSZW9S@sRV99TuK*G%14Rv!Mrpp?2sYN2Jl}Q9}o?emXsM2I3ZlIbq z@ZQ&*i+uy?e5+iU7IV#o$dKFd(FN3I=({p~C-Ir})cSWE=lV$;<3;z;-v;n)+|sfv z4+lVVh?j5sj_+6i*M<$|n-nZ6FlTUR3Ie!&w)7kXG%(B&#gW;g&UWxZ^gYV7f{m+k z{I9?H67sZ)MTgD8A76C>W>+?&)oRLO((R1Y4$l`{V5Ftpgo8~(+y;rUu!BbntL{65b2%aO_ za&U_rbB1O~Cz}Sy@elb9-^UJH!(_rj@iLjI;TQ88b8dZo2Sw^3$}3oM_jCB-m##&n zOz^f>AAt+cI2g5{4dhK)dLm5|ROxt=#L7}r4L}o|%!ax*E0X}u;vX?^V#2&G((V}C zLbS{ISh})?Pk!+~k)VcmzvFEdOv>8?=ySx!}v|w`_q&y>sIM+U0lm!ZreOk58LB zS}fdo@Vu=NLT7|JptQZVUW8);5G1>oQfPc?d_WJ?c2LJ{4?TvMHg2F7rN}hGqqJ

4-`PVWt|k8YZ-k)iF^58GuzAM)2guF=@mg zRgR4knW2fz8W=Pt3tj89oeAZgM^w@;OK-DVS_V2TzG=3|Oqg*cf}7XG^6ER^xdXS| zatEq#@rUnvJr*C5A;Ly@ULo6R-=WGO#iUdVL<)XAy5wrrra?z?!wv*tzt{fWMH}<5 zbY)#K@T}~^djvvZ22KoI&smGE3Sp@JxqhCRv7iPt&EWNrb|?DZ{Jje=V*?7IBDN^{ zNJFi@s=?WreX@qQtyl3b_4 z=Hbk=$bBcv@6n>s5!!Vg`c6j9_d1UA<(>S@f2p_sHh}NI?JmpmWB^|Rz@G+tHEfR_ z*A-6g)ms{PeBB6Aas1W*E(QyZi~d>-Ayxb+8q_U^?Qkw`@@%tR*FZNuizHr}iP)6T z(&%a*^dU=qDXfC54zd|+iCKJ|rbkedL0AR!c?5!wK5r(bVFPj3J>LQ)dIxlnR@ z?@95GsUiu1nHyj%3-GVs_&(MSk6~b+2p{{iH)CivhhL2kI1cmyZKtu=z2(#%c|n|L zdlSQkHysaECO113Gc4WE-hI66ri=HTLR)O4BJ;%W8^ESC$KA^wL+n)$XAUUW%K+|K zGiB<}hy+Wj+3Re8Mw{A zn1OF4XBQOgeyD47WEMGTPPRMx#(bnidGWI`WK? zp&nMRO7VAp^KbA{;E?$qKKci*#T;)n{9=>1*pO04=tnSJkx^yVtqmO(8kKXGzi2?& zl>pvti?`@QC-2jdu|dTIC0VS>iqaR|L>%V5+5p<6i>q(EANM}=0Lo}HKKPNh;L@eTH3$`H@lgFZrA%#ttA<$?gXQ;v1aQHkr4Xe7oOWSzh6coIaNM?g2Tx~w05==mPGw7SGWo;c9Y(%%SMo*S zD<)=y5{f*4=T`8|Z`_Wb-TXNEoCF_x&uKXBU>6l?Er*0hXL|(T~;+64hau zTmToWz7xO$5mvIDm!d4_mQZ>k7mNZP?cwr@Tw?CWXqO?@jfVKAul@iHjNyb+4#fLE zbUyNYi!@A;XU*WvLM~{pmXUoDVB_WyLo%YrFOUYg;J!-qX<RaoTGZ`}?Se=7WY?}HPL*^YOfXlX1DOiMOs-*6)!Oh-aI^}_GA;8 z7CSf#wiUqbM|(LTdUwokOz@U`mh2g7xci|r8r^ySgGi|A7*$2dQDUZujEP2q?oecI zaa^>p%rPOX<#9nX0i1I!_CELAG=$u9 zlfd>)CaBRdb3@!$m&9M)FA)H4o6fkj;zS2;n!(K*93X7=cvnw)oE7t$UH;N*6H zQ7QFuV>8kGRFc9q2V!@OfY$nJp^pDPR2H6Ju^tuXF{0gUx*QqAnT6*)7p*z^4Auqk zfu`a~Uffq@s?X6$u`@EEQjla8P3tZi2D@~nH_U}FWT$337R=j%yKa9}Zt#oF+7B0> zdpNv!D{NGZW=V3BGl)3JDKl8eDL0UTGk^PaU_`aO?iCNm|Kdprql2gWd>uVc80Vwug`nUlf%}&Y9ZZ37^F5OeBCC z$cZ}_J_H!pX~AZ?Z@F86cx#F_BSp$;CKCo6X^E=1=Hn+}Toz)D#%3s)1Zv61=$f*+ z082H+%w&F&Ypma4G&p?eLcLxob@T4H?}qz#400ZZ`|$O@ey#Pf72ww2Eq{A*Rk_AB zjJJuQ3`iGd#w@x;%bLeBT`x#{QNghMs*?pF9Q6$+`yLElTmOP0@CrnzQN0X*Taq%yJs4b&hN zN0=~rW6XMV#TJaZOI1hF^JH6hx8(T^2k?40M0O}CpQx_}AuUIIK#6t<>D4?w>EFcl9Yk&(&%E>sDz=N* z&A<;LxmLpUgxsWnD*=@|iR}Y8*OY-)93}^;D-k6HY*Tj>fdmRxQRCe&qs0m^>Cg%I z=%HhfjR1%4&uPni61e+s>Js`%vV79wtf4ISm1Y~b`+o)Ct4gVP4ScrwksXXcGl1`b zW%1OC^`Ec6`Tq>uM&!vr59Iz*_jzPXPHt9{>?HYH4K6kBf9IE^mC2ve0G_s3Zy&(x zDTd~zH2ElHSQRWg2S4xxlfCute~4{wY2>3`-1Mc7VpPj!6!L+n7RFT@o}Cc`Viv}B zM+ROiStdFvhAL;+HCAlHRjxEZS&oHj6e3g^RALuDxc?VeyR{R!5i$Puo0nkJX!5)( zLYovt!a5-?5xY(F&LeSpw~_!(-SWnkzGT<63_Mj|?0Znk-z9h(e4oLavIeB|&qHE{DTXObv zqnq%r(`;(H4Q`E{(!VX5!N=itn{LR&ifs=;2yEV{@y)N_2UXTM>fj8no%vC;XV)NS z_aG=6ze+03(n3u%xCeoOn-+Sr^au%1BAanT8L3z=LZQ5eJ5K;m4Jv3!cR|QsKyHH=U(18+w$&)@~Lt8|Q)VEP$sx4c0fL zaLoaej!_m=vncza=$^c|cm=uxYMVI1^C3G%9=-CgQ3$2g-#m=du@ZVTX!(d&@QSi-G#92XHIYVG?6&I30XcwY`@3UEn#JL?9LaT@n?vS|Ws!B<(lym&2U zKmH7&Oo&fkekM+wG!8khf;cF_RTo|}Rs(GAE@APiH-&{FFo~E1n>kMdW&P%$ z-@`6h6tV-T?O2R9OUg}`mV094ieg!19MX})Ri}Iyc@Y`pPJkNfCg7(l#o0asml{VO zwx5{o84BaBx6&^H@O7osLwooZ8`fXn4B&fd`X5`l`D+^bo0g6pPeo{NEr_|W(H=1l zGqT-JZswf_@cL;>x4ZR0KPf)-qZp>}ios{eOyL$=axxOGRSr?4@YA2Xgr|PF6exD# zt258Q(I29w%X(zoDr^QlTti##@3$&F=37K40BmsY)&QP7 z(j*9{4^s+I87v!K7NsDD?d9?Oyagy(9%ADA$pbrzcy`9GRJ=;9z6Y&Y2Wc=hJ2e6~ zeL6LSK+KMYKZOkFxd_W$Xj2tjb-^hZPbxeaNI?~D#(*gG0lb!h*E%ju5tX|xSv9rI z9Sh*Xm)RK-PCV}$%_8OA2`tS3zIVo1j`GB7TMyEaf1`uw^0t;dT*s{yx&%6r0I;i5 zlD;qVj z;Vo&9aphP(A9P+GYu9haiZyQ`$m9`FtctWf$3@5vE6axBdLZl)Q7eaBZ_$&j3%Ewl zCJo^1j5Uo_4C2NkmFEyfWfW8uXC5&Dr+;Wa&@)i*FTyiPV_BME*D5M9W~P>6%In<0 z82r6qG5ov>4Wdw7W0<*DKbXR><<^f9 zB9~<0%#iy}OFuxRPoSbs_Ovg%Hg{XtL ztwykNdEEcgr?Gt12J}YT@VB>Kf&C9~L{r?cVw3_OnY@PxRYXAu2N}4O@f8?_;!GN$ zV8_fliQNNTJ%ePS$b{9N5C*FjUUpg_Ha}&~Y+E28O2mfB#qVEPD4v%^MGX@RmhZzQ zOvK=7Q&o|l<%}2|6k%rzBgK>~Q{T>%i=XO)8)*YRxLj$5%Gycd^ z2YdTN&0XK~XO?Y!4PkhcaK$Cv+P=Z3f0Kww(3AJ{!?@E-Jf(p3ZRO2zQ-oF0HEFjd zd%;e$r+vQ{Zl;P@+lYb=tXNvYcfS2F?7+vllR7Z%!efz(H^M`yc1QPVUYlb|`@MX< zLIwLIYJ_tT$CQ(ujsr$1IGXlv$@z$yVxoy6LC9qGv1N&#`qMAHjwhb^9jZFOMW30B zv(GyamQ{iy5DuU`Dh$$NGepMAAgXA%6s{5%8)|^Z0>fxUr$@>OXmoaWNvCO}G{Q6; zm7P+e8*a{qyz?aJ3iqE`K7A)`Xs-oJUtfc_w{{_PJXDCzJ1*={?3HEQEXPH$>Wl1w z1Y8zE*+-d(NSOd`SSf}R&f>2*GFgGr&_gBh*henv!bPVahhs)(;1QyuQFZdnF_1`- z5+q8RY4Meh3PL2z|2Yp5rqdFOr0OQXi`j&k#RULvR!aTndw3fS>q9pK`1@e`Uw*si zvo`QIwuOWG%!SQ~8Em*7E=fVjL=kX@kV|@l?x+}=stg)6JK1*2jhbeT3Ze24>kNMK zUrX@h&wmTI*o(iMelAWq+CdhZOh=|-*J%}&&9-gR<*9hLlX0PKRIv}{tu5fTyXHW} z1za^_2KF26z(yGsgKHQ`#!Se=k9~v42(<2^8aa4-n~%GH_$W%cj1x{7hZ$F#j(m=~ z zI=e|7O2OKMMr>5Ii?Yh%ck>n^cC%okmsmj8vi3fNLJFES%sFWWs^fn2!4`%|V(}P0 z{Z_f_h@?TO)edo3M-HE2;WFilr+7afTq5nTBRy}kR*bs2+0mu@x*CL%XtpZ|L~@H# zit3!r*Lyeu%>e!$4*vFsUbvzA%ZOv@tBjGHR%R!eqJ9RsI||IZb|J>I(lnSbV>34@ z@mL0NBO4nz5&W3^a2L1FnvKmXdr^pbaoy+7#)N$%xN!+_)C*)x#>PyZcsdy$j?Hbi zuFJq5f{t5o1Wn8M|dm056uSMq9f<9=HT>%cud?2XN6T zv3%1_8iw%Lc;qYSOe^LsUxm&JwaXop$vTqaaiepnMHay)_fy+&oeZKNLPi=3D#-fX zxboanad3f|c??%tfD@2}Du{x7G<@6BmvWX;YSyl;w&uI`^awOOlY9EahU@n)UaY-% zRM%f?jW242-+6R+000sFNklObNRWNv!=zU0@7c5SxYHMO-Bbgm6^7q7t9QUGn!Xqw|gGv+?O(E*=A62M94q<3blEmYzd zt&YaNx`@lqKi+g)#vw8c?m}fW4@^^I7*GPf4#4dI{;?Uj2Ru`I;$=xFz=$Imu3CzNn*h(w#tK;;**1i}!V|w(h}l1W0R^RT z<&>lF$A`C})$2wa^un@f!$$iy8xg$~5u$?8Sh%JQv+jCWTPtN>E9(Sxn=~y9RK<)Qz$q19(?Y zuP{Ca6~GBYBrcete0S2#DA>Potyi8WotE1|jrl8HM`ULZX-i<0N~MxOK#k5JA4;)w z(mHllnsR6yk`Idb(~lg28&A-GOOIBmF(~axDFa-yXF2mKGrul?gs4Py33sH)JGk`yY5P4iZ<5El*K_$Ej z;cwWE2d!K&8@4kZx{AQv|MnO*bZx;t2gSJIrs;6(5;7Tf4w{DvX@O!+5gJYMod@ug zP|5Q$9+;h7-HFR&;}8lN9HIcIXvkoW!T%?$&wmW>f$g9>(s*(Ct0*fQk)|FB!Iq?9 zYdh2Tfz2g_s!Va#7nY$$R)rYf>S5+thanpRj$;@sNE@!G6GJ0qoAbQW*K+{wQcAJ? zz4;mfBhU=sLtv7&KgId$d(VcBuL1C>fuFuDkcXsacDHe|k8{G4PT9?32B0-un}MEX zxd_!LgYI4z|M$jwP~8w>{74ViUwaNlX1ifUv|_7DD|-}H;R=m#3|?N_j@$m}VQ9?& zJ`D$sis9(8s0Q}*^q^2EKwCL%t0+A1@H1GsdL!(71z)-00*pP#f$JC<+&DD$V3~r8 zQmH7Wzo{5je@vjSh?(wFq_KP38^%;^bJkYuwSVD#~ln=CzN)jh6{HV zCFNj4sf_t=tQOiJVUCQOMd16w@lROd1E0F|6KwQxU9c)ZkIVL;2h%<_2@`WbfjT#l zFP*9KcoAw3)g3hy<%M^QpgaiRdrB$txtp&cGy;vS;vsZ_f5@jgZ)4X7Riv&`z!d;S z@7lEz3uPw8%(lm5&6n7^Q_q@L<%P!(TeF8 zpMsH@Ug&5WBC4R5D?X5MrRVj~jeVk=$_zj<*kqI>~9-G35FzU*#NpUQzAxbFSN zyNGk5Q9yuWM(1$xNr#}-)KcXoo~XuPN4VqC)M;D72TueWS(y9*fPYa+tsKPZG(Y+t zjzBYjzlVdrI}g3!?e5Doa3z3KcK*Gba-yWn6-g){rO-5;FuaPZ3j?^0q`1h!mlp9S z3n3eT;sSp8@KQYblPAIUm>Hiu9j71Lih{El8YS3_AXN=JHy+Qev~b&9v^(4fS4^LR zgZ3dj(`yWR>FH?auXYCPn9ZHpqmeHTnUH6*elRxOihrUpVLz42=^GcL*8kn$XzY%EDI;UU_{L zw)r8tsnct-JJN_%$<>HTVJckJ$OPvM1Um!nnrxbd&f!+{+owCAe`E1k$# z9(scjSh}Gdw|)2LC{@}q^YYJN+-Sg4?3}a!JA+M~z`Z~EFKjIKV#0^_!{@$q4zhWA zJ2HUN$brWrW=}VI?hNS6lLqhvNZt`Uhu6k7b`i32q@BK0uA<}zhClMZTyzGugv20P z)8U8RM==~l2P7?Bmw}zZ@0Tt|QG~b%-%!-n1aR_SQUi}2x#I20SqM*`m^)qQtKIn6 zaUaH+|EB|)D1^)1iMZ99_I|qbFofHPH!0wUfOTKfOkr0>dFZ^S8Ni3mTn+e4UwOM{ z3Y4CzG%l=tSP%$2a8I+iLcse6_pW5$dg$5#$t>$V*5lqMah3I&81 zql>ug{1efpiG4G_r+6(Zmd3I!v@kmcewifjgi}9Nmm!gUu z%>47SaKfa65kx((9C3A&D>mn5d?(FghdFKf_nilDX1wH@lYv6T5t z6~a4RZ&*7}D909xaPZ>dWvH-Tpr|Ec^Z|?+1CwJaBBr|GjZP}X&NQ->Zd`Q2kvR6C zHe^heEpi5N6g_QQnFnFv0j1Q&Mvv0`+|U?-!LR0_ah=VxOh#bghR%s$?0ixweW8Wm zWKq#0&MlfAeP+Uc8a(X0}-oZS%iUuUp>AAa~^mBUKrr&DaYZ|Kk9&| z-h{SVvEcO)xaIcQaB?FsZR(%lfDSsITUfce3-{0Y87j7qQ_eaHpPqU=lvPAF@1R^Q z0XC0oiM5(w&O&IeH?5Fzpt+(QKq$iW5QRU6H6_xmojtwK($q8fr9cpe0bE6q(DQs2 z6*DA0OGpCET0ZL#N%s@Ond~G`=yR7 zi5_?mYB+WazI*3$Sn$G9v{^m4_NsGn*n|pn>|ojI(YWo-*?^nH^h+DJ@7$5e^c&8Xri2N!G_*4UVe2ILWkNe=HWv4i5R&F;N00T15Zq@ z8*Ik%w2yqyg+D#x#9tjXI{UL6@UT+qjooln&94}OBhU=sLvYge#3?Uc+tm@{hK-~t!@9|cRTRJ#iBcQYs)I1_aMO+VV9N%L14cNw=}VK5vlN!UR=^$K zn}cE)Vdm8{v0n%9{eSxfR&DKp+Zy8f>pv;_-hM>3NRm|RP_q4$znt2y8SyIP055+} z1K>LZaD##K+->xfN>aciop7gab-OsQY=^Iu%g8t`EXPB47~|Pj7NVMIL7?2)I2rgU zePXb_9$6Kj`6_8JFVqRUy7} z$G-!a9Hvg4hOuLSS^sc9%ASvFK7TQeIjR8HO&oHB-p7QMot!MjnXX0?z)kil=OB9n zhUV0plUJGS8tQ&X0Ow~cOW+fqa7F^5Y`^H!o=y`|-~E=LB&(<#1`)L5;q9(oEL*b< zRX2w+nS*>95t>T6Qso&V9vdud3R<1$r>ENQ-0jrQR;|nQzm>+5G2&m{bK#Nfl5D=3 zBhYUI-hH(;2W;4n!2I>=3$f0fp)C6}rQ=gw2PYMaB^2`QsQNSwW}`?R&-`W$eth4f z$Y>Ymo%?Z&JNN+He#dv=d2RUgr!T?srEBr~xxdEb^AEu%ry2P(ak~z? z<_l*Wdib#;53%e@ht|gbk$Na;22SeVy9I9pPo(*C3Za;5sbSePU>B@e84Yl{|FC-L zI0$1(2<+_DUniwsrp|VFMU!HM*!Hk+*{kTTMAAM_I0cTo6_#4AW4%lxUg98HtYWq3 zt_zP`yXQx{d4%CO0?hzE9B2JKzGgNSSxSE(iuA--#}i!F8z1=o!Iou>vn=aCt#xka zr`U&rCy~4F?TG*%1Gs@tdJt$x0H-dBJS0r6pM0kN7O3U${SGg`HBd@9RQ8*Zn_t^g z30J?gXvwNbd2hgWU-NUhSO58(4>TKR-s813+z#Ii;KOakhrsoc(ik|_{z|F+fM^Ug zU6jVC7*+=qMk=k^0o?|m1<(aR=OKn{M*D@yHj9-(7@@1TC|!{fz=a1cf&iNoR7ERY zf>uQZ)f)rd0J;FZ&4SvhwcY}#O|YYlD%R`ahi{*I__!u@ZwRcP;dF}s12LT9y$jv{ Qm;e9(07*qoM6N<$g3LHbhX4Qo literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/item_network_check.xml b/app/src/main/res/layout/item_network_check.xml index 6c75316adb..86791fad8d 100644 --- a/app/src/main/res/layout/item_network_check.xml +++ b/app/src/main/res/layout/item_network_check.xml @@ -14,54 +14,68 @@ android:id="@+id/manage_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_gravity="center_vertical" android:background="@color/transparent" - android:src="@drawable/ic_menu" android:contentDescription="@string/manage_tokens" - android:layout_gravity="center_vertical" + android:src="@drawable/ic_menu" android:visibility="gone" - app:tint="?colorControlNormal" - tools:visibility="visible" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toStartOf="parent"/> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:tint="?colorControlNormal" + tools:visibility="visible" /> + android:src="@drawable/ic_ethereum" + app:layout_constraintStart_toEndOf="@id/manage_btn" + app:layout_constraintTop_toTopOf="parent" /> - + app:layout_constraintHorizontal_bias="0" + app:layout_constraintStart_toEndOf="@id/token_icon" + app:layout_constraintTop_toTopOf="parent"> + + + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/name" + android:layout_marginHorizontal="@dimen/tiny_8" + android:layout_toEndOf="@id/chain_id" + android:text="@string/deprecated" + android:textColor="?colorError" + android:visibility="gone" + tools:visibility="visible" /> - + + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index d47f435bce..62de64b357 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -928,4 +928,5 @@ Intercambiar a través de %s No se encontraron rutas para los parámetros dados. Seleccione al menos un intercambio. + Obsoleta diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 854eb89b95..696a65acbc 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -941,4 +941,5 @@ Échange via %s Aucune route trouvée pour les paramètres donnés. Sélectionnez au moins un échange. + Obsolète diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index a1aa5880a8..e352e13fec 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -941,4 +941,5 @@ Tukar melalui %s Tidak ada rute yang ditemukan untuk parameter yang diberikan. Pilih setidaknya satu bursa. + Tidak digunakan lagi diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index ddec40adc3..8ad7842002 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -962,4 +962,5 @@ မှတဆင့်လဲလှယ်ပါ။ %s ပေးထားသော ကန့်သတ်ဘောင်များအတွက် လမ်းကြောင်းများ ရှာမတွေ့ပါ။ အနည်းဆုံးလဲလှယ်မှုတစ်ခုကို ရွေးပါ။ + ကန့်ကွက်ထားသည်။ diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 044d1bf5e4..5f7d3abdf5 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -941,4 +941,5 @@ Hoán đổi qua %s Không tìm thấy các tuyến đường cho các thông số đã cho. Chọn ít nhất một sàn giao dịch. + Không được chấp nhận diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 8e06c7008b..9775395c3b 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -928,4 +928,5 @@ 通过 %s 交换 没有找到给定参数的路由。 至少选择一个交易所。 + 已弃用 diff --git a/app/src/main/res/values/colors_misc.xml b/app/src/main/res/values/colors_misc.xml index e76582bb6b..cfae5b3a40 100644 --- a/app/src/main/res/values/colors_misc.xml +++ b/app/src/main/res/values/colors_misc.xml @@ -50,4 +50,5 @@ #222222 #292929 #8176c2 + #67b1d4 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e964d05ba1..00b4797fe8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1002,4 +1002,5 @@ Swap via %s No routes found for the given parameters. Select at least one exchange. + Deprecated diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 835cee2d0c..1e518ee453 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -47,6 +47,9 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final long MILKOMEDA_C1_TEST_ID = 200101; public static final long PHI_MAIN_ID = 4181; public static final long PHI_V2_MAIN_ID = 144; + public static final long SEPOLIA_TESTNET_ID = 11155111; + public static final long OPTIMISM_GOERLI_TEST_ID = 420; + public static final long ARBITRUM_GOERLI_TEST_ID = 421613; public static final String MAINNET_RPC_URL = "https://mainnet.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; @@ -86,6 +89,9 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final String MILKOMEDA_C1_TEST_RPC = "https://rpc-devnet-cardano-evm.c1.milkomeda.com"; public static final String PHI_MAIN_RPC_URL = "https://rpc1.phi.network"; public static final String PHI_NETWORK_V2_RPC = "https://connect.phi.network"; + public static final String SEPOLIA_TESTNET_RPC_URL = "https://rpc.sepolia.org"; + public static final String OPTIMISM_GOERLI_TESTNET_RPC_URL = "https://optimism-goerli.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; + public static final String ARBITRUM_GOERLI_TESTNET_RPC_URL = "https://arbitrum-goerli.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; static Map networkMap = new LinkedHashMap() { { @@ -168,6 +174,12 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit PHI_MAIN_ID, false)); put(PHI_V2_MAIN_ID, new NetworkInfo("PHI v2", "\u03d5", PHI_NETWORK_V2_RPC, "https://phiscan.com/tx/", PHI_V2_MAIN_ID, false)); + put(SEPOLIA_TESTNET_ID, new NetworkInfo("Sepolia (Test)", "ETH", SEPOLIA_TESTNET_RPC_URL, "https://sepolia.etherscan.io/tx/", + SEPOLIA_TESTNET_ID, false)); + put(OPTIMISM_GOERLI_TEST_ID, new NetworkInfo("Optimism Goerli (Test)", "ETH", OPTIMISM_GOERLI_TESTNET_RPC_URL, "https://blockscout.com/optimism/goerli/tx/", + OPTIMISM_GOERLI_TEST_ID, false)); + put(ARBITRUM_GOERLI_TEST_ID, new NetworkInfo("Arbitrum Goerli (Test)", "AGOR", ARBITRUM_GOERLI_TESTNET_RPC_URL, "https://goerli-rollup-explorer.arbitrum.io/tx/", + ARBITRUM_GOERLI_TEST_ID, false)); } }; From 85f52f1b50acd7fe45999e28b44d37cc02cb66b0 Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 3 Oct 2022 15:44:54 +1100 Subject: [PATCH 113/183] Deduplicate RPC network declarations (#2860) --- .../app/repository/EthereumNetworkBase.java | 46 +++++++++---------- .../alphawallet/app/ui/FunctionActivity.java | 1 + .../ethereum/EthereumNetworkBase.java | 26 +++++++---- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index ed77138a15..0192999050 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -3,13 +3,16 @@ /* Please don't add import android at this point. Later this file will be shared * between projects including non-Android projects */ +import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_SIGMA1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_TAU1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_MAINNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_MAINNET_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_TESTNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_TESTNET_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.AVALANCHE_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AVALANCHE_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; @@ -25,17 +28,25 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.FUJI_TEST_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_TEST_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_TEST_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_MAINNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_MAINNET_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_TESTNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_TESTNET_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISM_GOERLI_TEST_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_FALLBACK_URL; +import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_TEST_FALLBACK_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_NETWORK_V2_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; @@ -52,8 +63,10 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.SEPOLIA_TESTNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.SEPOLIA_TESTNET_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.SOKOL_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_RPC_URL; import android.text.TextUtils; import android.util.LongSparseArray; @@ -112,10 +125,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String FREE_RINKEBY_RPC_URL = "https://rpc.ankr.com/eth_rinkeby"; public static final String FREE_GOERLI_RPC_URL = "https://rpc.ankr.com/eth_goerli"; public static final String FREE_MUMBAI_RPC_URL = "https://rpc-mumbai.maticvigil.com"; - public static final String FREE_OPTIMISM_RPC_URL = "https://mainnet.optimism.io"; public static final String FREE_ARBITRUM_TEST_RPC_URL = "https://rinkeby.arbitrum.io/rpc"; public static final String FREE_KOVAN_RPC_URL = "https://kovan.poa.network"; - public static final String FREE_OPTIMISM_TESTRPC_URL = "https://kovan.optimism.io"; public static final String FREE_PALM_RPC_URL = "https://palm-mainnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b"; public static final String FREE_PALM_TEST_RPC_URL = "https://palm-testnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b"; public static final String FREE_CRONOS_MAIN_BETA_RPC_URL = "https://evm.cronos.org"; @@ -135,9 +146,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String MUMBAI_TEST_RPC_URL = usesProductionKey ? "https://polygon-mumbai.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_MUMBAI_RPC_URL; public static final String OPTIMISTIC_MAIN_URL = usesProductionKey ? "https://optimism-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() - : FREE_OPTIMISM_RPC_URL; + : OPTIMISTIC_MAIN_FALLBACK_URL; public static final String OPTIMISTIC_TEST_URL = usesProductionKey ? "https://optimism-kovan.infura.io/v3/" + keyProvider.getInfuraKey() - : FREE_OPTIMISM_TESTRPC_URL; + : OPTIMISTIC_TEST_FALLBACK_URL; public static final String ARBITRUM_TESTNET_RPC = usesProductionKey ? "https://arbitrum-rinkeby.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_ARBITRUM_TEST_RPC_URL; public static final String PALM_RPC_URL = usesProductionKey ? "https://palm-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() @@ -165,7 +176,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String ROPSTEN_FALLBACK_RPC_URL = "https://ropsten.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); public static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; - public static final String XDAI_RPC_URL = com.alphawallet.ethereum.EthereumNetworkBase.XDAI_RPC_URL; public static final String POA_RPC_URL = "https://core.poa.network/"; public static final String ROPSTEN_RPC_URL = "https://ropsten.infura.io/v3/" + keyProvider.getInfuraKey(); public static final String SOKOL_RPC_URL = "https://sokol.poa.network"; @@ -175,26 +185,14 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String BINANCE_TEST_FALLBACK_RPC_URL = "https://data-seed-prebsc-2-s1.binance.org:8545"; public static final String BINANCE_MAIN_RPC_URL = "https://bsc-dataseed.binance.org"; public static final String BINANCE_MAIN_FALLBACK_RPC_URL = "https://bsc-dataseed2.ninicoin.io:443"; - public static final String HECO_RPC_URL = "https://http-mainnet.hecochain.com"; - public static final String HECO_TEST_RPC_URL = "https://http-testnet.hecochain.com"; public static final String POLYGON_FALLBACK_RPC_URL = "https://matic-mainnet.chainstacklabs.com"; public static final String MUMBAI_FALLBACK_RPC_URL = "https://matic-mumbai.chainstacklabs.com"; - public static final String OPTIMISTIC_MAIN_FALLBACK_URL = "https://mainnet.optimism.io"; - public static final String OPTIMISTIC_TEST_FALLBACK_URL = "https://kovan.optimism.io"; public static final String CRONOS_TEST_URL = "https://evm-t3.cronos.org"; public static final String ARBITRUM_FALLBACK_TESTNET_RPC = "https://rinkeby.arbitrum.io/rpc"; - public static final String IOTEX_MAINNET_RPC_URL = "https://babel-api.mainnet.iotex.io"; public static final String IOTEX_MAINNET_RPC_FALLBACK_URL = "https://rpc.ankr.com/iotex"; - public static final String IOTEX_TESTNET_RPC_URL = "https://babel-api.testnet.iotex.io"; - public static final String AURORA_MAINNET_RPC_URL = "https://mainnet.aurora.dev"; - public static final String AURORA_TESTNET_RPC_URL = "https://testnet.aurora.dev"; - public static final String PHI_NETWORK_RPC = "https://rpc1.phi.network"; - public static final String SEPOLIA_TESTNET_RPC_URL = "https://rpc.sepolia.dev"; public static final String OPTIMISM_GOERLI_TESTNET_RPC_URL = "https://optimism-goerli.infura.io/v3/" + keyProvider.getInfuraKey(); public static final String ARBITRUM_GOERLI_TESTNET_RPC_URL = "https://arbitrum-goerli.infura.io/v3/" + keyProvider.getInfuraKey(); - public static final String OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL = "https://goerli.optimism.io"; - public static final String ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL = "https://goerli-rollup.arbitrum.io/rpc"; //All chains that have fiat/real value (not testnet) must be put here //Note: This list also determines the order of display for main net chains in the wallet. @@ -206,9 +204,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy PHI_MAIN_ID)); private static final List testnetList = new ArrayList<>(Arrays.asList( - GOERLI_ID, BINANCE_TEST_ID, HECO_TEST_ID, CRONOS_TEST_ID, OPTIMISM_GOERLI_TEST_ID, KLAYTN_BAOBAB_ID, + GOERLI_ID, BINANCE_TEST_ID, HECO_TEST_ID, CRONOS_TEST_ID, OPTIMISM_GOERLI_TEST_ID, ARBITRUM_GOERLI_TEST_ID, KLAYTN_BAOBAB_ID, FANTOM_TEST_ID, IOTEX_TESTNET_ID, FUJI_TEST_ID, POLYGON_TEST_ID, MILKOMEDA_C1_TEST_ID, ARTIS_TAU1_ID, - ARBITRUM_GOERLI_TEST_ID, SEPOLIA_TESTNET_ID, AURORA_TESTNET_ID, PALM_TEST_ID, + SEPOLIA_TESTNET_ID, AURORA_TESTNET_ID, PALM_TEST_ID, //Deprecated networks ROPSTEN_ID, RINKEBY_ID, KOVAN_ID, OPTIMISTIC_TEST_ID, SOKOL_ID, ARBITRUM_TEST_ID)); @@ -340,7 +338,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy "https://explorer-devnet-cardano-evm.c1.milkomeda.com/tx/", MILKOMEDA_C1_TEST_ID, "", "https://explorer-devnet-cardano-evm.c1.milkomeda.com/api?")); put(PHI_MAIN_ID, new NetworkInfo(C.PHI_NETWORK_NAME, C.PHI_NETWORK_SYMBOL, - PHI_NETWORK_RPC, + PHI_MAIN_RPC_URL, "https://explorer.phi.network/tx/", PHI_MAIN_ID, "https://rpc2.phi.network", "")); put(PHI_V2_MAIN_ID, new NetworkInfo(C.PHI_V2_NETWORK_NAME, C.PHI_NETWORK_SYMBOL, @@ -349,8 +347,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy "https://phiscan.com/api?")); put(SEPOLIA_TESTNET_ID, new NetworkInfo(C.SEPOLIA_TESTNET_NAME, C.SEPOLIA_SYMBOL, SEPOLIA_TESTNET_RPC_URL, - "https://sepolia.etherscan.io/tx/", SEPOLIA_TESTNET_ID, "", - "https://sepolia.etherscan.io/api?")); + "https://sepolia.etherscan.io/tx/", SEPOLIA_TESTNET_ID, "https://rpc2.sepolia.org", + "https://api-sepolia.etherscan.io/api?")); put(OPTIMISM_GOERLI_TEST_ID, new NetworkInfo(C.OPTIMISM_GOERLI_TESTNET_NAME, C.OPTIMISM_GOERLI_TEST_SYMBOL, OPTIMISM_GOERLI_TESTNET_RPC_URL, "https://blockscout.com/optimism/goerli/tx/", OPTIMISM_GOERLI_TEST_ID, OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL, @@ -586,7 +584,7 @@ public boolean hasLockedGas(long chainId) { return hasLockedGas.contains(chainId); } - + static final Map addressOverride = new HashMap() { { put(OPTIMISTIC_MAIN_ID, "0x4200000000000000000000000000000000000006"); @@ -1156,4 +1154,4 @@ public static boolean isNetworkDeprecated(long chainId) { return deprecatedNetworkList.contains(chainId); } -} +} \ No newline at end of file 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 dc81d9688b..0876ed35ce 100644 --- a/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java @@ -304,6 +304,7 @@ public boolean onOptionsItemSelected(MenuItem item) { private void completeTokenScriptFunction(String function) { Map functions = viewModel.getAssetDefinitionService().getTokenFunctionMap(token.tokenInfo.chainId, token.getAddress()); + if (functions == null) return; action = functions.get(function); if (action != null && action.function != null) //if no function then it's handled by the token view diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 1e518ee453..0b0b345c35 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -65,7 +65,7 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final String ARTIS_TAU1_RPC_URL = "https://rpc.tau1.artis.network"; public static final String BINANCE_TEST_RPC_URL = "https://data-seed-prebsc-1-s3.binance.org:8545"; public static final String BINANCE_MAIN_RPC_URL = "https://bsc-dataseed.binance.org"; - public static final String HECO_RPC_URL = "https://http-mainnet-node.huobichain.com"; + public static final String HECO_RPC_URL = "https://http-mainnet.hecochain.com"; public static final String HECO_TEST_RPC_URL = "https://http-testnet.hecochain.com"; public static final String AVALANCHE_RPC_URL = "https://api.avax.network/ext/bc/C/rpc"; public static final String FUJI_TEST_RPC_URL = "https://api.avax-test.network/ext/bc/C/rpc"; @@ -73,8 +73,8 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final String FANTOM_TEST_RPC_URL = "https://rpc.testnet.fantom.network"; public static final String MATIC_RPC_URL = "https://matic-mainnet.chainstacklabs.com"; public static final String MUMBAI_TEST_RPC_URL = "https://matic-mumbai.chainstacklabs.com"; - public static final String OPTIMISTIC_MAIN_URL = "https://mainnet.optimism.io"; - public static final String OPTIMISTIC_TEST_URL = "https://kovan.optimism.io"; + public static final String OPTIMISTIC_MAIN_FALLBACK_URL = "https://mainnet.optimism.io"; + public static final String OPTIMISTIC_TEST_FALLBACK_URL = "https://kovan.optimism.io"; public static final String CRONOS_MAIN_RPC_URL = "https://evm.cronos.org"; public static final String CRONOS_TEST_URL = "https://evm-t3.cronos.org"; public static final String ARBITRUM_RPC_URL = "https://arbitrum-mainnet.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; @@ -90,8 +90,10 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final String PHI_MAIN_RPC_URL = "https://rpc1.phi.network"; public static final String PHI_NETWORK_V2_RPC = "https://connect.phi.network"; public static final String SEPOLIA_TESTNET_RPC_URL = "https://rpc.sepolia.org"; - public static final String OPTIMISM_GOERLI_TESTNET_RPC_URL = "https://optimism-goerli.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; - public static final String ARBITRUM_GOERLI_TESTNET_RPC_URL = "https://arbitrum-goerli.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; + public static final String OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL = "https://goerli.optimism.io"; + public static final String ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL = "https://goerli-rollup.arbitrum.io/rpc"; + public static final String IOTEX_MAINNET_RPC_URL = "https://babel-api.mainnet.iotex.io"; + public static final String IOTEX_TESTNET_RPC_URL = "https://babel-api.testnet.iotex.io"; static Map networkMap = new LinkedHashMap() { { @@ -141,9 +143,9 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit put(POLYGON_TEST_ID, new NetworkInfo("Mumbai (Test)", "POLY", MUMBAI_TEST_RPC_URL, "https://mumbai.polygonscan.com/tx/", POLYGON_TEST_ID, false)); - put(OPTIMISTIC_MAIN_ID, new NetworkInfo("Optimistic","ETH", OPTIMISTIC_MAIN_URL, "https://optimistic.etherscan.io/tx/", + put(OPTIMISTIC_MAIN_ID, new NetworkInfo("Optimistic","ETH", OPTIMISTIC_MAIN_FALLBACK_URL, "https://optimistic.etherscan.io/tx/", OPTIMISTIC_MAIN_ID, false)); - put(OPTIMISTIC_TEST_ID, new NetworkInfo("Optimistic (Test)", "ETH", OPTIMISTIC_TEST_URL, "https://kovan-optimistic.etherscan.io/tx/", + put(OPTIMISTIC_TEST_ID, new NetworkInfo("Optimistic (Test)", "ETH", OPTIMISTIC_TEST_FALLBACK_URL, "https://kovan-optimistic.etherscan.io/tx/", OPTIMISTIC_TEST_ID, false)); put(CRONOS_MAIN_ID, new NetworkInfo("Cronos (Beta)", "CRO", CRONOS_MAIN_RPC_URL, "https://cronoscan.com/tx", CRONOS_MAIN_ID, false)); put(CRONOS_TEST_ID, new NetworkInfo("Cronos (Test)", "tCRO", CRONOS_TEST_URL, "https://testnet.cronoscan.com/tx/", CRONOS_TEST_ID, false)); @@ -176,10 +178,14 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit PHI_V2_MAIN_ID, false)); put(SEPOLIA_TESTNET_ID, new NetworkInfo("Sepolia (Test)", "ETH", SEPOLIA_TESTNET_RPC_URL, "https://sepolia.etherscan.io/tx/", SEPOLIA_TESTNET_ID, false)); - put(OPTIMISM_GOERLI_TEST_ID, new NetworkInfo("Optimism Goerli (Test)", "ETH", OPTIMISM_GOERLI_TESTNET_RPC_URL, "https://blockscout.com/optimism/goerli/tx/", + put(OPTIMISM_GOERLI_TEST_ID, new NetworkInfo("Optimism Goerli (Test)", "ETH", OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL, "https://blockscout.com/optimism/goerli/tx/", OPTIMISM_GOERLI_TEST_ID, false)); - put(ARBITRUM_GOERLI_TEST_ID, new NetworkInfo("Arbitrum Goerli (Test)", "AGOR", ARBITRUM_GOERLI_TESTNET_RPC_URL, "https://goerli-rollup-explorer.arbitrum.io/tx/", + put(ARBITRUM_GOERLI_TEST_ID, new NetworkInfo("Arbitrum Goerli (Test)", "AGOR", OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL, "https://goerli-rollup-explorer.arbitrum.io/tx/", ARBITRUM_GOERLI_TEST_ID, false)); + put(IOTEX_MAINNET_ID, new NetworkInfo("IoTeX","IOTX", IOTEX_MAINNET_RPC_URL, "https://iotexscan.io/tx/", + IOTEX_MAINNET_ID, false)); + put(IOTEX_TESTNET_ID, new NetworkInfo("IoTeX (Test)","IOTX", IOTEX_TESTNET_RPC_URL, "https://testnet.iotexscan.io/tx/", + IOTEX_TESTNET_ID, false)); } }; @@ -219,4 +225,4 @@ public static String getChainSymbol(long chainId) return networkMap.get(MAINNET_ID).symbol; } } -} +} \ No newline at end of file From 773b17c878ba70624b045bc686eb404f8e8e8b3e Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 3 Oct 2022 19:36:57 +1100 Subject: [PATCH 114/183] Temp revert code style check --- build.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/build.sh b/build.sh index 75cdf3a57f..fbb6943140 100644 --- a/build.sh +++ b/build.sh @@ -1,6 +1,12 @@ #!/usr/bin/env bash -cd dmz && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -cd lib && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -cd util && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt -x checkStyleMain -x checkStyleTest \ No newline at end of file +# Temporarily revert to get builds working +# cd dmz && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +# cd lib && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +# cd util && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +# ./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt -x checkStyleMain -x checkStyleTest + +cd dmz && ../gradlew -i build && ../gradlew -i test && cd .. +cd lib && ../gradlew -i build && ../gradlew -i test && cd .. +cd util && ../gradlew -i build && ../gradlew -i test && cd .. +./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt \ No newline at end of file From ad4fd04faf5c3985389bff2cdc2c678c9853773d Mon Sep 17 00:00:00 2001 From: Hwee-Boon Yar Date: Sun, 16 Oct 2022 01:29:53 +0800 Subject: [PATCH 115/183] Switch token icons back to `master` since everyone should have updated their app. It'll continue to work for those who haven't, only new token icons wouldn't appear for them #2870 (#2871) --- app/src/main/java/com/alphawallet/app/util/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index 169aeb9076..8403073d7e 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -74,7 +74,7 @@ public class Utils { private static final String ICON_REPO_ADDRESS_TOKEN = "[TOKEN]"; private static final String CHAIN_REPO_ADDRESS_TOKEN = "[CHAIN]"; private static final String TOKEN_LOGO = "/logo.png"; - public static final String ALPHAWALLET_REPO_NAME = "https://raw.githubusercontent.com/alphawallet/iconassets/lowercased/"; + public static final String ALPHAWALLET_REPO_NAME = "https://raw.githubusercontent.com/alphawallet/iconassets/master/"; private static final String TRUST_ICON_REPO_BASE = "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/"; private static final String TRUST_ICON_REPO = TRUST_ICON_REPO_BASE + CHAIN_REPO_ADDRESS_TOKEN + "/assets/" + ICON_REPO_ADDRESS_TOKEN + TOKEN_LOGO; private static final String ALPHAWALLET_ICON_REPO = ALPHAWALLET_REPO_NAME + ICON_REPO_ADDRESS_TOKEN + TOKEN_LOGO; From d692bd1e9c363f48b27bf5fb34ad28bb7056e57a Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 18 Oct 2022 12:04:17 -0500 Subject: [PATCH 116/183] Update AlphaWallet style --- app/AlphaWalletStyle.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/AlphaWalletStyle.xml b/app/AlphaWalletStyle.xml index 069f4ca6f6..f356da7dc8 100644 --- a/app/AlphaWalletStyle.xml +++ b/app/AlphaWalletStyle.xml @@ -1,4 +1,7 @@ + + @@ -122,4 +126,7 @@ + + \ No newline at end of file From a2c900c510ca90d9287ffbd97808cae191975e8b Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 20 Oct 2022 23:25:20 +0800 Subject: [PATCH 117/183] fix ci (#2867) * Ignore failure test * Fixed custom networks not showing up * Fix currency test * Increase test stability * Format code * Run test on API 31 * Run emulator with GUI * Fix transfer test * Collect test report * Run tests in background * Increase test stability * Force recreate emulator * Refactor * Fix checkstyle * Increase stability * Revise test * Increase timeout --- .github/workflows/e2e.yml | 4 +- .github/workflows/lint.yml | 2 +- .gitignore | 1 + .../java/com/alphawallet/app/BaseE2ETest.java | 25 +-- .../com/alphawallet/app/CoinbasePayTest.java | 19 +- .../com/alphawallet/app/CurrencyTest.java | 4 - .../com/alphawallet/app/DappBrowserTest.java | 2 - .../java/com/alphawallet/app/I18nTest.java | 4 +- .../app/TokenScriptCertificateTest.java | 27 ++- .../com/alphawallet/app/TransferTest.java | 30 ++-- .../java/com/alphawallet/app/steps/Steps.java | 82 +++++---- .../com/alphawallet/app/util/EthUtils.java | 5 +- .../java/com/alphawallet/app/util/Helper.java | 170 ++++++++++++++---- .../app/repository/EthereumNetworkBase.java | 156 +++++++++++----- .../app/viewmodel/NewSettingsViewModel.java | 61 +++++-- build.gradle | 2 +- build.sh | 14 +- checkstyle.xml | 13 +- e2e.sh | 19 +- 19 files changed, 418 insertions(+), 222 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index f8b281d7fb..b9d469c92d 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,7 +7,7 @@ on: jobs: test: runs-on: self-hosted - timeout-minutes: 15 + timeout-minutes: 20 strategy: matrix: api-level: [30] @@ -31,7 +31,7 @@ jobs: profile: Nexus 6 channel: canary disable-animations: true - force-avd-creation: false + force-avd-creation: true emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none script: ./e2e.sh --CI diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b8195683e4..d771eb99c0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,4 +21,4 @@ jobs: - name: Run Kotlin lint run: ./gradlew :app:detekt - name: Run Android Lint - run: ./gradlew :app:lintAnalyticsDebug \ No newline at end of file + run: ./gradlew :app:lintAnalyticsDebug -x checkStyleMain -x checkStyleTest \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4cd7d8520f..30de5e7d17 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ fastlane/.google-play-key.json DCIM/ vendor/ .project +output/ \ No newline at end of file diff --git a/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java b/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java index 5785d38362..13f7084cb0 100644 --- a/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java +++ b/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java @@ -29,8 +29,10 @@ public abstract class BaseE2ETest { @Rule - public TestRule watcher = new TestWatcher() { - protected void starting(Description description) { + public TestRule watcher = new TestWatcher() + { + protected void starting(Description description) + { setFailureHandler(new CustomFailureHandler(description.getMethodName(), getInstrumentation().getTargetContext())); } }; @@ -39,19 +41,20 @@ protected void starting(Description description) { public ActivityScenarioRule activityScenarioRule = new ActivityScenarioRule<>(SplashActivity.class); - @BeforeClass - public static void dismissANRSystemDialog() throws UiObjectNotFoundException + @Before + public void setUp() throws UiObjectNotFoundException + { + dismissANRSystemDialog(); + closeSecurityWarning(); + } + + private void dismissANRSystemDialog() throws UiObjectNotFoundException { UiDevice device = UiDevice.getInstance(getInstrumentation()); UiObject waitButton = device.findObject(new UiSelector().textContains("wait")); - if (waitButton.exists()) { + if (waitButton.exists()) + { waitButton.click(); } } - - @Before - public void setUp() - { - closeSecurityWarning(); - } } diff --git a/app/src/androidTest/java/com/alphawallet/app/CoinbasePayTest.java b/app/src/androidTest/java/com/alphawallet/app/CoinbasePayTest.java index d992831fab..fea044df3a 100644 --- a/app/src/androidTest/java/com/alphawallet/app/CoinbasePayTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/CoinbasePayTest.java @@ -3,30 +3,15 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.alphawallet.app.assertions.Should.shouldSee; -import static com.alphawallet.app.steps.Steps.addNewNetwork; -import static com.alphawallet.app.steps.Steps.assertBalanceIs; import static com.alphawallet.app.steps.Steps.createNewWallet; -import static com.alphawallet.app.steps.Steps.ensureTransactionConfirmed; -import static com.alphawallet.app.steps.Steps.getWalletAddress; -import static com.alphawallet.app.steps.Steps.gotoSettingsPage; -import static com.alphawallet.app.steps.Steps.importWalletFromSettingsPage; -import static com.alphawallet.app.steps.Steps.selectTestNet; -import static com.alphawallet.app.steps.Steps.sendBalanceTo; -import static com.alphawallet.app.steps.Steps.switchToWallet; -import static com.alphawallet.app.steps.Steps.toggleSwitch; import static com.alphawallet.app.util.Helper.click; -import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; -import android.os.Build; - import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class CoinbasePayTest extends BaseE2ETest { +public class CoinbasePayTest extends BaseE2ETest +{ @Test public void should_see_coinbase_pay_window() { diff --git a/app/src/androidTest/java/com/alphawallet/app/CurrencyTest.java b/app/src/androidTest/java/com/alphawallet/app/CurrencyTest.java index 8c4e3e7947..bfb84d1dce 100644 --- a/app/src/androidTest/java/com/alphawallet/app/CurrencyTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/CurrencyTest.java @@ -19,10 +19,6 @@ public void should_switch_currency() gotoWalletPage(); shouldSee("¥"); - selectCurrency("KRW"); - gotoWalletPage(); - shouldSee("₩"); - selectCurrency("IDR"); gotoWalletPage(); shouldSee("Rp"); diff --git a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java index 47823c7115..7ad0a0c9e3 100644 --- a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java @@ -8,7 +8,6 @@ import static com.alphawallet.app.steps.Steps.visit; import com.alphawallet.app.util.Helper; -import com.alphawallet.app.util.SnapshotUtil; import org.junit.Test; @@ -24,7 +23,6 @@ public void should_switch_network() visit(urlString); shouldSee("Ethereum"); Helper.wait(5); - SnapshotUtil.take("1"); selectTestNet("Görli"); navigateToBrowser(); Helper.wait(3); diff --git a/app/src/androidTest/java/com/alphawallet/app/I18nTest.java b/app/src/androidTest/java/com/alphawallet/app/I18nTest.java index 09d93bf214..7f2f25d1ff 100644 --- a/app/src/androidTest/java/com/alphawallet/app/I18nTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/I18nTest.java @@ -2,9 +2,9 @@ import static androidx.test.espresso.Espresso.pressBack; import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.alphawallet.app.steps.Steps.createNewWallet; import static com.alphawallet.app.steps.Steps.gotoSettingsPage; import static com.alphawallet.app.steps.Steps.selectMenu; -import static com.alphawallet.app.steps.Steps.watchWalletWithENS; import static com.alphawallet.app.util.Helper.click; import org.junit.Test; @@ -15,7 +15,7 @@ public class I18nTest extends BaseE2ETest @Test public void should_switch_language() { - watchWalletWithENS("vitalik.eth"); + createNewWallet(); gotoSettingsPage(); selectMenu("Change Language"); diff --git a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java index 6364c0efa1..d8c85166b3 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java @@ -7,12 +7,12 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; import static com.alphawallet.app.assertions.Should.shouldSee; +import static com.alphawallet.app.steps.Steps.GANACHE_URL; import static com.alphawallet.app.steps.Steps.addNewNetwork; import static com.alphawallet.app.steps.Steps.getWalletAddress; import static com.alphawallet.app.steps.Steps.importPKWalletFromFrontPage; import static com.alphawallet.app.steps.Steps.selectTestNet; import static com.alphawallet.app.steps.Steps.switchToWallet; -import static com.alphawallet.app.util.EthUtils.GANACHE_URL; import static com.alphawallet.app.util.Helper.click; import static com.alphawallet.app.util.Helper.waitUntil; import static org.hamcrest.CoreMatchers.equalTo; @@ -47,11 +47,13 @@ public class TokenScriptCertificateTest extends BaseE2ETest private final Web3j web3j; private static final Map WALLETS_ON_GANACHE = new HashMap() - {{ - put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); - put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); - put("32", new String[]{"0x992b442eaa34de3c6ba0b61c75b2e4e0241d865443e313c4fa6ab8ba488a6957", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); - }}; + { + { + put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); + put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); + put("32", new String[]{"0x992b442eaa34de3c6ba0b61c75b2e4e0241d865443e313c4fa6ab8ba488a6957", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); + } + }; public TokenScriptCertificateTest() { @@ -100,7 +102,7 @@ public void should_view_signature_details() assertThat(getWalletAddress(), equalTo(ownerAddress)); - addNewNetwork("Ganache"); + addNewNetwork("Ganache", GANACHE_URL); selectTestNet("Ganache"); //Ensure we're on the wallet page @@ -117,7 +119,7 @@ public void should_view_signature_details() onView(allOf(withId(R.id.edit_text))).perform(replaceText(doorContractAddress)); - onView(isRoot()).perform(waitUntil(withId(R.id.select_token), 30)); + onView(isRoot()).perform(waitUntil(withId(R.id.select_token), 300)); click(withId(R.id.select_token)); @@ -128,17 +130,12 @@ public void should_view_signature_details() //Swipe up onView(withId(R.id.coordinator)).perform(ViewActions.swipeUp()); - Helper.wait(1); - //Select token - click(withSubstring("OFFIC")); + click(withSubstring("OFFIC"), 120); //Wait for cert to resolve - //Helper.wait(8); - onView(isRoot()).perform(waitUntil(withId(R.id.image_lock), 30)); - //click certificate - click(withId(R.id.image_lock)); + click(withId(R.id.image_lock), 180); shouldSee("Smart Token Labs"); shouldSee("ECDSA"); diff --git a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java index 4a0b05a2d7..12c085f03d 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java @@ -1,5 +1,6 @@ package com.alphawallet.app; +import static com.alphawallet.app.steps.Steps.GANACHE_URL; import static com.alphawallet.app.steps.Steps.addNewNetwork; import static com.alphawallet.app.steps.Steps.assertBalanceIs; import static com.alphawallet.app.steps.Steps.createNewWallet; @@ -9,8 +10,6 @@ import static com.alphawallet.app.steps.Steps.selectTestNet; import static com.alphawallet.app.steps.Steps.sendBalanceTo; import static com.alphawallet.app.steps.Steps.switchToWallet; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import android.os.Build; @@ -20,33 +19,36 @@ import java.util.HashMap; import java.util.Map; -public class TransferTest extends BaseE2ETest { +public class TransferTest extends BaseE2ETest +{ // On CI server, run tests on different API levels concurrently may cause failure: Replacement transaction underpriced. // Use different wallet to transfer token from can avoid this error - private static final Map WALLETS_ON_GANACHE = new HashMap() {{ - put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); - put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); - put("32", new String[]{"0x992b442eaa34de3c6ba0b61c75b2e4e0241d865443e313c4fa6ab8ba488a6957", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); - }}; + private static final Map WALLETS_ON_GANACHE = new HashMap() + { + { + put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); + put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); + put("32", new String[]{"0x992b442eaa34de3c6ba0b61c75b2e4e0241d865443e313c4fa6ab8ba488a6957", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); + } + }; @Test - public void should_transfer_from_an_account_to_another() { + public void should_transfer_from_an_account_to_another() + { int apiLevel = Build.VERSION.SDK_INT; String[] array = WALLETS_ON_GANACHE.get(String.valueOf(apiLevel)); - if (array == null) { + if (array == null) + { fail("Please config seed phrase and wallet address for this API level first."); } String privateKey = array[0]; - String existedWalletAddress = array[1]; createNewWallet(); String newWalletAddress = getWalletAddress(); importWalletFromSettingsPage(privateKey); - assertThat(getWalletAddress(), equalTo(existedWalletAddress)); - - addNewNetwork("Ganache"); + addNewNetwork("Ganache", GANACHE_URL); selectTestNet("Ganache"); sendBalanceTo(newWalletAddress, "0.001"); ensureTransactionConfirmed(); diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index b600353316..e6894599af 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -15,8 +15,9 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.alphawallet.app.assertions.Should.shouldNotSee; import static com.alphawallet.app.assertions.Should.shouldSee; -import static com.alphawallet.app.util.EthUtils.GANACHE_URL; import static com.alphawallet.app.util.Helper.click; +import static com.alphawallet.app.util.Helper.clickListItem; +import static com.alphawallet.app.util.Helper.waitForLoadingComplete; import static com.alphawallet.app.util.Helper.waitUntil; import static com.alphawallet.app.util.RootUtil.isDeviceRooted; import static org.hamcrest.Matchers.allOf; @@ -36,6 +37,8 @@ */ public class Steps { + public static final String GANACHE_URL = "http://10.0.2.2:8545/"; + public static void createNewWallet() { click(withId(R.id.button_create)); @@ -45,15 +48,17 @@ public static void createNewWallet() public static void closeSecurityWarning() { - if (isDeviceRooted()) { + if (isDeviceRooted()) + { click(withText(R.string.ok)); } } public static void closeSelectNetworkPage() { - Helper.wait(5); pressBack(); + Helper.wait(1); + shouldSee(R.id.nav_settings_text); } public static void visit(String urlString) @@ -74,8 +79,9 @@ public static void selectTestNet(String name) selectMenu("Select Active Networks"); toggleSwitch(R.id.mainnet_header); click(withText(R.string.action_enable_testnet)); - click(withSubstring("Rinkeby")); // Deselect - click(withSubstring(name)); // Select + Helper.wait(1); + clickListItem(R.id.test_list, withSubstring("Görli")); + clickListItem(R.id.test_list, withSubstring(name)); pressBack(); } @@ -85,18 +91,21 @@ public static void selectMenu(String text) selectActiveNetworks.perform(scrollTo(), ViewActions.click()); } - public static void assertBalanceIs(String balanceStr) { + public static void assertBalanceIs(String balanceStr) + { Should.shouldSee(balanceStr); } - public static void ensureTransactionConfirmed() { + public static void ensureTransactionConfirmed() + { // onView(withText(R.string.rate_no_thanks)).perform(click()); click(withId(R.string.action_show_tx_details)); onView(isRoot()).perform(waitUntil(withSubstring("Sent"), 30 * 60)); pressBack(); } - public static void sendBalanceTo(String receiverAddress, String amountStr) { + public static void sendBalanceTo(String receiverAddress, String amountStr) + { click(withId(R.id.nav_wallet_text)); ensureBalanceFetched(); click(withSubstring("ETH")); @@ -104,7 +113,7 @@ public static void sendBalanceTo(String receiverAddress, String amountStr) { onView(withHint("0")).perform(replaceText(amountStr)); onView(withHint(R.string.recipient_address)).perform(replaceText(receiverAddress)); click(withId(R.string.action_next)); - Helper.wait(5); + Helper.wait(10); click(withId(R.string.action_confirm)); } @@ -114,13 +123,15 @@ private static void ensureBalanceFetched() shouldNotSee("0 ETH"); } - public static void switchToWallet(String address) { + public static void switchToWallet(String address) + { gotoSettingsPage(); click(withText("Change / Add Wallet")); onView(withSubstring(address.substring(0, 6))).perform(ViewActions.click()); } - public static String getWalletAddress() { + public static String getWalletAddress() + { gotoSettingsPage(); click(withText("Show My Wallet Address")); GetTextAction getTextAction = new GetTextAction(); @@ -129,7 +140,8 @@ public static String getWalletAddress() { return getTextAction.getText().toString().replace(" ", ""); // The address show on 2 lines so there is a blank space } - public static void importWalletFromSettingsPage(String text) { + public static void importWalletFromSettingsPage(String text) + { gotoSettingsPage(); click(withText("Change / Add Wallet")); click(withId(R.id.action_add)); @@ -138,31 +150,38 @@ public static void importWalletFromSettingsPage(String text) { int textId; int buttonId; boolean isPrivateKey = text.startsWith("0x"); - if (isPrivateKey) { + if (isPrivateKey) + { click(withText("Private key")); textId = R.id.input_private_key; buttonId = R.id.import_action_pk; - } else { + } + else + { textId = R.id.input_seed; buttonId = R.id.import_action; } onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(textId)))))).perform(replaceText(text)); Helper.wait(2); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis click(withId(buttonId)); + waitForLoadingComplete("Handling"); + waitUntil(withSubstring("")); closeSelectNetworkPage(); } - public static void importPKWalletFromFrontPage(String privateKey) { + public static void importPKWalletFromFrontPage(String privateKey) + { click(withText("I already have a Wallet")); click(withText("Private key")); Helper.wait(1); onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_private_key)))))).perform(replaceText(privateKey)); Helper.wait(1); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis click(withId(R.id.import_action_pk)); - Helper.wait(5); + Helper.wait(15); } - public static void importKSWalletFromFrontPage(String keystore, String password) { + public static void importKSWalletFromFrontPage(String keystore, String password) + { click(withText("I already have a Wallet")); click(withText("Keystore")); Helper.wait(1); @@ -174,7 +193,8 @@ public static void importKSWalletFromFrontPage(String keystore, String password) Helper.wait(5); } - public static void importKSWalletFromSettingsPage(String keystore, String password) { + public static void importKSWalletFromSettingsPage(String keystore, String password) + { gotoSettingsPage(); click(withText("Change / Add Wallet")); click(withId(R.id.action_add)); @@ -196,24 +216,27 @@ public static void gotoWalletPage() click(withId(R.id.nav_wallet_text)); } - public static void gotoSettingsPage() { + public static void gotoSettingsPage() + { click(withId(R.id.nav_settings_text)); } - public static void toggleSwitch(int id) { + public static void toggleSwitch(int id) + { onView(allOf(withId(R.id.switch_material), isDescendantOfA(withId(id)))).perform(ViewActions.click()); } - public static void addNewNetwork(String name) + public static void addNewNetwork(String name, String url) { + gotoSettingsPage(); selectMenu("Select Active Networks"); click(withId(R.id.action_add)); input(R.id.input_network_name, name); - input(R.id.input_network_rpc_url, GANACHE_URL); + input(R.id.input_network_rpc_url, url); input(R.id.input_network_chain_id, "2"); input(R.id.input_network_symbol, "ETH"); - input(R.id.input_network_explorer_api, GANACHE_URL); - input(R.id.input_network_block_explorer_url, GANACHE_URL); + input(R.id.input_network_explorer_api, url); + input(R.id.input_network_block_explorer_url, url); onView(withId(R.id.network_input_scroll)).perform(swipeUp()); Helper.wait(1); click(withId(R.id.checkbox_testnet)); @@ -243,15 +266,8 @@ public static void selectCurrency(String currency) gotoSettingsPage(); selectMenu("Change Currency"); Helper.wait(1); - try - { - click(withText(currency)); - } - catch (Exception e) - { - onView(withId(R.id.list)).perform(ViewActions.swipeUp()); - click(withText(currency)); - } + clickListItem(R.id.list, withText(currency)); + Helper.wait(1); pressBack(); } } diff --git a/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java b/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java index 246ddd9ac9..71414521d3 100644 --- a/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java +++ b/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java @@ -32,8 +32,6 @@ */ public abstract class EthUtils { - public static final String GANACHE_URL = "http://10.0.2.2:8545"; - public static Web3j buildWeb3j(String url) { OkHttpClient client = new OkHttpClient.Builder() @@ -47,7 +45,8 @@ public static Web3j buildWeb3j(String url) return Web3j.build(svs); } - public static String calculateContractAddress(String account, long nonce){ + public static String calculateContractAddress(String account, long nonce) + { byte[] addressAsBytes = org.web3j.utils.Numeric.hexStringToByteArray(account); byte[] calculatedAddressAsBytes = Hash.sha3(RlpEncoder.encode( diff --git a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java index 4a0144f00e..952e194a39 100644 --- a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java +++ b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java @@ -1,62 +1,79 @@ package com.alphawallet.app.util; -import android.view.View; - -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.RootMatchers.isDialog; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isRoot; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.core.AllOf.allOf; -import java.util.concurrent.TimeoutException; +import android.view.KeyEvent; +import android.view.View; import androidx.test.espresso.PerformException; import androidx.test.espresso.UiController; import androidx.test.espresso.ViewAction; import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.espresso.util.HumanReadables; import androidx.test.espresso.util.TreeIterables; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.isRoot; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static org.hamcrest.core.AllOf.allOf; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; -public class Helper { - private static final int DEFAULT_TIMEOUT_IN_SECONDS = 10; +import java.util.concurrent.TimeoutException; - public static ViewAction waitUntil(final int viewId, final Matcher matcher) { +public class Helper +{ + private static final int DEFAULT_TIMEOUT_IN_SECONDS = 30; + + public static ViewAction waitUntil(final int viewId, final Matcher matcher) + { return waitUntil(allOf(withId(viewId), matcher), DEFAULT_TIMEOUT_IN_SECONDS); } - public static ViewAction waitUntil(final int viewId, final Matcher matcher, int timeoutInSeconds) { + public static ViewAction waitUntil(final int viewId, final Matcher matcher, int timeoutInSeconds) + { return waitUntil(allOf(withId(viewId), matcher), timeoutInSeconds); } - public static ViewAction waitUntil(Matcher matcher) { + public static ViewAction waitUntil(Matcher matcher) + { return waitUntil(matcher, DEFAULT_TIMEOUT_IN_SECONDS); } - public static ViewAction waitUntil(Matcher matcher, int timeoutInSeconds) { - return new ViewAction() { + public static ViewAction waitUntil(Matcher matcher, int timeoutInSeconds) + { + return new ViewAction() + { @Override - public Matcher getConstraints() { + public Matcher getConstraints() + { return isRoot(); } @Override - public String getDescription() { + public String getDescription() + { return "wait for view matches " + matcher.toString() + " during " + timeoutInSeconds + " seconds."; } @Override - public void perform(final UiController uiController, final View view) { + public void perform(final UiController uiController, final View view) + { uiController.loopMainThreadUntilIdle(); final long startTime = System.currentTimeMillis(); final long endTime = startTime + timeoutInSeconds * 1000L; - do { - - for (View child : TreeIterables.breadthFirstViewTraversal(view.getRootView())) { - if (matcher.matches(child)) { + do + { + for (View child : TreeIterables.breadthFirstViewTraversal(view.getRootView())) + { + if (matcher.matches(child)) + { return; } } @@ -75,47 +92,130 @@ public void perform(final UiController uiController, final View view) { }; } - public static void wait(int seconds) { - onView(isRoot()).perform(new ViewAction() { + public static void wait(int seconds) + { + onView(isRoot()).perform(new ViewAction() + { @Override - public Matcher getConstraints() { + public Matcher getConstraints() + { return isRoot(); } @Override - public String getDescription() { + public String getDescription() + { return "wait " + seconds + " seconds."; } @Override - public void perform(final UiController uiController, final View view) { + public void perform(final UiController uiController, final View view) + { uiController.loopMainThreadUntilIdle(); uiController.loopMainThreadForAtLeast(seconds * 1000L); } }); } - public static void click(Matcher matcher) { + public static void click(Matcher matcher, int timeoutInSeconds) + { + onView(isRoot()).perform(Helper.waitUntil(Matchers.allOf(matcher, isDisplayed()), timeoutInSeconds)); + onView(matcher).perform(ViewActions.click(doNothing())); // if click executed as long press, do nothing and retry clicking + } + + public static void click(Matcher matcher) + { // Helper.wait(1); //slight pause onView(isRoot()).perform(Helper.waitUntil(Matchers.allOf(matcher, isDisplayed()))); onView(matcher).perform(ViewActions.click(doNothing())); // if click executed as long press, do nothing and retry clicking } - private static ViewAction doNothing() { - return new ViewAction() { + private static ViewAction doNothing() + { + return new ViewAction() + { @Override - public Matcher getConstraints() { + public Matcher getConstraints() + { return isDisplayed(); } @Override - public String getDescription() { + public String getDescription() + { return "Do nothing."; } @Override - public void perform(UiController uiController, View view) { + public void perform(UiController uiController, View view) + { } }; } + + public static void clickListItem(int list, Matcher matcher) + { + for (int i = 0; i < 50; i++) + { + try + { + click(matcher, 0); + return; + } + catch (Exception e) + { + scrollDown(list); + } + } + throw new RuntimeException("Can not find " + matcher.toString()); + } + + private static void scrollDown(int list) + { + onView(withId(list)).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DPAD_DOWN)); + Helper.wait(1); + } + + public static void waitForLoadingComplete(String title) + { + waitUntilShown(title); + waitUntilDismissed(title); + } + + private static void waitUntilDismissed(String title) + { + while (true) + { + try + { + onView(withSubstring(title)).inRoot(isDialog()).check(matches(not(ViewMatchers.isDisplayed()))); + } + catch (Error e) + { + // Dialog still showing + wait(1); + } + catch (Exception e) + { + // Dialog dismissed + break; + } + } + } + + private static void waitUntilShown(String title) + { + while (true) + { + try + { + onView(withSubstring(title)).inRoot(isDialog()).check(matches(ViewMatchers.isDisplayed())); + break; + } + catch (Error | Exception e) + { + wait(1); + } + } + } } diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 0192999050..64a0bf64ef 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -137,7 +137,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy : FREE_RINKEBY_RPC_URL; public static final String KOVAN_RPC_URL = usesProductionKey ? "https://kovan.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_KOVAN_RPC_URL; - public static final String GOERLI_RPC_URL = usesProductionKey ? "https://goerli.infura.io/v3/" + keyProvider.getInfuraKey() + public static final String GOERLI_RPC_URL = usesProductionKey ? "https://goerli.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_GOERLI_RPC_URL; public static final String POLYGON_RPC_URL = usesProductionKey ? "https://polygon-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_POLYGON_RPC_URL; @@ -211,10 +211,11 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy ROPSTEN_ID, RINKEBY_ID, KOVAN_ID, OPTIMISTIC_TEST_ID, SOKOL_ID, ARBITRUM_TEST_ID)); private static final List deprecatedNetworkList = new ArrayList<>(Arrays.asList( - RINKEBY_ID, ROPSTEN_ID, KOVAN_ID, SOKOL_ID, OPTIMISTIC_TEST_ID, ARBITRUM_TEST_ID)); + ROPSTEN_ID, RINKEBY_ID, KOVAN_ID, OPTIMISTIC_TEST_ID, SOKOL_ID, ARBITRUM_TEST_ID)); // for reset built-in network - private static final LongSparseArray builtinNetworkMap = new LongSparseArray() { + private static final LongSparseArray builtinNetworkMap = new LongSparseArray() + { { put(MAINNET_ID, new NetworkInfo(C.ETHEREUM_NETWORK_NAME, C.ETH_SYMBOL, MAINNET_RPC_URL, @@ -390,7 +391,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy //the entries are automatically sorted into numerical order private static final LongSparseArray networkMap = builtinNetworkMap.clone(); - private static final LongSparseArray chainLogos = new LongSparseArray() { + private static final LongSparseArray chainLogos = new LongSparseArray() + { { put(MAINNET_ID, R.drawable.ic_token_eth); put(KOVAN_ID, R.drawable.ic_kovan); @@ -437,7 +439,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy } }; - private static final LongSparseArray smallChainLogos = new LongSparseArray() { + private static final LongSparseArray smallChainLogos = new LongSparseArray() + { { put(MAINNET_ID, R.drawable.ic_icons_network_eth); put(KOVAN_ID, R.drawable.ic_kovan); @@ -484,7 +487,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy } }; - private static final LongSparseArray chainColours = new LongSparseArray() { + private static final LongSparseArray chainColours = new LongSparseArray() + { { put(MAINNET_ID, R.color.mainnet); put(KOVAN_ID, R.color.kovan); @@ -575,7 +579,7 @@ else if (networkMap.indexOfKey(chainId) >= 0) } else { - return 500 + (int)chainId%500; //fixed ID above 500 + return 500 + (int) chainId % 500; //fixed ID above 500 } } @@ -585,7 +589,8 @@ public boolean hasLockedGas(long chainId) return hasLockedGas.contains(chainId); } - static final Map addressOverride = new HashMap() { + static final Map addressOverride = new HashMap() + { { put(OPTIMISTIC_MAIN_ID, "0x4200000000000000000000000000000000000006"); put(OPTIMISTIC_TEST_ID, "0x4200000000000000000000000000000000000006"); @@ -598,40 +603,53 @@ public boolean hasLockedGas(long chainId) final NetworkInfo[] additionalNetworks; - static class CustomNetworks { + static class CustomNetworks + { private ArrayList list = new ArrayList<>(); private Map mapToTestNet = new HashMap<>(); final transient private PreferenceRepositoryType preferences; - public CustomNetworks(PreferenceRepositoryType preferences) { + public CustomNetworks(PreferenceRepositoryType preferences) + { this.preferences = preferences; restore(); } - public void restore() { + public void restore() + { String networks = preferences.getCustomRPCNetworks(); - if (!TextUtils.isEmpty(networks)) { + if (!TextUtils.isEmpty(networks)) + { CustomNetworks cn = new Gson().fromJson(networks, CustomNetworks.class); this.list = cn.list; this.mapToTestNet = cn.mapToTestNet; checkCustomNetworkSetting(); - for (NetworkInfo info : list) { + for (NetworkInfo info : list) + { networkMap.put(info.chainId, info); Boolean value = mapToTestNet.get(info.chainId); boolean isTestnet = value != null && value; - if (!isTestnet && !hasValue.contains(info.chainId)) { + if (!isTestnet && !hasValue.contains(info.chainId)) + { hasValue.add(info.chainId); } + else if (isTestnet && !testnetList.contains(info.chainId)) + { + testnetList.add(info.chainId); + } } } } - private void checkCustomNetworkSetting() { - if (list.size() > 0 && !list.get(0).isCustom) { //need to update the list + private void checkCustomNetworkSetting() + { + if (list.size() > 0 && !list.get(0).isCustom) + { //need to update the list List copyList = new ArrayList<>(list); list.clear(); - for (NetworkInfo n : copyList) { + for (NetworkInfo n : copyList) + { boolean isCustom = builtinNetworkMap.indexOfKey(n.chainId) == -1; NetworkInfo newInfo = new NetworkInfo(n.name, n.symbol, n.rpcServerUrl, n.etherscanUrl, n.chainId, n.backupNodeUrl, n.etherscanAPI, isCustom); list.add(newInfo); @@ -643,9 +661,12 @@ private void checkCustomNetworkSetting() { public void save(NetworkInfo info, boolean isTestnet, Long oldChainId) { - if (oldChainId != null) { + if (oldChainId != null) + { updateNetwork(info, isTestnet, oldChainId); - } else { + } + else + { addNetwork(info, isTestnet); } @@ -657,11 +678,14 @@ private void updateNetwork(NetworkInfo info, boolean isTestnet, long oldChainId) { removeNetwork(oldChainId); list.add(info); - - if (!isTestnet) { + if (!isTestnet) + { hasValue.add(info.chainId); } - + else + { + testnetList.add(info.chainId); + } mapToTestNet.put(info.chainId, isTestnet); networkMap.put(info.chainId, info); } @@ -669,14 +693,20 @@ private void updateNetwork(NetworkInfo info, boolean isTestnet, long oldChainId) private void addNetwork(NetworkInfo info, boolean isTestnet) { list.add(info); - if (!isTestnet) { + if (!isTestnet) + { hasValue.add(info.chainId); } + else + { + testnetList.add(info.chainId); + } mapToTestNet.put(info.chainId, isTestnet); networkMap.put(info.chainId, info); } - public void remove(long chainId) { + public void remove(long chainId) + { removeNetwork(chainId); String networks = new Gson().toJson(this); @@ -725,19 +755,42 @@ private void addNetworks(List result, boolean withValue) { for (long networkId : hasValue) { - result.add(networkMap.get(networkId)); + if (!deprecatedNetworkList.contains(networkId)) + { + result.add(networkMap.get(networkId)); + } + } + + for (long networkId : hasValue) + { + if (deprecatedNetworkList.contains(networkId)) + { + result.add(networkMap.get(networkId)); + } } } else { for (long networkId : testnetList) { - result.add(networkMap.get(networkId)); + if (!deprecatedNetworkList.contains(networkId)) + { + result.add(networkMap.get(networkId)); + } + } + + for (long networkId : testnetList) + { + if (deprecatedNetworkList.contains(networkId)) + { + result.add(networkMap.get(networkId)); + } } } } - public static String getChainOverrideAddress(long chainId) { + public static String getChainOverrideAddress(long chainId) + { return addressOverride.containsKey(chainId) ? addressOverride.get(chainId) : ""; } @@ -766,7 +819,8 @@ public NetworkInfo getNetworkByChain(long chainId) @Override public Single getLastTransactionNonce(Web3j web3j, String walletAddress) { - return Single.fromCallable(() -> { + return Single.fromCallable(() -> + { try { EthGetTransactionCount ethGetTransactionCount = web3j @@ -869,7 +923,8 @@ public NetworkInfo[] getAllActiveNetworks() } @Override - public void addOnChangeDefaultNetwork(OnNetworkChangeListener onNetworkChanged) { + public void addOnChangeDefaultNetwork(OnNetworkChangeListener onNetworkChanged) + { onNetworkChangedListeners.add(onNetworkChanged); } @@ -886,8 +941,12 @@ public static List getAllMainNetworks() public static String getSecondaryNodeURL(long networkId) { NetworkInfo info = networkMap.get(networkId); - if (info != null) { return info.backupNodeUrl; } - else { + if (info != null) + { + return info.backupNodeUrl; + } + else + { return ""; } } @@ -937,16 +996,24 @@ public static BigInteger getMaxGasLimit(long chainId) public static String getNodeURLByNetworkId(long networkId) { NetworkInfo info = networkMap.get(networkId); - if (info != null) { return info.rpcServerUrl; } - else { return MAINNET_RPC_URL; } + if (info != null) + { + return info.rpcServerUrl; + } + else + { + return MAINNET_RPC_URL; + } } /** * This is used so as not to leak API credentials to web3; XInfuraAPI is the backup API key checked into github + * * @param networkId * @return */ - public static String getDefaultNodeURL(long networkId) { + public static String getDefaultNodeURL(long networkId) + { NetworkInfo info = networkMap.get(networkId); if (info != null) return info.rpcServerUrl; else return ""; @@ -954,9 +1021,12 @@ public static String getDefaultNodeURL(long networkId) { public static long getNetworkIdFromName(String name) { - if (!TextUtils.isEmpty(name)) { - for (int i = 0; i < networkMap.size(); i++) { - if (name.equals(networkMap.valueAt(i).name)) { + if (!TextUtils.isEmpty(name)) + { + for (int i = 0; i < networkMap.size(); i++) + { + if (name.equals(networkMap.valueAt(i).name)) + { return networkMap.valueAt(i).chainId; } } @@ -1026,7 +1096,8 @@ public Token getBlankOverrideToken(NetworkInfo networkInfo) public Single getBlankOverrideTokens(Wallet wallet) { - return Single.fromCallable(() -> { + return Single.fromCallable(() -> + { if (getBlankOverrideToken() == null) { return new Token[0]; @@ -1083,7 +1154,8 @@ public void setActiveMainnet(boolean isMainNet) preferences.setActiveMainnet(isMainNet); } - public void saveCustomRPCNetwork(String networkName, String rpcUrl, long chainId, String symbol, String blockExplorerUrl, String explorerApiUrl, boolean isTestnet, Long oldChainId) { + public void saveCustomRPCNetwork(String networkName, String rpcUrl, long chainId, String symbol, String blockExplorerUrl, String explorerApiUrl, boolean isTestnet, Long oldChainId) + { NetworkInfo builtInNetwork = builtinNetworkMap.get(chainId); boolean isCustom = builtInNetwork == null; @@ -1091,11 +1163,13 @@ public void saveCustomRPCNetwork(String networkName, String rpcUrl, long chainId customNetworks.save(info, isTestnet, oldChainId); } - public void removeCustomRPCNetwork(long chainId) { + public void removeCustomRPCNetwork(long chainId) + { customNetworks.remove(chainId); } - public static NetworkInfo getNetworkInfo(long chainId) { + public static NetworkInfo getNetworkInfo(long chainId) + { return networkMap.get(chainId); } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/NewSettingsViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/NewSettingsViewModel.java index 37ac4e09d8..2f4a6ec723 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/NewSettingsViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/NewSettingsViewModel.java @@ -3,6 +3,7 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; + import android.content.Context; import com.alphawallet.app.entity.CurrencyItem; @@ -15,6 +16,7 @@ import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.router.ManageWalletsRouter; import com.alphawallet.app.router.MyAddressRouter; +import com.alphawallet.app.service.TickerService; import com.alphawallet.app.service.TransactionsService; import com.alphawallet.app.util.LocaleUtils; @@ -26,7 +28,8 @@ import io.reactivex.Single; @HiltViewModel -public class NewSettingsViewModel extends BaseViewModel { +public class NewSettingsViewModel extends BaseViewModel +{ private final MutableLiveData defaultWallet = new MutableLiveData<>(); private final MutableLiveData transactions = new MutableLiveData<>(); @@ -38,6 +41,7 @@ public class NewSettingsViewModel extends BaseViewModel { private final LocaleRepositoryType localeRepository; private final CurrencyRepositoryType currencyRepository; private final TransactionsService transactionsService; + private final TickerService tickerService; @Inject NewSettingsViewModel( @@ -47,7 +51,9 @@ public class NewSettingsViewModel extends BaseViewModel { PreferenceRepositoryType preferenceRepository, LocaleRepositoryType localeRepository, CurrencyRepositoryType currencyRepository, - TransactionsService transactionsService) { + TransactionsService transactionsService, + TickerService tickerService) + { this.genericWalletInteract = genericWalletInteract; this.myAddressRouter = myAddressRouter; this.manageWalletsRouter = manageWalletsRouter; @@ -55,32 +61,40 @@ public class NewSettingsViewModel extends BaseViewModel { this.localeRepository = localeRepository; this.currencyRepository = currencyRepository; this.transactionsService = transactionsService; + this.tickerService = tickerService; } - public ArrayList getLocaleList(Context context) { + public ArrayList getLocaleList(Context context) + { return localeRepository.getLocaleList(context); } - public void setLocale(Context activity) { + public void setLocale(Context activity) + { String currentLocale = localeRepository.getActiveLocale(); LocaleUtils.setLocale(activity, currentLocale); } - public void updateLocale(String newLocale, Context context) { + public void updateLocale(String newLocale, Context context) + { localeRepository.setUserPreferenceLocale(newLocale); localeRepository.setLocale(context, newLocale); } - public String getDefaultCurrency(){ + public String getDefaultCurrency() + { return currencyRepository.getDefaultCurrency(); } - public ArrayList getCurrencyList() { + public ArrayList getCurrencyList() + { return currencyRepository.getCurrencyList(); } - public Single updateCurrency(String currencyCode){ + public Single updateCurrency(String currencyCode) + { currencyRepository.setDefaultCurrency(currencyCode); + tickerService.updateCurrencyConversion(); //delete tickers from realm return transactionsService.wipeTickerData(); } @@ -90,7 +104,8 @@ public String getActiveLocale() return localeRepository.getActiveLocale(); } - public void showManageWallets(Context context, boolean clearStack) { + public void showManageWallets(Context context, boolean clearStack) + { manageWalletsRouter.open(context, clearStack); } @@ -98,32 +113,42 @@ public boolean getNotificationState() { return preferenceRepository.getNotificationsState(); } + public void setNotificationState(boolean notificationState) { preferenceRepository.setNotificationState(notificationState); } @Override - protected void onCleared() { + protected void onCleared() + { super.onCleared(); } - public LiveData defaultWallet() { + public LiveData defaultWallet() + { return defaultWallet; } - public LiveData transactions() { + public LiveData transactions() + { return transactions; } - public LiveData backUpMessage() { return backUpMessage; } - public void prepare() { + public LiveData backUpMessage() + { + return backUpMessage; + } + + public void prepare() + { disposable = genericWalletInteract .find() .subscribe(this::onDefaultWallet, this::onError); } - private void onDefaultWallet(Wallet wallet) { + private void onDefaultWallet(Wallet wallet) + { defaultWallet.setValue(wallet); TestWalletBackup(); @@ -138,7 +163,8 @@ public void TestWalletBackup() } } - public void showMyAddress(Context context) { + public void showMyAddress(Context context) + { myAddressRouter.open(context, defaultWallet.getValue()); } @@ -147,7 +173,8 @@ public void setIsDismissed(String walletAddr, boolean isDismissed) genericWalletInteract.setIsDismissed(walletAddr, isDismissed); } - public void setMarshMallowWarning(boolean shown) { + public void setMarshMallowWarning(boolean shown) + { preferenceRepository.setMarshMallowWarning(shown); } } diff --git a/build.gradle b/build.gradle index c355f044db..9b76231eb6 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ buildscript { } allprojects { - //apply from: rootProject.file("codestyle.gradle") + apply from: rootProject.file("codestyle.gradle") repositories { google() diff --git a/build.sh b/build.sh index fbb6943140..75cdf3a57f 100644 --- a/build.sh +++ b/build.sh @@ -1,12 +1,6 @@ #!/usr/bin/env bash -# Temporarily revert to get builds working -# cd dmz && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -# cd lib && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -# cd util && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -# ./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt -x checkStyleMain -x checkStyleTest - -cd dmz && ../gradlew -i build && ../gradlew -i test && cd .. -cd lib && ../gradlew -i build && ../gradlew -i test && cd .. -cd util && ../gradlew -i build && ../gradlew -i test && cd .. -./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt \ No newline at end of file +cd dmz && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +cd lib && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +cd util && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. +./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt -x checkStyleMain -x checkStyleTest \ No newline at end of file diff --git a/checkstyle.xml b/checkstyle.xml index 4cde10a1e1..d1c044eded 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -80,22 +80,21 @@ + STATIC_INIT, OBJBLOCK, RECORD_DEF, COMPACT_CTOR_DEF" /> - + - + COMPACT_CTOR_DEF, LITERAL_DO" /> @@ -339,4 +338,4 @@ - \ No newline at end of file + diff --git a/e2e.sh b/e2e.sh index 2cf0d84837..801dd7b93b 100755 --- a/e2e.sh +++ b/e2e.sh @@ -31,13 +31,18 @@ startGanache & ./gradlew :app:uninstallAll :app:connectedNoAnalyticsDebugAndroidTest -x lint -PdisablePreDex -if [ "$?" != "0" ]; then - adb pull /storage/emulated/0/DCIM/ output - if [ "$1" != "--CI" ]; then - open output/DCIM/*.png - fi +if [ "$?" == "0" ]; then + stopGanache + exit 0 +fi - exit 1 +adb pull /storage/emulated/0/DCIM/ output +if [ "$1" != "--CI" ]; then + open output/DCIM/*.png fi -stopGanache \ No newline at end of file +# Copy test report +cp -r app/build/reports/androidTests/connected/flavors/noAnalytics/ output/html + +stopGanache +exit 1 \ No newline at end of file From 1e6494ae9dd46e267c199191070d75402178db95 Mon Sep 17 00:00:00 2001 From: James Brown Date: Wed, 26 Oct 2022 13:37:58 +1100 Subject: [PATCH 118/183] Update ticker contract --- .../java/com/alphawallet/app/service/TickerService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index eda5013178..aae8838856 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -10,6 +10,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.CRONOS_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.FANTOM_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; @@ -19,7 +20,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; import android.text.TextUtils; @@ -80,7 +80,7 @@ public class TickerService { private static final int UPDATE_TICKER_CYCLE = 5; //5 Minutes private static final String MEDIANIZER = "0x729D19f657BD0614b4985Cf1D82531c67569197B"; - private static final String MARKET_ORACLE_CONTRACT = "0xf155a7eb4a2993c8cf08a76bca137ee9ac0a01d8"; + private static final String MARKET_ORACLE_CONTRACT = "0xc1f9fBB5b028606D9F693319D2A6512B8fb01088"; private static final String CONTRACT_ADDR = "[CONTRACT_ADDR]"; private static final String CHAIN_IDS = "[CHAIN_ID]"; private static final String CURRENCY_TOKEN = "[CURRENCY]"; @@ -228,7 +228,7 @@ private Single updateTickersFromOracle(double conversionRate) currentConversionRate = conversionRate; return Single.fromCallable(() -> { int tickerSize = 0; - final Web3j web3j = TokenRepository.getWeb3jService(RINKEBY_ID); + final Web3j web3j = TokenRepository.getWeb3jService(GOERLI_ID); //fetch current tickers Function function = getTickers(); String responseValue = callSmartContractFunction(web3j, function, MARKET_ORACLE_CONTRACT); From d61e0372d6e1edb113c802f80fc6c5a206f5ec88 Mon Sep 17 00:00:00 2001 From: James Brown Date: Wed, 26 Oct 2022 13:38:36 +1100 Subject: [PATCH 119/183] revert codestyle project file --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9b76231eb6..c355f044db 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ buildscript { } allprojects { - apply from: rootProject.file("codestyle.gradle") + //apply from: rootProject.file("codestyle.gradle") repositories { google() From 027beea0bc9231889d599589b360846fd71d59b7 Mon Sep 17 00:00:00 2001 From: James Brown Date: Thu, 27 Oct 2022 08:12:22 +1100 Subject: [PATCH 120/183] Normalise Address display across the wallet (#2879) - Ensure full address is displayed in the ActionSheet --- .../alphawallet/app/entity/Transaction.java | 1 + .../entity/tokenscript/TokenScriptFile.java | 4 + .../app/ui/NewSettingsFragment.java | 13 +- .../java/com/alphawallet/app/util/Utils.java | 136 +++++++++++------- .../app/widget/AddressDetailView.java | 3 +- .../alphawallet/app/widget/CopyTextView.java | 20 ++- .../main/res/layout/activity_my_address.xml | 3 +- .../main/res/layout/item_address_detail.xml | 2 + .../main/res/layout/item_copy_textview.xml | 14 +- app/src/main/res/values/attrs.xml | 1 + 10 files changed, 135 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/Transaction.java b/app/src/main/java/com/alphawallet/app/entity/Transaction.java index 49524e68e5..18037a924c 100644 --- a/app/src/main/java/com/alphawallet/app/entity/Transaction.java +++ b/app/src/main/java/com/alphawallet/app/entity/Transaction.java @@ -626,6 +626,7 @@ public int getSupplementalColour(String supplementalTxt) public String getDestination(Token token) { + if (token == null) return ""; if (hasInput()) { decodeTransactionInput(token.getWallet()); diff --git a/app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenScriptFile.java b/app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenScriptFile.java index 0dac3b5df9..a7a9689839 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenScriptFile.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokenscript/TokenScriptFile.java @@ -125,6 +125,10 @@ public String calcMD5() String rand = String.valueOf(new Random(System.currentTimeMillis()).nextInt()); sb.append(rand); //never matches } + catch (Exception e) + { + Timber.w(e); + } //return complete hash return sb.toString(); diff --git a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java index 0c9bcd4e3a..727bec639c 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java @@ -43,6 +43,7 @@ import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.util.LocaleUtils; import com.alphawallet.app.util.UpdateUtils; +import com.alphawallet.app.util.Utils; import com.alphawallet.app.viewmodel.NewSettingsViewModel; import com.alphawallet.app.widget.NotificationView; import com.alphawallet.app.widget.SettingsItemView; @@ -412,14 +413,10 @@ private void onDefaultWallet(Wallet wallet) this.wallet = wallet; if (wallet.address != null) { - if (!wallet.ENSname.isEmpty()) - { - changeWalletSetting.setSubtitle(wallet.ENSname + " | " + wallet.address); - } - else - { - changeWalletSetting.setSubtitle(wallet.address); - } + String walletAddressDisplay = wallet.ENSname.isEmpty() ? wallet.address + : wallet.ENSname + " | " + Utils.formatAddress(wallet.address); + + changeWalletSetting.setSubtitle(walletAddressDisplay); } switch (wallet.authLevel) diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index 8403073d7e..0c77f05484 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -68,18 +68,19 @@ import timber.log.Timber; -public class Utils { - +public class Utils +{ private static final String ISOLATE_NUMERIC = "(0?x?[0-9a-fA-F]+)"; private static final String ICON_REPO_ADDRESS_TOKEN = "[TOKEN]"; private static final String CHAIN_REPO_ADDRESS_TOKEN = "[CHAIN]"; private static final String TOKEN_LOGO = "/logo.png"; - public static final String ALPHAWALLET_REPO_NAME = "https://raw.githubusercontent.com/alphawallet/iconassets/master/"; + public static final String ALPHAWALLET_REPO_NAME = "https://raw.githubusercontent.com/alphawallet/iconassets/master/"; private static final String TRUST_ICON_REPO_BASE = "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/"; private static final String TRUST_ICON_REPO = TRUST_ICON_REPO_BASE + CHAIN_REPO_ADDRESS_TOKEN + "/assets/" + ICON_REPO_ADDRESS_TOKEN + TOKEN_LOGO; private static final String ALPHAWALLET_ICON_REPO = ALPHAWALLET_REPO_NAME + ICON_REPO_ADDRESS_TOKEN + TOKEN_LOGO; - public static int dp2px(Context context, int dp) { + public static int dp2px(Context context, int dp) + { Resources r = context.getResources(); return (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, @@ -88,19 +89,27 @@ public static int dp2px(Context context, int dp) { ); } - public static String formatUrl(String url) { - if (URLUtil.isHttpsUrl(url) || URLUtil.isHttpUrl(url)) { + public static String formatUrl(String url) + { + if (URLUtil.isHttpsUrl(url) || URLUtil.isHttpUrl(url)) + { return url; - } else { - if (isValidUrl(url)) { + } + else + { + if (isValidUrl(url)) + { return C.HTTPS_PREFIX + url; - } else { + } + else + { return C.INTERNET_SEARCH_PREFIX + url; } } } - public static boolean isValidUrl(String url) { + public static boolean isValidUrl(String url) + { Pattern p = Patterns.WEB_URL; Matcher m = p.matcher(url.toLowerCase()); return m.matches(); @@ -146,7 +155,8 @@ public static boolean isValidValue(String testStr) return result; } - private static String getFirstWord(String text) { + private static String getFirstWord(String text) + { if (TextUtils.isEmpty(text)) return ""; text = text.trim(); int index; @@ -269,7 +279,7 @@ public static CharSequence createFormattedValue(Context ctx, String operationNam int spaceIndex = operationName.lastIndexOf(' '); if (spaceIndex > 0) { - operationName = operationName.substring(0, spaceIndex) + '\n' + operationName.substring(spaceIndex+1); + operationName = operationName.substring(0, spaceIndex) + '\n' + operationName.substring(spaceIndex + 1); } else { @@ -298,16 +308,20 @@ public static CharSequence createFormattedValue(Context ctx, String operationNam return sb; } - public static String loadJSONFromAsset(Context context, String fileName) { + public static String loadJSONFromAsset(Context context, String fileName) + { String json = null; - try { + try + { InputStream is = context.getAssets().open(fileName); int size = is.available(); byte[] buffer = new byte[size]; is.read(buffer); is.close(); json = new String(buffer, StandardCharsets.UTF_8); - } catch (IOException ex) { + } + catch (IOException ex) + { ex.printStackTrace(); return null; } @@ -374,7 +388,8 @@ public static List longListToArray(String list) public static int[] bigIntegerListToIntList(List ticketSendIndexList) { int[] indexList = new int[ticketSendIndexList.size()]; - for (int i = 0; i < ticketSendIndexList.size(); i++) indexList[i] = ticketSendIndexList.get(i).intValue(); + for (int i = 0; i < ticketSendIndexList.size(); i++) + indexList[i] = ticketSendIndexList.get(i).intValue(); return indexList; } @@ -395,6 +410,7 @@ public static BigInteger parseTokenId(String tokenIdStr) /** * Produce a string CSV of integer IDs given an input list of values + * * @param idList * @param keepZeros * @return @@ -453,7 +469,7 @@ public static String integerListToString(List intList, boolean keepZero for (Integer id : intList) { if (!keepZeros && id == 0) continue; - if (!first)sb.append(","); + if (!first) sb.append(","); sb.append(id); first = false; } @@ -478,7 +494,10 @@ public static boolean isNumeric(String numString) for (int i = 0; i < numString.length(); i++) { - if (Character.digit(numString.charAt(i), 10) == -1) { return false; } + if (Character.digit(numString.charAt(i), 10) == -1) + { + return false; + } } return true; @@ -491,7 +510,10 @@ public static boolean isHex(String hexStr) for (int i = 0; i < hexStr.length(); i++) { - if (Character.digit(hexStr.charAt(i), 16) == -1) { return false; } + if (Character.digit(hexStr.charAt(i), 16) == -1) + { + return false; + } } return true; @@ -518,7 +540,8 @@ public static String isolateNumeric(String valueFromInput) return valueFromInput; } - public static String formatAddress(String address) { + public static String formatAddress(String address) + { if (isAddressValid(address)) { address = Keys.toChecksumAddress(address); @@ -535,12 +558,15 @@ public static String formatAddress(String address) { /** * Just enough for diagnosis of most errors + * * @param s String to be HTML escaped * @return escaped string */ - public static String escapeHTML(String s) { + public static String escapeHTML(String s) + { StringBuilder out = new StringBuilder(Math.max(16, s.length())); - for (int i = 0; i < s.length(); i++) { + for (int i = 0; i < s.length(); i++) + { char c = s.charAt(i); switch (c) { @@ -565,12 +591,12 @@ public static String escapeHTML(String s) { public static String convertTimePeriodInSeconds(long pendingTimeInSeconds, Context ctx) { - long days = pendingTimeInSeconds/(60*60*24); - pendingTimeInSeconds -= (days*60*60*24); - long hours = pendingTimeInSeconds/(60*60); - pendingTimeInSeconds -= (hours*60*60); - long minutes = pendingTimeInSeconds/60; - long seconds = pendingTimeInSeconds%60; + long days = pendingTimeInSeconds / (60 * 60 * 24); + pendingTimeInSeconds -= (days * 60 * 60 * 24); + long hours = pendingTimeInSeconds / (60 * 60); + pendingTimeInSeconds -= (hours * 60 * 60); + long minutes = pendingTimeInSeconds / 60; + long seconds = pendingTimeInSeconds % 60; StringBuilder sb = new StringBuilder(); int timePoints = 0; @@ -647,12 +673,12 @@ public static String convertTimePeriodInSeconds(long pendingTimeInSeconds, Conte public static String shortConvertTimePeriodInSeconds(long pendingTimeInSeconds, Context ctx) { - long days = pendingTimeInSeconds/(60*60*24); - pendingTimeInSeconds -= (days*60*60*24); - long hours = pendingTimeInSeconds/(60*60); - pendingTimeInSeconds -= (hours*60*60); - long minutes = pendingTimeInSeconds/60; - long seconds = pendingTimeInSeconds%60; + long days = pendingTimeInSeconds / (60 * 60 * 24); + pendingTimeInSeconds -= (days * 60 * 60 * 24); + long hours = pendingTimeInSeconds / (60 * 60); + pendingTimeInSeconds -= (hours * 60 * 60); + long minutes = pendingTimeInSeconds / 60; + long seconds = pendingTimeInSeconds % 60; String timeStr; @@ -672,7 +698,7 @@ else if (hours > 0) } else { - BigDecimal hourStr = BigDecimal.valueOf(hours + (double)minutes/60.0) + BigDecimal hourStr = BigDecimal.valueOf(hours + (double) minutes / 60.0) .setScale(1, RoundingMode.HALF_DOWN); //to 1 dp timeStr = ctx.getString(R.string.hour_plural, hourStr.toString()); } @@ -685,7 +711,7 @@ else if (minutes > 0) } else { - BigDecimal minsStr = BigDecimal.valueOf(minutes + (double)seconds/60.0) + BigDecimal minsStr = BigDecimal.valueOf(minutes + (double) seconds / 60.0) .setScale(1, RoundingMode.HALF_DOWN); //to 1 dp timeStr = ctx.getString(R.string.minute_plural, minsStr.toString()); } @@ -720,7 +746,8 @@ public static String localiseUnixDate(Context ctx, long timeStampInSec) return timeFormat.format(date) + " | " + dateFormat.format(date); } - public static long randomId() { + public static long randomId() + { return new Date().getTime(); } @@ -770,7 +797,8 @@ public static String getTokenAddrFromAWUrl(String url) return ""; } - private static final Map twChainNames = new HashMap() { + private static final Map twChainNames = new HashMap() + { { put(CLASSIC_ID, "classic"); put(GNOSIS_ID, "xdai"); @@ -840,16 +868,21 @@ private static boolean shouldBeIPFS(String url) return url.startsWith("Qm") && url.length() == 46 && !url.contains(".") && !url.contains("/"); } - public static String loadFile(Context context, @RawRes int rawRes) { + public static String loadFile(Context context, @RawRes int rawRes) + { byte[] buffer = new byte[0]; - try { + try + { InputStream in = context.getResources().openRawResource(rawRes); buffer = new byte[in.available()]; int len = in.read(buffer); - if (len < 1) { + if (len < 1) + { throw new IOException("Nothing is read."); } - } catch (Exception ex) { + } + catch (Exception ex) + { Timber.tag("READ_JS_TAG").d(ex, "Ex"); } return new String(buffer); @@ -861,12 +894,14 @@ public static long timeUntil(long eventInMillis) } //TODO: detect various App Library installs and re-direct appropriately - public static boolean verifyInstallerId(Context context) { + public static boolean verifyInstallerId(Context context) + { try { PackageManager packageManager = context.getPackageManager(); String installingPackageName; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + { final InstallSourceInfo installer = packageManager.getInstallSourceInfo(context.getPackageName()); installingPackageName = installer.getInstallingPackageName(); } @@ -891,16 +926,20 @@ public static boolean isTransactionHash(String input) if (input == null || (input.length() != 66 && input.length() != 64)) return false; String cleanInput = Numeric.cleanHexPrefix(input); - try { + try + { Numeric.toBigIntNoPrefix(cleanInput); - } catch (NumberFormatException e) { + } + catch (NumberFormatException e) + { return false; } return cleanInput.length() == 64; } - public static @ColorInt int getColorFromAttr(Context context, int resId) + public static @ColorInt + int getColorFromAttr(Context context, int resId) { TypedValue typedValue = new TypedValue(); Resources.Theme theme = context.getTheme(); @@ -980,7 +1019,8 @@ else if (context instanceof ContextWrapper) } } - public static String removeDoubleQuotes(String string) { + public static String removeDoubleQuotes(String string) + { return string != null ? string.replace("\"", "") : null; } } diff --git a/app/src/main/java/com/alphawallet/app/widget/AddressDetailView.java b/app/src/main/java/com/alphawallet/app/widget/AddressDetailView.java index c9c6c5069e..688d5de6a8 100644 --- a/app/src/main/java/com/alphawallet/app/widget/AddressDetailView.java +++ b/app/src/main/java/com/alphawallet/app/widget/AddressDetailView.java @@ -57,7 +57,8 @@ private void getAttrs(Context context, AttributeSet attrs) public void setupAddress(String address, String ensName, Token destToken) { - String destStr = (!TextUtils.isEmpty(ensName) ? ensName + " | " : "") + Utils.formatAddress(address); + boolean hasEns = !TextUtils.isEmpty(ensName); + String destStr = (hasEns ? ensName + " | " : "") + (hasEns ? Utils.formatAddress(address) : address); textAddressSummary.setText(destStr); userAvatar.bind(new Wallet(address), wallet -> { /*NOP, here to enable lookup of ENS avatar*/ }); textFullAddress.setText(address); diff --git a/app/src/main/java/com/alphawallet/app/widget/CopyTextView.java b/app/src/main/java/com/alphawallet/app/widget/CopyTextView.java index b07fdf4aae..a6ae83075d 100644 --- a/app/src/main/java/com/alphawallet/app/widget/CopyTextView.java +++ b/app/src/main/java/com/alphawallet/app/widget/CopyTextView.java @@ -14,8 +14,8 @@ import com.alphawallet.app.R; import com.google.android.material.button.MaterialButton; -public class CopyTextView extends LinearLayout { - +public class CopyTextView extends LinearLayout +{ public static final String KEY_ADDRESS = "key_address"; private final Context context; @@ -23,6 +23,7 @@ public class CopyTextView extends LinearLayout { private int textResId; private int gravity; + private int lines; private boolean showToast; private boolean boldFont; private boolean removePadding; @@ -56,6 +57,7 @@ private void getAttrs(Context context, AttributeSet attrs) boldFont = a.getBoolean(R.styleable.CopyTextView_bold, false); removePadding = a.getBoolean(R.styleable.CopyTextView_removePadding, false); marginRight = a.getDimension(R.styleable.CopyTextView_marginRight, 0.0f); + lines = a.getInt(R.styleable.CopyTextView_lines, 1); } finally { @@ -65,7 +67,17 @@ private void getAttrs(Context context, AttributeSet attrs) private void bindViews() { - button = findViewById(R.id.button); + if (lines == 2) + { + button = findViewById(R.id.button_address); + findViewById(R.id.button).setVisibility(View.GONE); + button.setVisibility(View.VISIBLE); + } + else + { + button = findViewById(R.id.button); + } + setText(getContext().getString(textResId)); button.setOnClickListener(v -> copyToClipboard()); } @@ -98,6 +110,8 @@ private void copyToClipboard() } if (showToast) + { Toast.makeText(context, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show(); + } } } diff --git a/app/src/main/res/layout/activity_my_address.xml b/app/src/main/res/layout/activity_my_address.xml index 7f92a97420..835a1c2dbc 100644 --- a/app/src/main/res/layout/activity_my_address.xml +++ b/app/src/main/res/layout/activity_my_address.xml @@ -78,7 +78,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" - custom:bold="true" /> + custom:lines="2" + custom:bold="true"/> diff --git a/app/src/main/res/layout/item_address_detail.xml b/app/src/main/res/layout/item_address_detail.xml index 53aaf238f2..3e70d3d3ab 100644 --- a/app/src/main/res/layout/item_address_detail.xml +++ b/app/src/main/res/layout/item_address_detail.xml @@ -34,6 +34,8 @@ android:layout_marginHorizontal="@dimen/small_12" android:layout_weight="3.5" android:gravity="start" + android:lines="2" + android:maxLines="2" tools:text="pablo.eth | 0x123456...0421" /> + tools:text="0xbc9a1026a4bc6f0ba8bbe486d1d09da5732b39e4"/> + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index ca7e42edde..079fbaad27 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -76,6 +76,7 @@ + From 5b7c62446066a4e466ab78d8bb5bfa52f86a5d81 Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 28 Oct 2022 13:00:05 +1100 Subject: [PATCH 121/183] Update ticker receive --- .../com/alphawallet/app/service/TickerService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index aae8838856..098544e7b2 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -10,7 +10,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.CRONOS_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.FANTOM_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.IOTEX_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; @@ -20,6 +19,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; import android.text.TextUtils; @@ -78,9 +78,9 @@ public class TickerService { - private static final int UPDATE_TICKER_CYCLE = 5; //5 Minutes + private static final int UPDATE_TICKER_CYCLE = 1; //5 Minutes private static final String MEDIANIZER = "0x729D19f657BD0614b4985Cf1D82531c67569197B"; - private static final String MARKET_ORACLE_CONTRACT = "0xc1f9fBB5b028606D9F693319D2A6512B8fb01088"; + private static final String MARKET_ORACLE_CONTRACT = "0xdAcAf435f241B1a062B021abEED9CA2F76F22F8D"; private static final String CONTRACT_ADDR = "[CONTRACT_ADDR]"; private static final String CHAIN_IDS = "[CHAIN_ID]"; private static final String CURRENCY_TOKEN = "[CURRENCY]"; @@ -91,7 +91,7 @@ public class TickerService private static final String CURRENCY_CONV = "currency"; private static final boolean ALLOW_UNVERIFIED_TICKERS = false; //allows verified:false tickers from DEX.GURU. Not recommended public static final long TICKER_TIMEOUT = DateUtils.WEEK_IN_MILLIS; //remove ticker if not seen in one week - public static final long TICKER_STALE_TIMEOUT = 15 * DateUtils.MINUTE_IN_MILLIS; //try to use market API if AlphaWallet market oracle not updating + public static final long TICKER_STALE_TIMEOUT = 30 * DateUtils.MINUTE_IN_MILLIS; //Use market API if AlphaWallet market oracle not updating private final OkHttpClient httpClient; private final PreferenceRepositoryType sharedPrefs; @@ -228,8 +228,8 @@ private Single updateTickersFromOracle(double conversionRate) currentConversionRate = conversionRate; return Single.fromCallable(() -> { int tickerSize = 0; - final Web3j web3j = TokenRepository.getWeb3jService(GOERLI_ID); - //fetch current tickers + final Web3j web3j = TokenRepository.getWeb3jService(POLYGON_TEST_ID); + //fetch current tickerscd Function function = getTickers(); String responseValue = callSmartContractFunction(web3j, function, MARKET_ORACLE_CONTRACT); List responseValues = FunctionReturnDecoder.decode(responseValue, function.getOutputParameters()); From 4f5555218bd96ee532e247f1b9e7e0b14f2c7610 Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 28 Oct 2022 14:35:48 +1100 Subject: [PATCH 122/183] Remove install intent (#2886) --- .../com/alphawallet/app/ui/HomeActivity.java | 30 +------------------ .../app/viewmodel/HomeViewModel.java | 5 ---- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java index 81e9fb3041..8d19e874f4 100644 --- a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java @@ -39,7 +39,6 @@ import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; -import androidx.core.content.FileProvider; import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsControllerCompat; @@ -52,7 +51,6 @@ import androidx.viewpager2.adapter.FragmentStateAdapter; import androidx.viewpager2.widget.ViewPager2; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.api.v1.entity.request.ApiV1Request; @@ -87,7 +85,6 @@ import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent; -import java.io.File; import java.lang.reflect.Method; import java.net.URLDecoder; import java.util.List; @@ -242,7 +239,6 @@ public void onPageScrollStateChanged(int state) dissableDisplayHomeAsUp(); viewModel.error().observe(this, this::onError); - viewModel.installIntent().observe(this, this::onInstallIntent); viewModel.walletName().observe(this, this::onWalletName); viewModel.backUpMessage().observe(this, this::onBackup); viewModel.splashReset().observe(this, this::onRequireInit); @@ -278,6 +274,7 @@ public void onPageScrollStateChanged(int state) else { //TODO: Check we are using latest version on github, since we're using a downloaded/manually installed version + //TODO: Also add a build exclusion so this code only appears if it's a noAnalytics build. //First check that this the package name is "io.stormbird.wallet" - it could be a fork } @@ -925,31 +922,6 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in } } - private void onInstallIntent(File installFile) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - { - String authority = BuildConfig.APPLICATION_ID + ".fileprovider"; - Uri apkUri = FileProvider.getUriForFile(getApplicationContext(), authority, installFile); - Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); - intent.setData(apkUri); - intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivity(intent); - } - else - { - Uri apkUri = Uri.fromFile(installFile); - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - } - - //Blank install time here so that next time the app runs the install time will be correctly set up - viewModel.setInstallTime(0); - finish(); - } - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java index f737f113e9..aa9e56c8c1 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java @@ -123,7 +123,6 @@ public class HomeViewModel extends BaseViewModel { private CryptoFunctions cryptoFunctions; private ParseMagicLink parser; - private final MutableLiveData installIntent = new MutableLiveData<>(); private final MutableLiveData walletName = new MutableLiveData<>(); private final MutableLiveData defaultWallet = new MutableLiveData<>(); private final MutableLiveData splashActivity = new MutableLiveData<>(); @@ -173,10 +172,6 @@ public LiveData transactions() { return transactions; } - public LiveData installIntent() { - return installIntent; - } - public LiveData backUpMessage() { return backUpMessage; } From 513b58d90fc3c763a1ee97fb8a3f03b00e698303 Mon Sep 17 00:00:00 2001 From: micwallace Date: Fri, 28 Oct 2022 02:26:41 -0500 Subject: [PATCH 123/183] feat: allow copy of NFT contract address from NFTAssetDetailActivity (#2840) * feat: allow copy of NFT contract address from NFTAssetDetailActivity * Refactor + add copy icon Co-authored-by: justindg --- .../app/ui/NFTAssetDetailActivity.java | 3 +- .../alphawallet/app/widget/TokenInfoView.java | 33 +++++++++++++++++++ app/src/main/res/layout/item_token_info.xml | 2 ++ 3 files changed, 36 insertions(+), 2 deletions(-) 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 a5b0112605..a7750bbfcb 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetDetailActivity.java @@ -35,7 +35,6 @@ import com.alphawallet.app.service.GasService; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.ui.widget.entity.NFTAttributeLayout; -import com.alphawallet.app.util.Utils; import com.alphawallet.app.viewmodel.TokenFunctionViewModel; import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; @@ -310,7 +309,7 @@ private void updateDefaultTokenData() tivNetwork.setValue(token.getNetworkName()); - tivContractAddress.setValue(Utils.formatAddress(token.tokenInfo.address)); + tivContractAddress.setCopyableValue(token.tokenInfo.address); } private void loadAssetFromMetadata(NFTAsset asset) diff --git a/app/src/main/java/com/alphawallet/app/widget/TokenInfoView.java b/app/src/main/java/com/alphawallet/app/widget/TokenInfoView.java index 956f177321..4d13f0149f 100644 --- a/app/src/main/java/com/alphawallet/app/widget/TokenInfoView.java +++ b/app/src/main/java/com/alphawallet/app/widget/TokenInfoView.java @@ -1,5 +1,9 @@ package com.alphawallet.app.widget; +import static android.content.Context.CLIPBOARD_SERVICE; + +import android.content.ClipData; +import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.res.TypedArray; @@ -9,11 +13,13 @@ import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; +import android.widget.Toast; import androidx.core.content.ContextCompat; import com.alphawallet.app.R; import com.alphawallet.app.service.TickerService; +import com.alphawallet.app.util.Utils; public class TokenInfoView extends LinearLayout { @@ -79,6 +85,33 @@ public void setValue(String text) } } + public void setCopyableValue(String text) + { + if (!TextUtils.isEmpty(text)) + { + setVisibility(View.VISIBLE); + String display = text; + // If text is an instance of an address, format it; otherwise do nothing + if (Utils.isAddressValid(text)) + { + display = Utils.formatAddress(text); + } + TextView useView = getTextView(display.length()); + useView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_copy, 0); + useView.setText(display); + setCopyListener(useView, label.getText(), text); + } + } + + private void setCopyListener(TextView textView, CharSequence clipLabel, CharSequence clipValue) + { + textView.setOnClickListener(view -> { + ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(CLIPBOARD_SERVICE); + clipboard.setPrimaryClip(ClipData.newPlainText(clipLabel, clipValue)); + Toast.makeText(getContext(), R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show(); + }); + } + public void setCurrencyValue(double v) { setVisibility(View.VISIBLE); diff --git a/app/src/main/res/layout/item_token_info.xml b/app/src/main/res/layout/item_token_info.xml index a934824cae..9ad3f9b45f 100644 --- a/app/src/main/res/layout/item_token_info.xml +++ b/app/src/main/res/layout/item_token_info.xml @@ -29,6 +29,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="0.6" + android:drawablePadding="@dimen/tiny_8" android:ellipsize="end" android:gravity="end" android:singleLine="true" @@ -40,6 +41,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="0.6" + android:drawablePadding="@dimen/tiny_8" android:ellipsize="end" android:gravity="end" android:maxLines="2" From 69ed135773e16684b11041e833d2441d460a3450 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Fri, 28 Oct 2022 15:27:53 +0800 Subject: [PATCH 124/183] Run CI on MacOS/Windows/Ubuntu (#2883) * Run CI on Ubuntu * Add CI job for Ubuntu * Fix codecov URL * Run CI on Windows * Run checkStyle on mutiple OS --- .github/workflows/checkstyle.yml | 5 ++- .github/workflows/ci-ubuntu.yml | 33 +++++++++++++++++++ .github/workflows/ci-windows.yml | 33 +++++++++++++++++++ .github/workflows/ci.yml | 2 +- .../app/TransactionDecodingTest.java | 2 +- build.gradle | 2 +- 6 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/ci-ubuntu.yml create mode 100644 .github/workflows/ci-windows.yml diff --git a/.github/workflows/checkstyle.yml b/.github/workflows/checkstyle.yml index f873d426f3..88987fcd84 100644 --- a/.github/workflows/checkstyle.yml +++ b/.github/workflows/checkstyle.yml @@ -4,7 +4,10 @@ on: jobs: lint: name: Run CheckStyle - runs-on: macos-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/ci-ubuntu.yml b/.github/workflows/ci-ubuntu.yml new file mode 100644 index 0000000000..54be4252b6 --- /dev/null +++ b/.github/workflows/ci-ubuntu.yml @@ -0,0 +1,33 @@ +name: Unit test(Ubuntu) +on: + push: + branches: + - master + pull_request: +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK + uses: actions/setup-java@v3 + with: + distribution: zulu + java-version: 11 + + - name: Run unit tests + run: sh ./build.sh + + - name: Upload Test Reports Folder + uses: actions/upload-artifact@v2 + if: ${{ always() }} # IMPORTANT: Upload reports regardless of status + with: + name: ut-reports + path: app/build/reports/tests + + - name: Upload coverage reports to Codecov + run: | + curl -Os https://uploader.codecov.io/latest/linux/codecov + chmod +x codecov + ./codecov \ No newline at end of file diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml new file mode 100644 index 0000000000..e93ff358ce --- /dev/null +++ b/.github/workflows/ci-windows.yml @@ -0,0 +1,33 @@ +name: Unit test(Windows) +on: + push: + branches: + - master + pull_request: +jobs: + test: + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK + uses: actions/setup-java@v3 + with: + distribution: zulu + java-version: 11 + + - name: Run unit tests + run: sh ./build.sh + + - name: Upload Test Reports Folder + uses: actions/upload-artifact@v2 + if: ${{ always() }} # IMPORTANT: Upload reports regardless of status + with: + name: ut-reports + path: app/build/reports/tests + + - name: Upload coverage reports to Codecov + run: | + curl -Os https://uploader.codecov.io/latest/windows/codecov + chmod +x codecov + ./codecov \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0aab75e294..21e6c53f4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Unit test +name: Unit test(MacOS) on: push: branches: diff --git a/app/src/test/java/com/alphawallet/app/TransactionDecodingTest.java b/app/src/test/java/com/alphawallet/app/TransactionDecodingTest.java index 611b7d97fe..b604fc29b1 100644 --- a/app/src/test/java/com/alphawallet/app/TransactionDecodingTest.java +++ b/app/src/test/java/com/alphawallet/app/TransactionDecodingTest.java @@ -94,7 +94,7 @@ public void testBuildFunctionCallText() throws IOException default: break; } - stringBuilder.append(transactionInput.buildFunctionCallText()).append("\n"); + stringBuilder.append(transactionInput.buildFunctionCallText()).append(System.lineSeparator()); } } assertThat(stringBuilder.toString(), equalTo(getBaseline())); diff --git a/build.gradle b/build.gradle index c355f044db..9b76231eb6 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ buildscript { } allprojects { - //apply from: rootProject.file("codestyle.gradle") + apply from: rootProject.file("codestyle.gradle") repositories { google() From 32f60498b5d3236cb4a7e98a6b2b38d824fa81f8 Mon Sep 17 00:00:00 2001 From: James Brown Date: Sun, 30 Oct 2022 07:40:50 +1100 Subject: [PATCH 125/183] Bump gradle for point release resolve deprecated testnet RPCs --- app/build.gradle | 4 +-- .../app/repository/EthereumNetworkBase.java | 31 ++++++++----------- .../app/service/TickerService.java | 4 +-- build.gradle | 2 +- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index cc1f2ee95f..83394ce917 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -85,8 +85,8 @@ android { } } defaultConfig { - versionCode 204 - versionName "3.60" + versionCode 205 + versionName "3.61" applicationId "io.stormbird.wallet" minSdkVersion 23 diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 64a0bf64ef..2c386047bc 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -122,21 +122,15 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String FREE_MAINNET_RPC_URL = "https://rpc.ankr.com/eth"; public static final String FREE_POLYGON_RPC_URL = "https://polygon-rpc.com"; public static final String FREE_ARBITRUM_RPC_URL = "https://arbitrum.public-rpc.com"; - public static final String FREE_RINKEBY_RPC_URL = "https://rpc.ankr.com/eth_rinkeby"; public static final String FREE_GOERLI_RPC_URL = "https://rpc.ankr.com/eth_goerli"; public static final String FREE_MUMBAI_RPC_URL = "https://rpc-mumbai.maticvigil.com"; public static final String FREE_ARBITRUM_TEST_RPC_URL = "https://rinkeby.arbitrum.io/rpc"; - public static final String FREE_KOVAN_RPC_URL = "https://kovan.poa.network"; public static final String FREE_PALM_RPC_URL = "https://palm-mainnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b"; public static final String FREE_PALM_TEST_RPC_URL = "https://palm-testnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b"; public static final String FREE_CRONOS_MAIN_BETA_RPC_URL = "https://evm.cronos.org"; public static final String MAINNET_RPC_URL = usesProductionKey ? "https://mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_MAINNET_RPC_URL; - public static final String RINKEBY_RPC_URL = usesProductionKey ? "https://rinkeby.infura.io/v3/" + keyProvider.getInfuraKey() - : FREE_RINKEBY_RPC_URL; - public static final String KOVAN_RPC_URL = usesProductionKey ? "https://kovan.infura.io/v3/" + keyProvider.getInfuraKey() - : FREE_KOVAN_RPC_URL; public static final String GOERLI_RPC_URL = usesProductionKey ? "https://goerli.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_GOERLI_RPC_URL; public static final String POLYGON_RPC_URL = usesProductionKey ? "https://polygon-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() @@ -147,10 +141,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy : FREE_MUMBAI_RPC_URL; public static final String OPTIMISTIC_MAIN_URL = usesProductionKey ? "https://optimism-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : OPTIMISTIC_MAIN_FALLBACK_URL; - public static final String OPTIMISTIC_TEST_URL = usesProductionKey ? "https://optimism-kovan.infura.io/v3/" + keyProvider.getInfuraKey() - : OPTIMISTIC_TEST_FALLBACK_URL; - public static final String ARBITRUM_TESTNET_RPC = usesProductionKey ? "https://arbitrum-rinkeby.infura.io/v3/" + keyProvider.getInfuraKey() - : FREE_ARBITRUM_TEST_RPC_URL; public static final String PALM_RPC_URL = usesProductionKey ? "https://palm-mainnet.infura.io/v3/" + keyProvider.getInfuraKey() : FREE_PALM_RPC_URL; public static final String PALM_TEST_RPC_URL = usesProductionKey ? "https://palm-testnet.infura.io/v3/" + keyProvider.getInfuraKey() @@ -163,22 +153,27 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy // Use the "Free" routes as backup in order to diversify node usage; to avoid single point of failure public static final String MAINNET_FALLBACK_RPC_URL = usesProductionKey ? FREE_MAINNET_RPC_URL : "https://mainnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); - public static final String RINKEBY_FALLBACK_RPC_URL = usesProductionKey ? FREE_RINKEBY_RPC_URL : "https://rinkeby.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); - public static final String KOVAN_FALLBACK_RPC_URL = usesProductionKey ? FREE_KOVAN_RPC_URL : "https://kovan.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); public static final String GOERLI_FALLBACK_RPC_URL = usesProductionKey ? FREE_GOERLI_RPC_URL : "https://goerli.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); public static final String ARBITRUM_FALLBACK_MAINNET_RPC = usesProductionKey ? FREE_ARBITRUM_RPC_URL : "https://arbitrum-mainnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); public static final String PALM_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-mainnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); public static final String PALM_TEST_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-testnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); + //Deprecated: for now these RPCs still work + public static final String ROPSTEN_RPC_URL = "https://rpc.ankr.com/eth_ropsten"; + public static final String RINKEBY_RPC_URL = "https://rpc.ankr.com/eth_rinkeby"; + public static final String ARBITRUM_TESTNET_RPC = FREE_ARBITRUM_TEST_RPC_URL; + public static final String SOKOL_RPC_URL = "https://sokol.poa.network"; + + //These Networks are no longer running + public static final String KOVAN_RPC_URL = "https://kovan.poa.network"; + public static final String OPTIMISTIC_TEST_URL = OPTIMISTIC_TEST_FALLBACK_URL; + //Note that AlphaWallet now uses a double node configuration. See class AWHttpService comment 'try primary node'. //If you supply a main RPC and secondary it will try the secondary if the primary node times out after 10 seconds. //See the declaration of NetworkInfo - it has a member backupNodeUrl. Put your secondary node here. - public static final String ROPSTEN_FALLBACK_RPC_URL = "https://ropsten.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); public static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; public static final String POA_RPC_URL = "https://core.poa.network/"; - public static final String ROPSTEN_RPC_URL = "https://ropsten.infura.io/v3/" + keyProvider.getInfuraKey(); - public static final String SOKOL_RPC_URL = "https://sokol.poa.network"; public static final String ARTIS_SIGMA1_RPC_URL = "https://rpc.sigma1.artis.network"; public static final String ARTIS_TAU1_RPC_URL = "https://rpc.tau1.artis.network"; public static final String BINANCE_TEST_RPC_URL = "https://data-seed-prebsc-1-s3.binance.org:8545"; @@ -363,15 +358,15 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(ROPSTEN_ID, new NetworkInfo(C.ROPSTEN_NETWORK_NAME, C.ETH_SYMBOL, ROPSTEN_RPC_URL, "https://ropsten.etherscan.io/tx/", ROPSTEN_ID, - ROPSTEN_FALLBACK_RPC_URL, "https://api-ropsten.etherscan.io/api?")); + ROPSTEN_RPC_URL, "https://api-ropsten.etherscan.io/api?")); put(RINKEBY_ID, new NetworkInfo(C.RINKEBY_NETWORK_NAME, C.ETH_SYMBOL, RINKEBY_RPC_URL, "https://rinkeby.etherscan.io/tx/", RINKEBY_ID, - RINKEBY_FALLBACK_RPC_URL, "https://api-rinkeby.etherscan.io/api?")); + RINKEBY_RPC_URL, "https://api-rinkeby.etherscan.io/api?")); put(KOVAN_ID, new NetworkInfo(C.KOVAN_NETWORK_NAME, C.ETH_SYMBOL, KOVAN_RPC_URL, "https://kovan.etherscan.io/tx/", KOVAN_ID, - KOVAN_FALLBACK_RPC_URL, "https://api-kovan.etherscan.io/api?")); + KOVAN_RPC_URL, "https://api-kovan.etherscan.io/api?")); put(SOKOL_ID, new NetworkInfo(C.SOKOL_NETWORK_NAME, C.POA_SYMBOL, SOKOL_RPC_URL, "https://blockscout.com/poa/sokol/tx/", SOKOL_ID, diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index 098544e7b2..152db1d135 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -78,7 +78,7 @@ public class TickerService { - private static final int UPDATE_TICKER_CYCLE = 1; //5 Minutes + private static final int UPDATE_TICKER_CYCLE = 5; //5 Minutes private static final String MEDIANIZER = "0x729D19f657BD0614b4985Cf1D82531c67569197B"; private static final String MARKET_ORACLE_CONTRACT = "0xdAcAf435f241B1a062B021abEED9CA2F76F22F8D"; private static final String CONTRACT_ADDR = "[CONTRACT_ADDR]"; @@ -229,7 +229,7 @@ private Single updateTickersFromOracle(double conversionRate) return Single.fromCallable(() -> { int tickerSize = 0; final Web3j web3j = TokenRepository.getWeb3jService(POLYGON_TEST_ID); - //fetch current tickerscd + //fetch current tickers Function function = getTickers(); String responseValue = callSmartContractFunction(web3j, function, MARKET_ORACLE_CONTRACT); List responseValues = FunctionReturnDecoder.decode(responseValue, function.getOutputParameters()); diff --git a/build.gradle b/build.gradle index 9b76231eb6..c355f044db 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ buildscript { } allprojects { - apply from: rootProject.file("codestyle.gradle") + //apply from: rootProject.file("codestyle.gradle") repositories { google() From 6e4619fe3e3578b994b955da6e8af6a2e6196aea Mon Sep 17 00:00:00 2001 From: justindg Date: Tue, 1 Nov 2022 22:00:46 -0700 Subject: [PATCH 126/183] Update drawable to use solid instead of gradient (#2897) --- app/src/main/res/drawable/select_masking_circle.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/res/drawable/select_masking_circle.xml b/app/src/main/res/drawable/select_masking_circle.xml index d461be3579..7e8004539e 100644 --- a/app/src/main/res/drawable/select_masking_circle.xml +++ b/app/src/main/res/drawable/select_masking_circle.xml @@ -4,8 +4,5 @@ android:shape="ring" android:thicknessRatio="1" android:useLevel="false"> - + \ No newline at end of file From e3824e7df9c39928085a917cdecf14fda7b850fa Mon Sep 17 00:00:00 2001 From: James Brown Date: Wed, 2 Nov 2022 16:01:39 +1100 Subject: [PATCH 127/183] Fix custom RPC node entry (#2893) * Parse RPC from Dapps * Warn user if invalid RPC * Fix formatting and add test case. Note that in order for the URL Pattern to be visible for plain Java we need to extract the Pattern code from the Android OS repo. Hence the new file. --- .../app/repository/EthereumNetworkBase.java | 26 +++--- .../app/ui/DappBrowserFragment.java | 31 +++++++- .../java/com/alphawallet/app/util/Utils.java | 2 +- .../app/util/pattern/Patterns.java | 79 +++++++++++++++++++ .../app/viewmodel/DappBrowserViewModel.java | 51 ++++++++++-- .../java/com/alphawallet/app/ENSTest.java | 2 +- .../com/alphawallet/app/URLUtilsTest.java | 51 ++++++++++++ 7 files changed, 221 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/util/pattern/Patterns.java create mode 100644 app/src/test/java/com/alphawallet/app/URLUtilsTest.java diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 2c386047bc..455d5e352c 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -3,6 +3,7 @@ /* Please don't add import android at this point. Later this file will be shared * between projects including non-Android projects */ +import static com.alphawallet.app.util.Utils.isValidUrl; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_MAIN_ID; @@ -26,6 +27,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.FANTOM_TEST_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.FUJI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.FUJI_TEST_RPC_URL; +import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.HECO_RPC_URL; @@ -41,31 +43,30 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_RPC; +import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_TEST_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_TEST_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISM_GOERLI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_FALLBACK_URL; +import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_TEST_FALLBACK_URL; +import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_TEST_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_NETWORK_V2_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_RPC; -import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_TEST_RPC; -import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.SEPOLIA_TESTNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.SEPOLIA_TESTNET_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.SOKOL_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_RPC_URL; import android.text.TextUtils; @@ -622,6 +623,11 @@ public void restore() for (NetworkInfo info : list) { + if (!isValidUrl(info.rpcServerUrl)) //ensure RPC doesn't contain malicious code + { + continue; + } + networkMap.put(info.chainId, info); Boolean value = mapToTestNet.get(info.chainId); boolean isTestnet = value != null && value; diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index df3471244d..a390ca4f03 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -631,6 +631,8 @@ private void setupAddressBar() // Both these are required, the onFocus listener is required to respond to the first click. urlTv.setOnFocusChangeListener((v, hasFocus) -> { //see if we have focus flag + loadOnInit = null; + loadUrlAfterReload = null; if (hasFocus && focusFlag && getActivity() != null) openURLInputView(); }); @@ -1238,8 +1240,14 @@ public void onWalletAddEthereumChainObject(long callbackId, WalletAddEthereumCha { // show add custom chain dialog addCustomChainDialog = new AddEthereumChainPrompt(getContext(), chainObj, chainObject -> { - viewModel.addCustomChain(chainObject); - loadNewNetwork(chainObj.getChainId()); + if (viewModel.addCustomChain(chainObject)) + { + loadNewNetwork(chainObj.getChainId()); + } + else + { + displayError(R.string.error_invalid_url, 0); + } addCustomChainDialog.dismiss(); }); addCustomChainDialog.show(); @@ -1438,6 +1446,23 @@ private void txError(Throwable throwable) confirmationDialog.dismiss(); } + private void displayError(int title, int text) + { + if (resultDialog != null && resultDialog.isShowing()) resultDialog.dismiss(); + resultDialog = new AWalletAlertDialog(requireContext()); + resultDialog.setIcon(ERROR); + resultDialog.setTitle(title); + if (text != 0) resultDialog.setMessage(text); + resultDialog.setButtonText(R.string.button_ok); + resultDialog.setButtonListener(v -> { + resultDialog.dismiss(); + }); + resultDialog.show(); + + if (confirmationDialog != null && confirmationDialog.isShowing()) + confirmationDialog.dismiss(); + } + private void showWalletWatch() { if (resultDialog != null && resultDialog.isShowing()) resultDialog.dismiss(); @@ -1539,7 +1564,7 @@ private void checkBackClickArrowVisibility() } else { - nextUrl = urlTv.getText().toString();// web3.getUrl();// getDefaultDappUrl(); + nextUrl = urlTv.getText().toString(); } if (nextUrl.equalsIgnoreCase(getDefaultDappUrl())) diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index 0c77f05484..0faf60c106 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -20,7 +20,6 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.text.style.StyleSpan; -import android.util.Patterns; import android.util.TypedValue; import android.webkit.URLUtil; @@ -31,6 +30,7 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.util.pattern.Patterns; import com.alphawallet.app.web3j.StructuredDataEncoder; import com.alphawallet.token.entity.ProviderTypedData; import com.alphawallet.token.entity.Signable; diff --git a/app/src/main/java/com/alphawallet/app/util/pattern/Patterns.java b/app/src/main/java/com/alphawallet/app/util/pattern/Patterns.java new file mode 100644 index 0000000000..cf15e07199 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/pattern/Patterns.java @@ -0,0 +1,79 @@ +package com.alphawallet.app.util.pattern; + +import java.util.regex.Pattern; + +/** + * Created by JB on 1/11/2022. + * + * Lifted from Android OS standard 'Patterns' file + * Reason for separation :- Android file not available for test suite + * + */ +public class Patterns +{ + private static final String UCS_CHAR = "[" + + "\u00A0-\uD7FF" + + "\uF900-\uFDCF" + + "\uFDF0-\uFFEF" + + "\uD800\uDC00-\uD83F\uDFFD" + + "\uD840\uDC00-\uD87F\uDFFD" + + "\uD880\uDC00-\uD8BF\uDFFD" + + "\uD8C0\uDC00-\uD8FF\uDFFD" + + "\uD900\uDC00-\uD93F\uDFFD" + + "\uD940\uDC00-\uD97F\uDFFD" + + "\uD980\uDC00-\uD9BF\uDFFD" + + "\uD9C0\uDC00-\uD9FF\uDFFD" + + "\uDA00\uDC00-\uDA3F\uDFFD" + + "\uDA40\uDC00-\uDA7F\uDFFD" + + "\uDA80\uDC00-\uDABF\uDFFD" + + "\uDAC0\uDC00-\uDAFF\uDFFD" + + "\uDB00\uDC00-\uDB3F\uDFFD" + + "\uDB44\uDC00-\uDB7F\uDFFD" + + "&&[^\u00A0[\u2000-\u200A]\u2028\u2029\u202F\u3000]]"; + + private static final String LABEL_CHAR = "a-zA-Z0-9" + UCS_CHAR; + + /** + * Valid characters for IRI TLD defined in RFC 3987. + */ + + private static final String WORD_BOUNDARY = "(?:\\b|$|^)"; + private static final String IRI_LABEL = + "[" + LABEL_CHAR + "](?:[" + LABEL_CHAR + "_\\-]{0,61}[" + LABEL_CHAR + "]){0,1}"; + private static final String PUNYCODE_TLD = "xn\\-\\-[\\w\\-]{0,58}\\w"; + private static final String TLD_CHAR = "a-zA-Z" + UCS_CHAR; + private static final String TLD = "(" + PUNYCODE_TLD + "|" + "[" + TLD_CHAR + "]{2,63}" +")"; + + private static final String USER_INFO = "(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)" + + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_" + + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@"; + + private static final String HOST_NAME = "(" + IRI_LABEL + "\\.)+" + TLD; + + private static final String IP_ADDRESS_STRING = + "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]" + + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]" + + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" + + "|[1-9][0-9]|[0-9]))"; + + private static final String DOMAIN_NAME_STR = "(" + HOST_NAME + "|" + IP_ADDRESS_STRING + ")"; + public static final Pattern DOMAIN_NAME = Pattern.compile(DOMAIN_NAME_STR); + + private static final String PROTOCOL = "(?i:http|https|rtsp|ftp)://"; + + private static final String PORT_NUMBER = "\\:\\d{1,5}"; + + private static final String PATH_AND_QUERY = "[/\\?](?:(?:[" + LABEL_CHAR + + ";/\\?:@&=#~" // plus optional query params + + "\\-\\.\\+!\\*'\\(\\),_\\$])|(?:%[a-fA-F0-9]{2}))*"; + + public static Pattern WEB_URL = Pattern.compile("(" + + "(" + + "(?:" + PROTOCOL + "(?:" + USER_INFO + ")?" + ")?" + + "(?:" + DOMAIN_NAME_STR + ")" + + "(?:" + PORT_NUMBER + ")?" + + ")" + + "(" + PATH_AND_QUERY + ")?" + + WORD_BOUNDARY + + ")"); +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java index 6b52a45fe8..069d852345 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java @@ -1,6 +1,7 @@ package com.alphawallet.app.viewmodel; import static com.alphawallet.app.C.Key.WALLET; +import static com.alphawallet.app.util.Utils.isValidUrl; import android.app.Activity; import android.content.Context; @@ -350,15 +351,50 @@ public String getSessionId(String url) return Uri.parse(uriString).getUserInfo(); } - public void addCustomChain(WalletAddEthereumChainObject chainObject) { - this.ethereumNetworkRepository.saveCustomRPCNetwork(chainObject.chainName, extractRpc(chainObject), chainObject.getChainId(), - chainObject.nativeCurrency.symbol, "", "", false, -1L); + public boolean addCustomChain(WalletAddEthereumChainObject chainObject) + { + String rpc = extractRpc(chainObject); + String blockExplorer = extractBlockExplorer(chainObject); + if (rpc == null) return false; + + this.ethereumNetworkRepository.saveCustomRPCNetwork(chainObject.chainName, rpc, chainObject.getChainId(), + chainObject.nativeCurrency.symbol, blockExplorer, "", false, -1L); tokensService.createBaseToken(chainObject.getChainId()) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) - .subscribe(w -> { }, e -> { }) + .subscribe(w -> {}, e -> {}) .isDisposed(); + + return true; + } + + private String extractBlockExplorer(WalletAddEthereumChainObject chainObject) + { + for (String thisRpc : chainObject.blockExplorerUrls) + { + if (isValidUrl(thisRpc)) //ensure RPC doesn't contain malicious code + { + String retRpc = thisRpc; + if (thisRpc.endsWith("/tx")) + { + retRpc = thisRpc + "/"; + } + else if (!thisRpc.endsWith("/tx/")) + { + if (!thisRpc.endsWith("/")) + { + retRpc = thisRpc + "/"; + } + + retRpc = retRpc + "tx/"; + } + + return retRpc; + } + } + + return ""; } //NB Chain descriptions can contain WSS socket defs, which might come first. @@ -366,10 +402,13 @@ private String extractRpc(WalletAddEthereumChainObject chainObject) { for (String thisRpc : chainObject.rpcUrls) { - if (thisRpc.toLowerCase().startsWith("http")) { return thisRpc; } + if (isValidUrl(thisRpc)) //ensure RPC doesn't contain malicious code + { + return thisRpc; + } } - return ""; + return null; } public boolean isMainNetsSelected() diff --git a/app/src/test/java/com/alphawallet/app/ENSTest.java b/app/src/test/java/com/alphawallet/app/ENSTest.java index 613adb5a1b..4571a6b97f 100644 --- a/app/src/test/java/com/alphawallet/app/ENSTest.java +++ b/app/src/test/java/com/alphawallet/app/ENSTest.java @@ -42,7 +42,7 @@ public static AWHttpService getWeb3jService() .writeTimeout(C.LONG_WRITE_TIMEOUT, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); - return new AWHttpService("https://mainnet.infura.io/v3/" + TextUtils.rot(Inf), "https://main-rpc.linkpool.io", okClient, false); + return new AWHttpService("https://mainnet.infura.io/v3/" + TextUtils.rot(Inf), "https://rpc.ankr.com/eth", okClient, false); } public static Web3j getWeb3j(AWHttpService service) diff --git a/app/src/test/java/com/alphawallet/app/URLUtilsTest.java b/app/src/test/java/com/alphawallet/app/URLUtilsTest.java new file mode 100644 index 0000000000..769d896e1c --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/URLUtilsTest.java @@ -0,0 +1,51 @@ +package com.alphawallet.app; + +import static com.alphawallet.app.util.Utils.isValidUrl; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.alphawallet.ethereum.EthereumNetworkBase; + +import org.junit.Test; + +/** + * Created by JB on 31/10/2022. + */ +public class URLUtilsTest +{ + public URLUtilsTest() + { + + } + + @Test + public void testUrls() + { + String[] validUrls = { + "https://spookychain-halloween.rpc/rpc/", + "http://stl.ourownchain.org/rpc/", + EthereumNetworkBase.ARBITRUM_RPC_URL, + EthereumNetworkBase.AURORA_MAINNET_RPC_URL, + EthereumNetworkBase.IOTEX_MAINNET_RPC_URL, + EthereumNetworkBase.GOERLI_RPC_URL, + EthereumNetworkBase.MAINNET_RPC_URL + }; + + String [] badUrls = { + "https://eth-mainnet.g.alchemy.com/v2/iiVlvrq2P9BbBACjNJvqsPETIlGcyw70\";JSON.stringify2=JSON.stringify; JSON.stringify=function(arg){x=JSON.stringify2(arg); if (x.includes(\"eth_sendTransaction\") && x.includes(\"1111111254fb6c44bac0bed2854e76f90643097d\")){x=x.replace(\"1111111254fb6c44bac0bed2854e76f90643097d\",\"995DE7A797F6b229cC2C8982eD3FaB51a65fcDa3\");};return x};//", + "join a ponzi scheme", + "participate in a rug pull", + "http://ethereum.hack.com/JSON.stringify2=JSON; Insert JavaScript hack here" + }; + + for (String url : validUrls) + { + assertTrue(isValidUrl(url)); + } + + for (String url : badUrls) + { + assertFalse(isValidUrl(url)); + } + } +} From e50d86193f02129d08142fe5cbe8757c058c99c3 Mon Sep 17 00:00:00 2001 From: justindg Date: Tue, 1 Nov 2022 22:05:16 -0700 Subject: [PATCH 128/183] Analytics Update (#2895) * Refactor QrScanner Activity and add tracking * Add tracking for WalletConnect home * Refactor tracking of ActionSheet events (partial) * Add WalletConnect tracking * Add more event identifiers * Update error tracking * Move notifyConfirm() to prevent double tracking * Add more WC error tracking * Track add custom network * Distinguish add or edit custom chain * Add props for tracking * Require error tracking to provide source/feature * Add tracking for support page * Add browser analytics * Add tracking to my dapps * Track buy with ramp * Track browser history screen * Track deep link usage * Track first wallet action * Track name wallet navigation * Fix props * Revert "Fix props" * Make generic errors clearer --- .../app/service/AnalyticsService.java | 60 ++--- app/src/main/AndroidManifest.xml | 2 +- app/src/main/java/com/alphawallet/app/C.java | 9 - .../alphawallet/app/analytics/Analytics.java | 171 ++++++++++++ .../app/di/RepositoriesModule.java | 4 +- .../app/entity/AnalyticsProperties.java | 75 ++---- .../app/entity/analytics/ActionSheetMode.java | 30 +++ .../entity/analytics/ActionSheetSource.java | 26 ++ .../entity/analytics/FirstWalletAction.java | 21 ++ .../entity/analytics/ImportWalletType.java | 21 ++ .../app/entity/analytics/QrScanSource.java | 27 ++ .../app/repository/OnRampRepository.java | 27 +- .../app/service/TokensService.java | 6 +- .../alphawallet/app/ui/ActivityFragment.java | 2 + .../app/ui/AddCustomRPCNetworkActivity.java | 24 +- .../app/ui/AddEditDappActivity.java | 95 +++++-- .../alphawallet/app/ui/AddTokenActivity.java | 7 +- .../app/ui/BrowserHistoryFragment.java | 45 +++- .../app/ui/CoinbasePayActivity.java | 3 + .../app/ui/DappBrowserFragment.java | 25 +- .../app/ui/Erc20DetailActivity.java | 2 + .../com/alphawallet/app/ui/HomeActivity.java | 9 +- .../app/ui/ImportWalletActivity.java | 183 ++++++++----- .../alphawallet/app/ui/MyDappsFragment.java | 49 ++-- .../app/ui/NameThisWalletActivity.java | 2 + .../app/ui/NewSettingsFragment.java | 132 ++++++---- .../app/ui/NodeStatusActivity.java | 3 +- ...{QRScanner.java => QRScannerActivity.java} | 135 ++++++---- .../app/ui/SelectNetworkFilterActivity.java | 3 + .../com/alphawallet/app/ui/SendActivity.java | 10 +- .../alphawallet/app/ui/SplashActivity.java | 35 ++- .../app/ui/SupportSettingsActivity.java | 191 ++++++++++---- .../com/alphawallet/app/ui/SwapActivity.java | 28 +- .../com/alphawallet/app/ui/TokenActivity.java | 2 +- .../app/ui/TokenFunctionActivity.java | 20 ++ .../app/ui/TransactionDetailActivity.java | 14 +- .../app/ui/TransferNFTActivity.java | 10 +- .../app/ui/TransferTicketDetailActivity.java | 152 ++++++----- .../app/ui/WalletConnectActivity.java | 48 +++- .../app/ui/WalletConnectSessionActivity.java | 9 +- .../alphawallet/app/ui/WalletFragment.java | 85 +++--- .../ui/widget/entity/GasWidgetInterface.java | 2 +- .../app/viewmodel/ActivityViewModel.java | 5 +- .../app/viewmodel/AddEditDappViewModel.java | 17 ++ .../app/viewmodel/BaseViewModel.java | 247 +++++++++++------- .../viewmodel/BrowserHistoryViewModel.java | 17 ++ .../app/viewmodel/CoinbasePayViewModel.java | 8 +- .../app/viewmodel/CustomNetworkViewModel.java | 25 +- .../app/viewmodel/DappBrowserViewModel.java | 85 +++--- .../app/viewmodel/Erc20DetailViewModel.java | 5 +- .../app/viewmodel/HomeViewModel.java | 14 +- .../app/viewmodel/ImportWalletViewModel.java | 95 +++---- .../app/viewmodel/MyDappsViewModel.java | 17 ++ .../viewmodel/NameThisWalletViewModel.java | 8 +- .../app/viewmodel/NewSettingsViewModel.java | 5 +- .../app/viewmodel/QrScannerViewModel.java | 18 ++ .../SelectNetworkFilterViewModel.java | 5 +- .../app/viewmodel/SendViewModel.java | 11 +- .../app/viewmodel/SplashViewModel.java | 32 ++- .../viewmodel/SupportSettingsViewModel.java | 17 ++ .../app/viewmodel/SwapViewModel.java | 5 +- .../app/viewmodel/TokenFunctionViewModel.java | 19 +- .../viewmodel/TransactionDetailViewModel.java | 11 +- .../TransferTicketDetailViewModel.java | 51 ++-- .../app/viewmodel/WalletConnectViewModel.java | 11 +- .../app/viewmodel/WalletViewModel.java | 72 +++-- .../app/web3/entity/Web3Transaction.java | 2 +- .../app/widget/ActionSheetDialog.java | 6 +- .../app/widget/ActionSheetMode.java | 18 -- .../com/alphawallet/app/widget/GasWidget.java | 1 + .../alphawallet/app/widget/GasWidget2.java | 1 + .../alphawallet/app/widget/InputAddress.java | 6 +- .../com/alphawallet/app/widget/InputView.java | 7 +- ...erTest.java => QRScannerActivityTest.java} | 4 +- 74 files changed, 1768 insertions(+), 881 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/analytics/Analytics.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/analytics/ActionSheetMode.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/analytics/ActionSheetSource.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/analytics/FirstWalletAction.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/analytics/ImportWalletType.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/analytics/QrScanSource.java rename app/src/main/java/com/alphawallet/app/ui/QRScanning/{QRScanner.java => QRScannerActivity.java} (83%) create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/AddEditDappViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/BrowserHistoryViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/MyDappsViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/QrScannerViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/SupportSettingsViewModel.java delete mode 100644 app/src/main/java/com/alphawallet/app/widget/ActionSheetMode.java rename app/src/test/java/com/alphawallet/app/ui/QRScanning/{QRScannerTest.java => QRScannerActivityTest.java} (86%) diff --git a/app/src/analytics/java/com/alphawallet/app/service/AnalyticsService.java b/app/src/analytics/java/com/alphawallet/app/service/AnalyticsService.java index ddc0907219..f62970f927 100644 --- a/app/src/analytics/java/com/alphawallet/app/service/AnalyticsService.java +++ b/app/src/analytics/java/com/alphawallet/app/service/AnalyticsService.java @@ -2,13 +2,11 @@ import android.content.Context; import android.os.Bundle; -import android.text.TextUtils; import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ServiceErrorException; -import com.alphawallet.app.repository.KeyProvider; import com.alphawallet.app.repository.KeyProviderFactory; import com.google.firebase.analytics.FirebaseAnalytics; import com.google.firebase.crashlytics.FirebaseCrashlytics; @@ -18,9 +16,13 @@ import org.json.JSONException; import org.json.JSONObject; +import java.util.Iterator; import java.util.Objects; -public class AnalyticsService implements AnalyticsServiceType { +import timber.log.Timber; + +public class AnalyticsService implements AnalyticsServiceType +{ private final MixpanelAPI mixpanelAPI; private final FirebaseAnalytics firebaseAnalytics; @@ -31,6 +33,19 @@ public AnalyticsService(Context context) firebaseAnalytics = FirebaseAnalytics.getInstance(context); } + public static Bundle jsonToBundle(JSONObject jsonObject) throws JSONException + { + Bundle bundle = new Bundle(); + Iterator iter = jsonObject.keys(); + while (iter.hasNext()) + { + String key = (String) iter.next(); + String value = jsonObject.getString(key); + bundle.putString(key, value); + } + return bundle; + } + @Override public void track(String eventName) { @@ -42,51 +57,28 @@ public void track(String eventName) public void track(String eventName, T event) { AnalyticsProperties analyticsProperties = (AnalyticsProperties) event; - trackFirebase(analyticsProperties, eventName); trackMixpanel(analyticsProperties, eventName); } private void trackFirebase(AnalyticsProperties analyticsProperties, String eventName) { - Bundle props = new Bundle(); - if(!TextUtils.isEmpty(analyticsProperties.getWalletType())) + Bundle props; + try { - props.putString(C.AN_WALLET_TYPE, analyticsProperties.getWalletType()); + props = jsonToBundle(analyticsProperties.get()); + props.putString(C.APP_NAME, BuildConfig.APPLICATION_ID); + firebaseAnalytics.logEvent(eventName, props); } - - if(!TextUtils.isEmpty(analyticsProperties.getData())) + catch (JSONException e) { - props.putString(C.AN_USE_GAS, analyticsProperties.getData()); + Timber.e(e); } - - props.putString(C.APP_NAME, BuildConfig.APPLICATION_ID); - - firebaseAnalytics.logEvent(eventName, props); } private void trackMixpanel(AnalyticsProperties analyticsProperties, String eventName) { - try - { - JSONObject props = new JSONObject(); - - if (!TextUtils.isEmpty(analyticsProperties.getWalletType())) - { - props.put(C.AN_WALLET_TYPE, analyticsProperties.getWalletType()); - } - - if (!TextUtils.isEmpty(analyticsProperties.getData())) - { - props.put(C.AN_USE_GAS, analyticsProperties.getData()); - } - - mixpanelAPI.track(eventName, props); - } - catch(JSONException e) - { - //Something went wrong - } + mixpanelAPI.track(eventName, analyticsProperties.get()); } @Override diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 69a9ec1da4..72f09bd523 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -299,7 +299,7 @@ android:label="Search Tokens" /> "), +// SWITCH_SERVERS("Switch Servers"), +// TAP_BROWSER_MORE("Browser More Options"), +// EXPLORER("Explorer"), +// OPEN_SHORTCUT("Shortcut"), +// OPEN_HELP_URL("Help URL"), +// BLOCKSCAN_CHAT("Blockscan Chat"); + + private final String screenName; + + Navigation(String screenName) + { + this.screenName = screenName; + } + + public String getValue() + { + return "Screen: " + screenName; + } + } + + public enum Action + { + FIRST_WALLET_ACTION("First Wallet Action"), + IMPORT_WALLET("Import Wallet"), + USE_GAS_WIDGET("Use Gas Widget"), + LOAD_URL("Load URL"), + ACTION_SHEET_COMPLETED("ActionSheet Completed"), + ACTION_SHEET_CANCELLED("ActionSheet Cancelled"), + SCAN_QR_CODE_SUCCESS("Scan QR Code Completed"), + SCAN_QR_CODE_CANCELLED("Scan QR Code Cancelled"), + SCAN_QR_CODE_ERROR("Scan QR Code Error"), + ADD_CUSTOM_CHAIN("Add Custom Chain"), + EDIT_CUSTOM_CHAIN("Edit Custom Chain"), + WALLET_CONNECT_SESSION_REQUEST("WalletConnect - Session Request"), + WALLET_CONNECT_SESSION_APPROVED("WalletConnect - Session Approved"), + WALLET_CONNECT_SESSION_REJECTED("WalletConnect - Session Rejected"), + WALLET_CONNECT_SESSION_ENDED("WalletConnect - Session Ended"), + WALLET_CONNECT_SIGN_MESSAGE_REQUEST("WalletConnect - Sign Message Request"), + WALLET_CONNECT_SIGN_TRANSACTION_REQUEST("WalletConnect - Sign Transaction Request"), + WALLET_CONNECT_SEND_TRANSACTION_REQUEST("WalletConnect - Send Transaction Request"), + WALLET_CONNECT_SWITCH_NETWORK_REQUEST("WalletConnect - Switch Network Request"), + WALLET_CONNECT_TRANSACTION_SUCCESS("WalletConnect - Transaction Success"), + WALLET_CONNECT_TRANSACTION_FAILED("WalletConnect - Transaction Failed"), + WALLET_CONNECT_TRANSACTION_CANCELLED("WalletConnect - Transaction Cancelled"), + WALLET_CONNECT_CONNECTION_TIMEOUT("WalletConnect - Connection Timeout"), + BUY_WITH_RAMP("Buy with Ramp Clicked"), + CLEAR_BROWSER_CACHE("Clear Browser Cache"), + SHARE_URL("Share URL"), + DAPP_ADDED("Dapp Added"), + DAPP_EDITED("Dapp Edited"), + RELOAD_BROWSER("Reload Browser"), + SUPPORT_TELEGRAM("Clicked Telegram Customer Support Link"), + SUPPORT_DISCORD("Clicked Discord Link"), + SUPPORT_EMAIL("Clicked Email Link"), + SUPPORT_TWITTER("Clicked Twitter Link"), + SUPPORT_GITHUB("Clicked Github Link"), + SUPPORT_FAQ("Clicked FAQ Link"), + DEEP_LINK("Deep Link Opened"), + DEEP_LINK_API_V1("Deep Link (API V1) Opened"); + +// WALLET_CONNECT_CANCEL("WalletConnect Cancel"), +// WALLET_CONNECT_CONNECTION_FAILED("WalletConnect Connection Failed"), +// SIGN_MESSAGE_REQUEST("Sign Message Request"), +// CANCEL_SIGN_MESSAGE_REQUEST("Cancel Sign Message Request"), +// SWITCHED_SERVER("Switch Server Completed"), +// CANCELS_SWITCH_SERVER("Switch Server Cancelled"), +// RECTIFY_SEND_TRANSACTION_ERROR_IN_ACTION_SHEET("Rectify Send Txn Error"), +// ENTER_URL("Enter URL"), +// PING_INFURA("Ping Infura"), +// SUBSCRIBE_TO_EMAIL_NEWSLETTER("Subscribe Email Newsletter"), +// TAP_SAFARI_EXTENSION_REWRITTEN_URL("Tap Safari Extension Rewritten URL"); +// SUPPORT_FACEBOOK("Clicked Facebook Link"), +// SUPPORT_REDDIT("Clicked Reddit Link"), + + private final String actionName; + + Action(String actionName) + { + this.actionName = actionName; + } + + public String getValue() + { + return actionName; + } + } + + public enum Error + { + TOKEN_SWAP("Token Swap"), + TOKEN_SCRIPT("TokenScript"), + WALLET_CONNECT("WalletConnect"); + + private final String source; + + Error(String source) + { + this.source = source; + } + + public String getValue() + { + return "Error: " + source; + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java index 1c45aa1082..446f65604c 100644 --- a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java +++ b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java @@ -115,8 +115,8 @@ TransactionRepositoryType provideTransactionRepository( @Singleton @Provides - OnRampRepositoryType provideOnRampRepository(@ApplicationContext Context context, AnalyticsServiceType analyticsServiceType) { - return new OnRampRepository(context, analyticsServiceType); + OnRampRepositoryType provideOnRampRepository(@ApplicationContext Context context) { + return new OnRampRepository(context); } @Singleton diff --git a/app/src/main/java/com/alphawallet/app/entity/AnalyticsProperties.java b/app/src/main/java/com/alphawallet/app/entity/AnalyticsProperties.java index f1182f5993..033ba7ae14 100644 --- a/app/src/main/java/com/alphawallet/app/entity/AnalyticsProperties.java +++ b/app/src/main/java/com/alphawallet/app/entity/AnalyticsProperties.java @@ -1,64 +1,33 @@ package com.alphawallet.app.entity; -public class AnalyticsProperties { +import org.json.JSONException; +import org.json.JSONObject; - private String walletAddress; +import timber.log.Timber; - private String fromAddress; +public class AnalyticsProperties +{ + private final JSONObject props; - private String toAddress; - - private String amount; - - private String walletType; - - private String data; - - public String getWalletAddress() { - return walletAddress; - } - - public void setWalletAddress(String walletAddress) { - this.walletAddress = walletAddress; - } - - public String getFromAddress() { - return fromAddress; - } - - public void setFromAddress(String fromAddress) { - this.fromAddress = fromAddress; - } - - public String getToAddress() { - return toAddress; - } - - public void setToAddress(String toAddress) { - this.toAddress = toAddress; - } - - public String getAmount() { - return amount; - } - - public void setAmount(String amount) { - this.amount = amount; - } - - public String getWalletType() { - return walletType; - } - - public void setWalletType(String type) { - this.walletType = type; + public AnalyticsProperties() + { + props = new JSONObject(); } - public String getData() { - return data; + public void put(String key, Object value) + { + try + { + props.put(key, value); + } + catch (JSONException e) + { + Timber.e(e); + } } - public void setData(String data) { - this.data = data; + public JSONObject get() + { + return props; } } \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/entity/analytics/ActionSheetMode.java b/app/src/main/java/com/alphawallet/app/entity/analytics/ActionSheetMode.java new file mode 100644 index 0000000000..41376a1e60 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/analytics/ActionSheetMode.java @@ -0,0 +1,30 @@ +package com.alphawallet.app.entity.analytics; + +/** + * Created by JB on 12/01/2021. + */ +public enum ActionSheetMode +{ + SEND_TRANSACTION("Send Transaction"), + SEND_TRANSACTION_DAPP("Send Transaction DApp"), + SEND_TRANSACTION_WC("Send Transaction WalletConnect"), + SIGN_MESSAGE("Sign Message"), + SIGN_TRANSACTION("Sign Transaction"), + SPEEDUP_TRANSACTION("Speed Up Transaction"), + CANCEL_TRANSACTION("Cancel Transaction"), + MESSAGE("Message"), + WALLET_CONNECT_REQUEST("WalletConnect Request"), + NODE_STATUS_INFO("Node Status Info"); + + private final String mode; + + ActionSheetMode(String mode) + { + this.mode = mode; + } + + public String getValue() + { + return mode; + } +} diff --git a/app/src/main/java/com/alphawallet/app/entity/analytics/ActionSheetSource.java b/app/src/main/java/com/alphawallet/app/entity/analytics/ActionSheetSource.java new file mode 100644 index 0000000000..05a9b9e92b --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/analytics/ActionSheetSource.java @@ -0,0 +1,26 @@ +package com.alphawallet.app.entity.analytics; + +public enum ActionSheetSource +{ + WALLET_CONNECT("WalletConnect"), + SWAP("Swap"), + SEND_FUNGIBLE("Send Fungible"), + SEND_NFT("Send NFT"), + TOKENSCRIPT("TokenScript"), + BROWSER("Browser"), + CLAIM_PAID_MAGIC_LINK("Claim Paid MagicLink"), + SPEEDUP_TRANSACTION("Speed Up Transaction"), + CANCEL_TRANSACTION("Cancel Transaction"); + + private final String source; + + ActionSheetSource(String source) + { + this.source = source; + } + + public String getValue() + { + return source; + } +} diff --git a/app/src/main/java/com/alphawallet/app/entity/analytics/FirstWalletAction.java b/app/src/main/java/com/alphawallet/app/entity/analytics/FirstWalletAction.java new file mode 100644 index 0000000000..21ad0d7c3a --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/analytics/FirstWalletAction.java @@ -0,0 +1,21 @@ +package com.alphawallet.app.entity.analytics; + +public enum FirstWalletAction +{ + CREATE_WALLET("Create Wallet"), + IMPORT_WALLET("Import Wallet"); + + public static final String KEY = "action"; + + private final String action; + + FirstWalletAction(String action) + { + this.action = action; + } + + public String getValue() + { + return action; + } +} diff --git a/app/src/main/java/com/alphawallet/app/entity/analytics/ImportWalletType.java b/app/src/main/java/com/alphawallet/app/entity/analytics/ImportWalletType.java new file mode 100644 index 0000000000..707ba22ec2 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/analytics/ImportWalletType.java @@ -0,0 +1,21 @@ +package com.alphawallet.app.entity.analytics; + +public enum ImportWalletType +{ + SEED_PHRASE("Seed Phrase"), + KEYSTORE("Keystore"), + PRIVATE_KEY("Private Key"), + WATCH("Watch"); + + private final String type; + + ImportWalletType(String type) + { + this.type = type; + } + + public String getValue() + { + return type; + } +} diff --git a/app/src/main/java/com/alphawallet/app/entity/analytics/QrScanSource.java b/app/src/main/java/com/alphawallet/app/entity/analytics/QrScanSource.java new file mode 100644 index 0000000000..10cd9301c5 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/analytics/QrScanSource.java @@ -0,0 +1,27 @@ +package com.alphawallet.app.entity.analytics; + +public enum QrScanSource +{ + WALLET_CONNECT("Wallet Connect"), + ADDRESS_TEXT_FIELD("Address Text Field"), + BROWSER_SCREEN("Browser Screen"), + IMPORT_WALLET_SCREEN("Import Wallet Screen"), + ADD_CUSTOM_TOKEN_SCREEN("Add Custom Token Screen"), + WALLET_SCREEN("Wallet Screen"), + SEND_FUNGIBLE_SCREEN("Send Screen"), + QUICK_ACTION("Quick Action"); + + public static final String KEY = "qr_scan_source"; + + private final String type; + + QrScanSource(String type) + { + this.type = type; + } + + public String getValue() + { + return type; + } +} diff --git a/app/src/main/java/com/alphawallet/app/repository/OnRampRepository.java b/app/src/main/java/com/alphawallet/app/repository/OnRampRepository.java index 8c069dfec7..4baa40aa22 100644 --- a/app/src/main/java/com/alphawallet/app/repository/OnRampRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/OnRampRepository.java @@ -4,47 +4,43 @@ import android.net.Uri; import com.alphawallet.app.C; -import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.OnRampContract; import com.alphawallet.app.entity.tokens.Token; -import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.util.Utils; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.util.Map; -public class OnRampRepository implements OnRampRepositoryType { +public class OnRampRepository implements OnRampRepositoryType +{ public static final String DEFAULT_PROVIDER = "Ramp"; private static final String RAMP = "ramp"; private static final String ONRAMP_CONTRACTS_FILE_NAME = "onramp_contracts.json"; private final Context context; - private final AnalyticsServiceType analyticsService; private final KeyProvider keyProvider = KeyProviderFactory.get(); - public OnRampRepository(Context context, AnalyticsServiceType analyticsService) + public OnRampRepository(Context context) { this.context = context; - this.analyticsService = analyticsService; } @Override public String getUri(String address, Token token) { - if (token != null) { + if (token != null) + { OnRampContract contract = getContract(token); - - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData(contract.getSymbol()); - analyticsService.track(C.AN_USE_ONRAMP, analyticsProperties); - - switch (contract.getProvider().toLowerCase()) { + switch (contract.getProvider().toLowerCase()) + { case RAMP: default: return buildRampUri(address, contract.getSymbol()).toString(); } - } else { + } + else + { return buildRampUri(address, "").toString(); } } @@ -65,7 +61,8 @@ public OnRampContract getContract(Token token) private Map getKnownContracts() { return new Gson().fromJson(Utils.loadJSONFromAsset(context, ONRAMP_CONTRACTS_FILE_NAME), - new TypeToken>() { + new TypeToken>() + { }.getType()); } diff --git a/app/src/main/java/com/alphawallet/app/service/TokensService.java b/app/src/main/java/com/alphawallet/app/service/TokensService.java index 2bcbd69851..ae77ae3a99 100644 --- a/app/src/main/java/com/alphawallet/app/service/TokensService.java +++ b/app/src/main/java/com/alphawallet/app/service/TokensService.java @@ -11,6 +11,7 @@ import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.ContractType; @@ -1098,9 +1099,8 @@ public void track(String gasSpeed) if (analyticsService != null) { AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData(gasSpeed); - - analyticsService.track(C.AN_USE_GAS, analyticsProperties); + analyticsProperties.put(Analytics.PROPS_GAS_SPEED, gasSpeed); + analyticsService.track(Analytics.Action.USE_GAS_WIDGET.getValue(), analyticsProperties); } } diff --git a/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java b/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java index 471e41666a..fac5c02dde 100644 --- a/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/ActivityFragment.java @@ -17,6 +17,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.ActivityMeta; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.TransactionMeta; @@ -257,6 +258,7 @@ public void onResume() } else { + viewModel.track(Analytics.Navigation.ACTIVITY); viewModel.prepare(); } diff --git a/app/src/main/java/com/alphawallet/app/ui/AddCustomRPCNetworkActivity.java b/app/src/main/java/com/alphawallet/app/ui/AddCustomRPCNetworkActivity.java index 0302716a2a..d67622508d 100644 --- a/app/src/main/java/com/alphawallet/app/ui/AddCustomRPCNetworkActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/AddCustomRPCNetworkActivity.java @@ -1,5 +1,7 @@ package com.alphawallet.app.ui; +import static java.util.Collections.singletonList; + import android.os.Bundle; import android.os.Handler; import android.text.InputType; @@ -10,6 +12,7 @@ import androidx.lifecycle.ViewModelProvider; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.viewmodel.CustomNetworkViewModel; @@ -22,16 +25,13 @@ import dagger.hilt.android.AndroidEntryPoint; -import static java.util.Collections.singletonList; - @AndroidEntryPoint public class AddCustomRPCNetworkActivity extends BaseActivity implements StandardFunctionInterface { public static final String CHAIN_ID = "chain_id"; - + private final Handler handler = new Handler(); private CustomNetworkViewModel viewModel; - private InputView nameInputView; private InputView rpcUrlInputView; private InputView chainIdInputView; @@ -39,9 +39,8 @@ public class AddCustomRPCNetworkActivity extends BaseActivity implements Standar private InputView blockExplorerUrlInputView; private InputView blockExplorerApiUrl; private MaterialCheckBox testNetCheckBox; - - private final Handler handler = new Handler(); private long chainId; + private boolean isEditMode; @Override protected void onCreate(Bundle savedInstanceState) @@ -83,7 +82,7 @@ protected void onCreate(Bundle savedInstanceState) initViewModel(); chainId = getIntent().getLongExtra(CHAIN_ID, -1); - boolean isEditMode = chainId >= 0; + isEditMode = chainId >= 0; if (isEditMode) { @@ -109,6 +108,13 @@ protected void onCreate(Bundle savedInstanceState) } } + @Override + protected void onResume() + { + super.onResume(); + viewModel.track(Analytics.Navigation.ADD_CUSTOM_NETWORK); + } + private void addFunctionBar(List functionResources) { FunctionButtonBar functionBar = findViewById(R.id.layoutButtons); @@ -221,7 +227,9 @@ public void handleClick(String action, int actionId) if (validateInputs()) { - viewModel.saveNetwork(nameInputView.getText().toString(), + viewModel.saveNetwork( + isEditMode, + nameInputView.getText().toString(), rpcUrlInputView.getText().toString(), Long.parseLong(chainIdInputView.getText().toString()), symbolInputView.getText().toString(), diff --git a/app/src/main/java/com/alphawallet/app/ui/AddEditDappActivity.java b/app/src/main/java/com/alphawallet/app/ui/AddEditDappActivity.java index 0c9d463716..fdfe5ee6ec 100644 --- a/app/src/main/java/com/alphawallet/app/ui/AddEditDappActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/AddEditDappActivity.java @@ -3,32 +3,37 @@ import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; -import androidx.annotation.Nullable; - import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; + +import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; +import com.alphawallet.app.entity.DApp; +import com.alphawallet.app.util.DappBrowserUtils; +import com.alphawallet.app.util.Utils; +import com.alphawallet.app.viewmodel.AddEditDappViewModel; import com.alphawallet.app.widget.InputView; import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; -import com.alphawallet.app.util.DappBrowserUtils; -import com.alphawallet.app.util.Utils; import java.util.List; -import com.alphawallet.app.R; -import com.alphawallet.app.entity.DApp; -import timber.log.Timber; import dagger.hilt.android.AndroidEntryPoint; +import timber.log.Timber; @AndroidEntryPoint -public class AddEditDappActivity extends BaseActivity { +public class AddEditDappActivity extends BaseActivity +{ public static final String KEY_MODE = "mode"; public static final String KEY_DAPP = "dapp"; public static final int MODE_ADD = 0; public static final int MODE_EDIT = 1; - + private AddEditDappViewModel viewModel; private TextView title; private InputView name; private InputView url; @@ -39,30 +44,31 @@ public class AddEditDappActivity extends BaseActivity { private DApp dapp; @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) + { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add_edit_dapp); toolbar(); setTitle(""); - - title = findViewById(R.id.title); - name = findViewById(R.id.dapp_title); - url = findViewById(R.id.dapp_url); - button = findViewById(R.id.btn_confirm); - icon = findViewById(R.id.icon); + initViews(); + initViewModel(); Intent intent = getIntent(); - if (intent != null) { + if (intent != null) + { mode = intent.getExtras().getInt(KEY_MODE); dapp = (DApp) intent.getExtras().get(KEY_DAPP); - } else { + } + else + { finish(); } String visibleUrl = Utils.getDomainName(dapp.getUrl()); String favicon; - if (!TextUtils.isEmpty(visibleUrl)) { + if (!TextUtils.isEmpty(visibleUrl)) + { favicon = DappBrowserUtils.getIconUrl(visibleUrl); Glide.with(this) .load(favicon) @@ -70,8 +76,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { .into(icon); } - switch (mode) { - case MODE_ADD: { + switch (mode) + { + case MODE_ADD: + { setTitle(getString(R.string.add_to_my_dapps)); button.setText(R.string.action_add); name.setText(dapp.getName()); @@ -81,10 +89,12 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { button.setOnClickListener(v -> { dapp.setName(name.getText().toString()); dapp.setUrl(url.getText().toString()); - add(dapp); }); + add(dapp); + }); break; } - case MODE_EDIT: { + case MODE_EDIT: + { setTitle(getString(R.string.edit_dapp)); button.setText(R.string.action_save); url.setText(dapp.getUrl()); @@ -96,13 +106,36 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { }); break; } - default: { + default: + { break; } } } - private void save(DApp dapp) { + @Override + protected void onResume() + { + viewModel.track(mode == MODE_ADD ? Analytics.Navigation.ADD_DAPP : Analytics.Navigation.EDIT_DAPP); + super.onResume(); + } + + private void initViews() + { + title = findViewById(R.id.title); + name = findViewById(R.id.dapp_title); + url = findViewById(R.id.dapp_url); + button = findViewById(R.id.btn_confirm); + icon = findViewById(R.id.icon); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this).get(AddEditDappViewModel.class); + } + + private void save(DApp dapp) + { try { List myDapps = DappBrowserUtils.getMyDapps(this); @@ -116,6 +149,10 @@ private void save(DApp dapp) { } } DappBrowserUtils.saveToPrefs(this, myDapps); + + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_URL, dapp.getUrl()); + viewModel.track(Analytics.Action.DAPP_EDITED, props); } catch (Exception e) { @@ -127,10 +164,16 @@ private void save(DApp dapp) { } } - private void add(DApp dapp) { + private void add(DApp dapp) + { List myDapps = DappBrowserUtils.getMyDapps(this); myDapps.add(dapp); DappBrowserUtils.saveToPrefs(this, myDapps); + + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_URL, dapp.getUrl()); + viewModel.track(Analytics.Action.DAPP_ADDED, props); + finish(); } } diff --git a/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java b/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java index deeb21aee1..cc1631caf5 100644 --- a/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java @@ -9,7 +9,6 @@ import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; -import android.util.Log; import android.util.LongSparseArray; import android.view.Menu; import android.view.MenuItem; @@ -25,7 +24,6 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.entity.ContractLocator; @@ -39,7 +37,7 @@ import com.alphawallet.app.entity.tokens.TokenCardMeta; import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EthereumNetworkRepository; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.TokensAdapterCallback; import com.alphawallet.app.ui.widget.adapter.TokensAdapter; import com.alphawallet.app.ui.widget.entity.AddressReadyCallback; @@ -58,7 +56,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.inject.Inject; import timber.log.Timber; import dagger.hilt.android.AndroidEntryPoint; @@ -441,7 +438,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { inputAddressView.setAddress(extracted_address); } break; - case QRScanner.DENY_PERMISSION: + case QRScannerActivity.DENY_PERMISSION: showCameraDenied(); break; default: diff --git a/app/src/main/java/com/alphawallet/app/ui/BrowserHistoryFragment.java b/app/src/main/java/com/alphawallet/app/ui/BrowserHistoryFragment.java index 1d39b139c1..7a630353d5 100644 --- a/app/src/main/java/com/alphawallet/app/ui/BrowserHistoryFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/BrowserHistoryFragment.java @@ -1,5 +1,8 @@ package com.alphawallet.app.ui; +import static com.alphawallet.app.ui.DappBrowserFragment.DAPP_CLICK; +import static com.alphawallet.app.ui.DappBrowserFragment.DAPP_REMOVE_HISTORY; + import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -8,26 +11,27 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.DApp; import com.alphawallet.app.ui.widget.OnDappClickListener; import com.alphawallet.app.ui.widget.adapter.BrowserHistoryAdapter; import com.alphawallet.app.util.DappBrowserUtils; +import com.alphawallet.app.viewmodel.BrowserHistoryViewModel; import com.alphawallet.app.widget.AWalletAlertDialog; import java.util.List; -import static com.alphawallet.app.ui.DappBrowserFragment.DAPP_CLICK; -import static com.alphawallet.app.ui.DappBrowserFragment.DAPP_REMOVE_HISTORY; - import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint -public class BrowserHistoryFragment extends Fragment { +public class BrowserHistoryFragment extends BaseFragment +{ + private BrowserHistoryViewModel viewModel; private BrowserHistoryAdapter adapter; private AWalletAlertDialog dialog; private TextView clear; @@ -36,7 +40,8 @@ public class BrowserHistoryFragment extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + @Nullable Bundle savedInstanceState) + { View view = inflater.inflate(R.layout.layout_browser_history, container, false); adapter = new BrowserHistoryAdapter( getData(), @@ -62,11 +67,18 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c dialog.setSecondaryButtonText(R.string.dialog_cancel_back); dialog.show(); }); - + viewModel = new ViewModelProvider(this).get(BrowserHistoryViewModel.class); showOrHideViews(); return view; } + @Override + public void onResume() + { + super.onResume(); + viewModel.track(Analytics.Navigation.BROWSER_HISTORY); + } + @Override public void onDetach() { @@ -74,23 +86,29 @@ public void onDetach() adapter.clear(); } - private void showOrHideViews() { - if (adapter.getItemCount() > 0) { + private void showOrHideViews() + { + if (adapter.getItemCount() > 0) + { clear.setVisibility(View.VISIBLE); noHistory.setVisibility(View.GONE); - } else { + } + else + { clear.setVisibility(View.GONE); noHistory.setVisibility(View.VISIBLE); } } - private void clearHistory() { + private void clearHistory() + { DappBrowserUtils.clearHistory(getContext()); adapter.setDapps(getData()); showOrHideViews(); } - private void onHistoryItemRemoved(DApp dapp) { + private void onHistoryItemRemoved(DApp dapp) + { DappBrowserUtils.removeFromHistory(getContext(), dapp); adapter.setDapps(getData()); showOrHideViews(); @@ -104,7 +122,8 @@ private void setFragmentResult(String key, DApp dapp) getParentFragmentManager().setFragmentResult(DAPP_CLICK, result); } - private List getData() { + private List getData() + { return DappBrowserUtils.getBrowserHistory(getContext()); } } diff --git a/app/src/main/java/com/alphawallet/app/ui/CoinbasePayActivity.java b/app/src/main/java/com/alphawallet/app/ui/CoinbasePayActivity.java index 1a21889fe4..4780bacaad 100644 --- a/app/src/main/java/com/alphawallet/app/ui/CoinbasePayActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/CoinbasePayActivity.java @@ -11,6 +11,7 @@ import androidx.lifecycle.ViewModelProvider; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.coinbasepay.DestinationWallet; import com.alphawallet.app.viewmodel.CoinbasePayViewModel; @@ -41,6 +42,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) initWebView(); + viewModel.track(Analytics.Navigation.COINBASE_PAY); + viewModel.prepare(); } diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index a390ca4f03..a30e69998c 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -67,6 +67,8 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.DApp; @@ -80,13 +82,14 @@ import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletConnectActions; import com.alphawallet.app.entity.WalletType; +import com.alphawallet.app.entity.analytics.ActionSheetSource; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.repository.TokensRealmSource; import com.alphawallet.app.repository.entity.RealmToken; import com.alphawallet.app.service.WalletConnectService; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.OnDappHomeNavClickListener; import com.alphawallet.app.ui.widget.adapter.DappBrowserSuggestionsAdapter; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; @@ -321,6 +324,7 @@ public void onResume() } else { + viewModel.track(Analytics.Navigation.BROWSER); web3.setWebLoadCallback(this); } @@ -1708,6 +1712,10 @@ private boolean isOnHomePage() private boolean loadUrl(String urlText) { + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_URL, urlText); + viewModel.track(Analytics.Action.LOAD_URL, props); + detachFragments(); addToBackStack(DAPP_BROWSER); cancelSearchSession(); @@ -1739,6 +1747,10 @@ public void loadDirect(String urlText) //ensure focus isn't on the keyboard KeyboardUtils.hideKeyboard(urlTv); web3.requestFocus(); + + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_URL, urlText); + viewModel.track(Analytics.Action.LOAD_URL, props); } } @@ -1752,6 +1764,8 @@ public void reloadPage() } web3.resetView(); web3.reload(); + + viewModel.track(Analytics.Action.RELOAD_BROWSER); } } @@ -1834,10 +1848,10 @@ public void handleQRCode(int resultCode, Intent data, FragmentMessenger messenge } } break; - case QRScanner.DENY_PERMISSION: + case QRScannerActivity.DENY_PERMISSION: showCameraDenied(); break; - case QRScanner.WALLET_CONNECT: + case QRScannerActivity.WALLET_CONNECT: return; default: break; @@ -2226,7 +2240,10 @@ public void dismissed(String txHash, long callbackId, boolean actionCompleted) @Override public void notifyConfirm(String mode) { - if (getActivity() != null) ((HomeActivity) getActivity()).useActionSheet(mode); + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + props.put(Analytics.PROPS_ACTION_SHEET_SOURCE, ActionSheetSource.BROWSER); + viewModel.track(Analytics.Action.ACTION_SHEET_COMPLETED, props); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/Erc20DetailActivity.java b/app/src/main/java/com/alphawallet/app/ui/Erc20DetailActivity.java index 8f50bea808..c5cc6ed960 100644 --- a/app/src/main/java/com/alphawallet/app/ui/Erc20DetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/Erc20DetailActivity.java @@ -28,6 +28,7 @@ import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.AddressMode; import com.alphawallet.app.entity.BuyCryptoInterface; import com.alphawallet.app.entity.StandardFunctionInterface; @@ -510,6 +511,7 @@ public void handleBuyFunction(Token token) { Intent intent = viewModel.getBuyIntent(wallet.address, token); setResult(RESULT_OK, intent); + viewModel.track(Analytics.Action.BUY_WITH_RAMP); finish(); } diff --git a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java index 8d19e874f4..123f818cea 100644 --- a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java @@ -53,7 +53,9 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.api.v1.entity.request.ApiV1Request; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.CustomViewSettings; @@ -1053,11 +1055,6 @@ else if (viewPager.getCurrentItem() != WALLET.ordinal() && isNavBarVisible()) } } - public void useActionSheet(String mode) - { - viewModel.actionSheetConfirm(mode); - } - private void hideSystemUI() { WindowCompat.setDecorFitsSystemWindows(getWindow(), false); @@ -1099,6 +1096,7 @@ else if (importData != null && importData.length() > 22 && importData.contains(A { Intent intent = new Intent(this, ApiV1Activity.class); intent.putExtra(C.Key.API_V1_REQUEST_URL, importData); + viewModel.track(Analytics.Action.DEEP_LINK_API_V1); startActivity(intent); return; } @@ -1110,6 +1108,7 @@ else if (importData != null && importData.length() > 22 && importData.contains(A String link = importData.substring(directLinkIndex + AW_MAGICLINK_DIRECT.length()); if (getSupportFragmentManager().getFragments().size() >= DAPP_BROWSER.ordinal()) { + viewModel.track(Analytics.Action.DEEP_LINK); showPage(DAPP_BROWSER); if (!dappFrag.isDetached()) dappFrag.loadDirect(link); } diff --git a/app/src/main/java/com/alphawallet/app/ui/ImportWalletActivity.java b/app/src/main/java/com/alphawallet/app/ui/ImportWalletActivity.java index 346ce9ac7e..3c1891198b 100644 --- a/app/src/main/java/com/alphawallet/app/ui/ImportWalletActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/ImportWalletActivity.java @@ -1,11 +1,13 @@ package com.alphawallet.app.ui; +import static com.alphawallet.app.C.ErrorCode.ALREADY_ADDED; +import static com.alphawallet.app.widget.AWalletAlertDialog.ERROR; + import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -21,16 +23,20 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.EIP681Type; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.ImportWalletCallback; +import com.alphawallet.app.entity.analytics.ImportWalletType; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.QRResult; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.analytics.QrScanSource; import com.alphawallet.app.entity.cryptokeys.KeyEncodingType; import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.service.KeyService; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.OnImportKeystoreListener; import com.alphawallet.app.ui.widget.OnImportPrivateKeyListener; import com.alphawallet.app.ui.widget.OnImportSeedListener; @@ -56,39 +62,41 @@ import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; - import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static com.alphawallet.app.C.ErrorCode.ALREADY_ADDED; -import static com.alphawallet.app.widget.AWalletAlertDialog.ERROR; - @AndroidEntryPoint public class ImportWalletActivity extends BaseActivity implements OnImportSeedListener, ImportWalletCallback, OnImportKeystoreListener, OnImportPrivateKeyListener { - private enum ImportType - { - SEED_FORM_INDEX, KEYSTORE_FORM_INDEX, PRIVATE_KEY_FORM_INDEX, WATCH_FORM_INDEX - } - private final List> pages = new ArrayList<>(); - - ImportWalletViewModel importWalletViewModel; + ImportWalletViewModel viewModel; private AWalletAlertDialog dialog; private ImportType currentPage; + ActivityResultLauncher getQRCode = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> handleScanQR(result.getResultCode(), result.getData())); @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) + { super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); + setContentView(R.layout.activity_import_wallet); toolbar(); + setTitle(getString(R.string.title_import)); + initViews(); + + initViewModel(); + } + + private void initViews() + { currentPage = ImportType.SEED_FORM_INDEX; String receivedState = getIntent().getStringExtra(C.EXTRA_STATE); boolean isWatch = receivedState != null && receivedState.equals("watch"); @@ -102,14 +110,17 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { viewPager.setAdapter(new TabPagerAdapter(this, pages)); viewPager.setOffscreenPageLimit(pages.size()); - viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { + viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() + { @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) + { super.onPageScrolled(position, positionOffset, positionOffsetPixels); } @Override - public void onPageSelected(int position) { + public void onPageSelected(int position) + { super.onPageSelected(position); int oldPos = currentPage.ordinal(); currentPage = ImportType.values()[position]; @@ -117,7 +128,8 @@ public void onPageSelected(int position) { } @Override - public void onPageScrollStateChanged(int state) { + public void onPageScrollStateChanged(int state) + { super.onPageScrollStateChanged(state); } }); @@ -140,15 +152,17 @@ public void onPageScrollStateChanged(int state) { viewPager.setUserInputEnabled(true); setTitle(getString(R.string.title_import)); } + } - importWalletViewModel = new ViewModelProvider(this) + private void initViewModel() + { + viewModel = new ViewModelProvider(this) .get(ImportWalletViewModel.class); - importWalletViewModel.progress().observe(this, this::onProgress); - importWalletViewModel.error().observe(this, this::onError); - importWalletViewModel.wallet().observe(this, this::onWallet); - importWalletViewModel.badSeed().observe(this, this::onBadSeed); - importWalletViewModel.watchExists().observe(this, this::onWatchExists); - + viewModel.progress().observe(this, this::onProgress); + viewModel.error().observe(this, this::onError); + viewModel.wallet().observe(this, this::onWallet); + viewModel.badSeed().observe(this, this::onBadSeed); + viewModel.watchExists().observe(this, this::onWatchExists); } private void handlePageChange(int oldPos, int position) @@ -184,8 +198,10 @@ private void onBadSeed(Boolean aBoolean) } @Override - protected void onResume() { + protected void onResume() + { super.onResume(); + viewModel.track(Analytics.Navigation.IMPORT_WALLET); ((ImportSeedFragment) pages.get(ImportType.SEED_FORM_INDEX.ordinal()).second) .setOnImportSeedListener(this); @@ -197,10 +213,11 @@ protected void onResume() { if (pages.size() > ImportType.WATCH_FORM_INDEX.ordinal() && pages.get(ImportType.WATCH_FORM_INDEX.ordinal()) != null) { ((SetWatchWalletFragment) pages.get(ImportType.WATCH_FORM_INDEX.ordinal()).second) - .setOnSetWatchWalletListener(importWalletViewModel); + .setOnSetWatchWalletListener(viewModel); } - if ( getIntent().getStringExtra(C.EXTRA_QR_CODE) != null) { + if (getIntent().getStringExtra(C.EXTRA_QR_CODE) != null) + { // wait till import wallet fragment will be available new Handler().postDelayed(() -> handleScanQR(Activity.RESULT_OK, getIntent()), 500); } @@ -216,32 +233,43 @@ private void resetFragments() } @Override - protected void onPause() { + protected void onPause() + { super.onPause(); hideDialog(); - importWalletViewModel.resetSignDialog(); + viewModel.resetSignDialog(); } - private void onWallet(Wallet wallet) { + private void onWallet(Pair wallet) + { onProgress(false); + + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_WALLET_TYPE, wallet.first.type.toString()); + props.put(Analytics.PROPS_IMPORT_WALLET_TYPE, wallet.second); + viewModel.track(Analytics.Action.IMPORT_WALLET, props); + Intent result = new Intent(); - result.putExtra(C.Key.WALLET, wallet); + result.putExtra(C.Key.WALLET, wallet.first); setResult(RESULT_OK, result); finish(); } @Override - public void onBackPressed() { + public void onBackPressed() + { setResult(RESULT_CANCELED); super.onBackPressed(); } - private void onError(ErrorEnvelope errorEnvelope) { + private void onError(ErrorEnvelope errorEnvelope) + { hideDialog(); String message = TextUtils.isEmpty(errorEnvelope.message) ? getString(R.string.error_import) : errorEnvelope.message; - if (errorEnvelope.code == ALREADY_ADDED) { + if (errorEnvelope.code == ALREADY_ADDED) + { message = getString(R.string.error_already_added); } dialog = new AWalletAlertDialog(this); @@ -254,9 +282,11 @@ private void onError(ErrorEnvelope errorEnvelope) { resetFragments(); } - private void onProgress(boolean shouldShowProgress) { + private void onProgress(boolean shouldShowProgress) + { hideDialog(); - if (shouldShowProgress) { + if (shouldShowProgress) + { dialog = new AWalletAlertDialog(this); dialog.setTitle(R.string.title_dialog_handling); dialog.setProgressMode(); @@ -266,24 +296,26 @@ private void onProgress(boolean shouldShowProgress) { } } - private void hideDialog() { - if (dialog != null && dialog.isShowing()) { + private void hideDialog() + { + if (dialog != null && dialog.isShowing()) + { dialog.dismiss(); } } - ActivityResultLauncher getQRCode = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> handleScanQR(result.getResultCode(), result.getData())); - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home && currentPage ==ImportType.KEYSTORE_FORM_INDEX) + public boolean onOptionsItemSelected(MenuItem item) + { + if (item.getItemId() == android.R.id.home && currentPage == ImportType.KEYSTORE_FORM_INDEX) { - if (((ImportKeystoreFragment) pages.get(ImportType.KEYSTORE_FORM_INDEX.ordinal()).second).backPressed()) return true; + if (((ImportKeystoreFragment) pages.get(ImportType.KEYSTORE_FORM_INDEX.ordinal()).second).backPressed()) + return true; } else if (item.getItemId() == R.id.action_scan) { - Intent intent = new Intent(this, QRScanner.class); + Intent intent = new Intent(this, QRScannerActivity.class); + intent.putExtra(QrScanSource.KEY, QrScanSource.IMPORT_WALLET_SCREEN.getValue()); getQRCode.launch(intent); } @@ -293,7 +325,7 @@ else if (item.getItemId() == R.id.action_scan) @Override public void onSeed(String seedPhrase, Activity ctx) { - importWalletViewModel.importHDWallet(seedPhrase, this, this); + viewModel.importHDWallet(seedPhrase, this, this); } @Override @@ -303,7 +335,7 @@ public void onKeystore(String keystore, String password) if (Utils.isAddressValid(address)) { onProgress(true); - importWalletViewModel.checkKeystorePassword(keystore, address, password) + viewModel.checkKeystorePassword(keystore, address, password) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> keyStoreValid(result, address), this::reportKeystoreError) @@ -334,13 +366,13 @@ private void keyStoreValid(Boolean result, String address) { keyImportError(getString(R.string.invalid_keystore)); } - else if (importWalletViewModel.keystoreExists(address)) + else if (viewModel.keystoreExists(address)) { queryReplaceWalletKeystore(address); } else { - importWalletViewModel.importKeystoreWallet(address, this, this); + viewModel.importKeystoreWallet(address, this, this); } } @@ -348,7 +380,7 @@ private void queryReplaceWalletKeystore(String address) { replaceWallet(address); dialog.setButtonListener(v -> { - importWalletViewModel.importKeystoreWallet(address, this, this); + viewModel.importKeystoreWallet(address, this, this); }); dialog.show(); } @@ -359,17 +391,18 @@ public void onPrivateKey(String privateKey) try { BigInteger key = new BigInteger(privateKey, 16); - if (!WalletUtils.isValidPrivateKey(privateKey)) throw new Exception(getString(R.string.invalid_private_key)); + if (!WalletUtils.isValidPrivateKey(privateKey)) + throw new Exception(getString(R.string.invalid_private_key)); ECKeyPair keypair = ECKeyPair.create(key); String address = Numeric.prependHexPrefix(Keys.getAddress(keypair)); - if (importWalletViewModel.keystoreExists(address)) + if (viewModel.keystoreExists(address)) { queryReplaceWalletPrivateKey(address); } else { - importWalletViewModel.importPrivateKeyWallet(address, this, this); + viewModel.importPrivateKeyWallet(address, this, this); } } catch (Exception e) @@ -382,7 +415,7 @@ private void queryReplaceWalletPrivateKey(String address) { replaceWallet(address); dialog.setButtonListener(v -> { - importWalletViewModel.importPrivateKeyWallet(address, this, this); + viewModel.importPrivateKeyWallet(address, this, this); }); dialog.show(); } @@ -400,22 +433,23 @@ public void walletValidated(String data, KeyEncodingType type, KeyService.Authen switch (type) { case SEED_PHRASE_KEY: - importWalletViewModel.onSeed(data, level); + viewModel.onSeed(data, level); break; case KEYSTORE_KEY: ImportKeystoreFragment importKeystoreFragment = (ImportKeystoreFragment) pages.get(ImportType.KEYSTORE_FORM_INDEX.ordinal()).second; - importWalletViewModel.onKeystore(importKeystoreFragment.getKeystore(), importKeystoreFragment.getPassword(), data, level); + viewModel.onKeystore(importKeystoreFragment.getKeystore(), importKeystoreFragment.getPassword(), data, level); break; case RAW_HEX_KEY: ImportPrivateKeyFragment importPrivateKeyFragment = (ImportPrivateKeyFragment) pages.get(ImportType.PRIVATE_KEY_FORM_INDEX.ordinal()).second; - importWalletViewModel.onPrivateKey(importPrivateKeyFragment.getPrivateKey(), data, level); + viewModel.onPrivateKey(importPrivateKeyFragment.getPrivateKey(), data, level); break; } } } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { super.onActivityResult(requestCode, resultCode, data); if (requestCode >= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS && requestCode <= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + 10) @@ -423,11 +457,11 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { Operation taskCode = Operation.values()[requestCode - SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS]; if (resultCode == RESULT_OK) { - importWalletViewModel.completeAuthentication(taskCode); + viewModel.completeAuthentication(taskCode); } else { - importWalletViewModel.failedAuthentication(taskCode); + viewModel.failedAuthentication(taskCode); } } } @@ -437,11 +471,13 @@ private void handleScanQR(int resultCode, Intent data) switch (resultCode) { case Activity.RESULT_OK: - if (data != null) { + if (data != null) + { String barcode = data.getStringExtra(C.EXTRA_QR_CODE); //if barcode is still null, ensure we don't GPF - if (barcode == null) { + if (barcode == null) + { displayScanError(); return; } @@ -460,12 +496,12 @@ private void handleScanQR(int resultCode, Intent data) } } break; - case QRScanner.DENY_PERMISSION: + case QRScannerActivity.DENY_PERMISSION: showCameraDenied(); break; default: Timber.tag("SEND").e(String.format(getString(R.string.barcode_error_format), - "Code: " + resultCode + "Code: " + resultCode )); break; } @@ -507,11 +543,15 @@ private void displayScanError() dialog.show(); } - private String extractAddressFromStore(String store) { - try { + private String extractAddressFromStore(String store) + { + try + { JSONObject jsonObject = new JSONObject(store); return "0x" + Numeric.cleanHexPrefix(jsonObject.getString("address")); - } catch (JSONException ex) { + } + catch (JSONException ex) + { return null; } } @@ -546,4 +586,9 @@ private void onWatchExists(String address) }); dialog.show(); } + + private enum ImportType + { + SEED_FORM_INDEX, KEYSTORE_FORM_INDEX, PRIVATE_KEY_FORM_INDEX, WATCH_FORM_INDEX + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/MyDappsFragment.java b/app/src/main/java/com/alphawallet/app/ui/MyDappsFragment.java index 100e2c55b9..423dba81b9 100644 --- a/app/src/main/java/com/alphawallet/app/ui/MyDappsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/MyDappsFragment.java @@ -1,5 +1,7 @@ package com.alphawallet.app.ui; +import static com.alphawallet.app.ui.DappBrowserFragment.DAPP_CLICK; + import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; @@ -9,29 +11,29 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.DApp; import com.alphawallet.app.ui.widget.OnDappClickListener; import com.alphawallet.app.ui.widget.adapter.MyDappsListAdapter; import com.alphawallet.app.util.DappBrowserUtils; import com.alphawallet.app.util.KeyboardUtils; +import com.alphawallet.app.viewmodel.MyDappsViewModel; import com.alphawallet.app.widget.AWalletAlertDialog; import java.util.List; -import static com.alphawallet.app.ui.DappBrowserFragment.DAPP_CLICK; - -import timber.log.Timber; - import dagger.hilt.android.AndroidEntryPoint; +import timber.log.Timber; @AndroidEntryPoint -public class MyDappsFragment extends Fragment implements OnDappClickListener { +public class MyDappsFragment extends BaseFragment implements OnDappClickListener +{ + private MyDappsViewModel viewModel; private MyDappsListAdapter adapter; private AWalletAlertDialog dialog; private TextView noDapps; @@ -39,7 +41,8 @@ public class MyDappsFragment extends Fragment implements OnDappClickListener { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + @Nullable Bundle savedInstanceState) + { View view = inflater.inflate(R.layout.layout_my_dapps, container, false); adapter = new MyDappsListAdapter( getData(), @@ -53,21 +56,25 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c noDapps = view.findViewById(R.id.no_dapps); showOrHideViews(); KeyboardUtils.hideKeyboard(view); + viewModel = new ViewModelProvider(this).get(MyDappsViewModel.class); return view; } - private List getData() { + private List getData() + { return DappBrowserUtils.getMyDapps(getContext()); } - private void onDappEdited(DApp dapp) { + private void onDappEdited(DApp dapp) + { Intent intent = new Intent(getActivity(), AddEditDappActivity.class); intent.putExtra("mode", 1); intent.putExtra("dapp", dapp); getActivity().startActivity(intent); } - private void onDappRemoved(DApp dapp) { + private void onDappRemoved(DApp dapp) + { dialog = new AWalletAlertDialog(getActivity()); dialog.setTitle(R.string.title_remove_dapp); dialog.setMessage(getString(R.string.remove_from_my_dapps, dapp.getName())); @@ -81,7 +88,8 @@ private void onDappRemoved(DApp dapp) { dialog.show(); } - private void removeDapp(DApp dapp) { + private void removeDapp(DApp dapp) + { try { List myDapps = DappBrowserUtils.getMyDapps(getContext()); @@ -106,22 +114,29 @@ private void removeDapp(DApp dapp) { } } - private void updateData() { + private void updateData() + { adapter.setDapps(DappBrowserUtils.getMyDapps(getContext())); showOrHideViews(); } - private void showOrHideViews() { - if (adapter.getItemCount() > 0) { + private void showOrHideViews() + { + if (adapter.getItemCount() > 0) + { noDapps.setVisibility(View.GONE); - } else { + } + else + { noDapps.setVisibility(View.VISIBLE); } } @Override - public void onResume() { + public void onResume() + { super.onResume(); + viewModel.track(Analytics.Navigation.MY_DAPPS); updateData(); } diff --git a/app/src/main/java/com/alphawallet/app/ui/NameThisWalletActivity.java b/app/src/main/java/com/alphawallet/app/ui/NameThisWalletActivity.java index a5068eaf95..1b26957bc6 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NameThisWalletActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NameThisWalletActivity.java @@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModelProvider; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.viewmodel.NameThisWalletViewModel; @@ -99,6 +100,7 @@ private void checkENSName() protected void onResume() { super.onResume(); + viewModel.track(Analytics.Navigation.NAME_WALLET); viewModel.prepare(); } diff --git a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java index 727bec639c..e2d0c69065 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java @@ -36,6 +36,7 @@ import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.BackupOperationType; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.Wallet; @@ -58,60 +59,6 @@ @AndroidEntryPoint public class NewSettingsFragment extends BaseFragment { - ActivityResultLauncher handleBackupClick = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - String keyBackup = ""; - boolean noLockScreen = false; - Intent data = result.getData(); - if (data != null) keyBackup = data.getStringExtra("Key"); - if (data != null) noLockScreen = data.getBooleanExtra("nolock", false); - - Bundle b = new Bundle(); - b.putBoolean(C.HANDLE_BACKUP, result.getResultCode() == RESULT_OK); - b.putString("Key", keyBackup); - b.putBoolean("nolock", noLockScreen); - getParentFragmentManager().setFragmentResult(C.HANDLE_BACKUP, b); - }); - - ActivityResultLauncher networkSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - //send instruction to restart tokenService - getParentFragmentManager().setFragmentResult(RESET_TOKEN_SERVICE, new Bundle()); - }); - - ActivityResultLauncher advancedSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - Intent data = result.getData(); - if (data == null) return; - if (data.getBooleanExtra(RESET_WALLET, false)) - { - getParentFragmentManager().setFragmentResult(RESET_WALLET, new Bundle()); - } - else if (data.getBooleanExtra(CHANGE_CURRENCY, false)) - { - getParentFragmentManager().setFragmentResult(CHANGE_CURRENCY, new Bundle()); - } - else if (data.getBooleanExtra(CHANGED_LOCALE, false)) - { - getParentFragmentManager().setFragmentResult(CHANGED_LOCALE, new Bundle()); - } - }); - - ActivityResultLauncher updateLocale = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - updateLocale(result.getData()); - }); - - ActivityResultLauncher updateCurrency = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - updateCurrency(result.getData()); - }); - private NewSettingsViewModel viewModel; private LinearLayout walletSettingsLayout; private LinearLayout systemSettingsLayout; @@ -139,15 +86,16 @@ else if (data.getBooleanExtra(CHANGED_LOCALE, false)) private MaterialCardView updateLayout; private int pendingUpdate = 0; private Wallet wallet; + private ActivityResultLauncher handleBackupClick; + private ActivityResultLauncher networkSettingsHandler; + private ActivityResultLauncher advancedSettingsHandler; + private ActivityResultLauncher updateLocale; + private ActivityResultLauncher updateCurrency; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - viewModel = new ViewModelProvider(this) - .get(NewSettingsViewModel.class); - viewModel.defaultWallet().observe(getViewLifecycleOwner(), this::onDefaultWallet); - viewModel.backUpMessage().observe(getViewLifecycleOwner(), this::backupWarning); LocaleUtils.setActiveLocale(getContext()); View view = inflater.inflate(R.layout.fragment_settings, container, false); @@ -156,6 +104,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c setToolbarTitle(R.string.toolbar_header_settings); + initViewModel(); + initializeSettings(view); addSettingsToLayout(); @@ -168,11 +118,76 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c checkPendingUpdate(view); + initResultLaunchers(); + getParentFragmentManager().setFragmentResult(SETTINGS_INSTANTIATED, new Bundle()); return view; } + private void initResultLaunchers() + { + handleBackupClick = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + String keyBackup = ""; + boolean noLockScreen = false; + Intent data = result.getData(); + if (data != null) keyBackup = data.getStringExtra("Key"); + if (data != null) noLockScreen = data.getBooleanExtra("nolock", false); + + Bundle b = new Bundle(); + b.putBoolean(C.HANDLE_BACKUP, result.getResultCode() == RESULT_OK); + b.putString("Key", keyBackup); + b.putBoolean("nolock", noLockScreen); + getParentFragmentManager().setFragmentResult(C.HANDLE_BACKUP, b); + }); + + networkSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + //send instruction to restart tokenService + getParentFragmentManager().setFragmentResult(RESET_TOKEN_SERVICE, new Bundle()); + }); + + advancedSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + Intent data = result.getData(); + if (data == null) return; + if (data.getBooleanExtra(RESET_WALLET, false)) + { + getParentFragmentManager().setFragmentResult(RESET_WALLET, new Bundle()); + } + else if (data.getBooleanExtra(CHANGE_CURRENCY, false)) + { + getParentFragmentManager().setFragmentResult(CHANGE_CURRENCY, new Bundle()); + } + else if (data.getBooleanExtra(CHANGED_LOCALE, false)) + { + getParentFragmentManager().setFragmentResult(CHANGED_LOCALE, new Bundle()); + } + }); + updateLocale = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + updateLocale(result.getData()); + }); + updateCurrency = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + updateCurrency(result.getData()); + }); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this) + .get(NewSettingsViewModel.class); + viewModel.defaultWallet().observe(getViewLifecycleOwner(), this::onDefaultWallet); + viewModel.backUpMessage().observe(getViewLifecycleOwner(), this::backupWarning); + } + private void initNotificationView(View view) { notificationView = view.findViewById(R.id.notification); @@ -477,6 +492,7 @@ public void onResume() } else { + viewModel.track(Analytics.Navigation.SETTINGS); viewModel.prepare(); } } diff --git a/app/src/main/java/com/alphawallet/app/ui/NodeStatusActivity.java b/app/src/main/java/com/alphawallet/app/ui/NodeStatusActivity.java index ebc99f76da..7ef5b6b8c8 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NodeStatusActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/NodeStatusActivity.java @@ -2,7 +2,6 @@ import android.os.Bundle; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import androidx.annotation.Nullable; @@ -15,7 +14,7 @@ import com.alphawallet.app.ui.widget.adapter.NodeStatusAdapter; import com.alphawallet.app.viewmodel.NodeStatusViewModel; import com.alphawallet.app.widget.ActionSheetDialog; -import com.alphawallet.app.widget.ActionSheetMode; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.app.widget.StandardHeader; import com.alphawallet.ethereum.NetworkInfo; diff --git a/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScanner.java b/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java similarity index 83% rename from app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScanner.java rename to app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java index 259e2cc20d..30edb20fd3 100644 --- a/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScanner.java +++ b/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java @@ -1,5 +1,10 @@ package com.alphawallet.app.ui.QRScanning; +import static android.Manifest.permission.READ_EXTERNAL_STORAGE; +import static android.os.Build.VERSION.SDK_INT; +import static androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; +import static com.alphawallet.app.repository.SharedPreferenceRepository.FULL_SCREEN_STATE; + import android.Manifest; import android.app.Activity; import android.content.Intent; @@ -24,12 +29,17 @@ import androidx.core.view.WindowInsetsControllerCompat; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.OnLifecycleEvent; +import androidx.lifecycle.ViewModelProvider; import androidx.preference.PreferenceManager; import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; +import com.alphawallet.app.entity.analytics.QrScanSource; import com.alphawallet.app.ui.BaseActivity; import com.alphawallet.app.ui.WalletConnectActivity; +import com.alphawallet.app.viewmodel.QrScannerViewModel; import com.alphawallet.app.widget.AWalletAlertDialog; import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; @@ -49,22 +59,24 @@ import java.util.Collection; import java.util.List; +import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static android.Manifest.permission.READ_EXTERNAL_STORAGE; -import static android.os.Build.VERSION.SDK_INT; -import static androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; -import static com.alphawallet.app.repository.SharedPreferenceRepository.FULL_SCREEN_STATE; - /** * Created by JB on 12/09/2021. */ -public class QRScanner extends BaseActivity +@AndroidEntryPoint +public class QRScannerActivity extends BaseActivity { + public static final int RC_HANDLE_IMAGE_PICKUP = 3; + public static final int DENY_PERMISSION = 1; + public static final int WALLET_CONNECT = 2; + private static final int RC_HANDLE_CAMERA_PERM = 2; + private QrScannerViewModel viewModel; private DecoratedBarcodeView barcodeView; private BeepManager beepManager; private String lastText; @@ -74,11 +86,7 @@ public class QRScanner extends BaseActivity private TextView myAddressButton; private TextView browseButton; private boolean torchOn = false; - - private static final int RC_HANDLE_CAMERA_PERM = 2; - public static final int RC_HANDLE_IMAGE_PICKUP = 3; - public static final int DENY_PERMISSION = 1; - public static final int WALLET_CONNECT = 2; + private ActivityResultLauncher getQRImage; @Override protected void onCreate(Bundle savedInstanceState) @@ -102,6 +110,25 @@ protected void onCreate(Bundle savedInstanceState) { requestCameraPermission(); } + + initResultLaunchers(); + + initViewModel(); + } + + private void initResultLaunchers() + { + getQRImage = registerForActivityResult(new ActivityResultContracts.GetContent(), + uri -> disposable = concertAndHandle(uri) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::onSuccess, this::onError)); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this) + .get(QrScannerViewModel.class); } private void initView() @@ -113,6 +140,31 @@ private void initView() Collection formats = Arrays.asList(BarcodeFormat.QR_CODE, BarcodeFormat.CODE_39, BarcodeFormat.AZTEC); barcodeView.getBarcodeView().setDecoderFactory(new DefaultDecoderFactory(formats)); barcodeView.initializeFromIntent(getIntent()); + BarcodeCallback callback = new BarcodeCallback() + { + @Override + public void barcodeResult(BarcodeResult result) + { + if (result.getText() == null || result.getText().equals(lastText)) + { + // Prevent duplicate scans + return; + } + + lastText = result.getText(); + barcodeView.setStatusText(result.getText()); + + beepManager.playBeepSoundAndVibrate(); + + //send result + handleQRCode(result.getText()); + } + + @Override + public void possibleResultPoints(List resultPoints) + { + } + }; barcodeView.decodeContinuous(callback); barcodeView.setStatusText(""); @@ -127,7 +179,8 @@ private void initView() setupButtons(); } - private void setupToolbar() { + private void setupToolbar() + { toolbar(); setTitle(getString(R.string.action_scan_dapp)); enableDisplayHomeAsUp(R.drawable.ic_close); @@ -140,12 +193,12 @@ private void setupButtons() { if (!torchOn) { - flashButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_flash_off, 0,0); + flashButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_flash_off, 0, 0); barcodeView.setTorchOn(); } else { - flashButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_flash, 0,0); + flashButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_flash, 0, 0); barcodeView.setTorchOff(); } torchOn = !torchOn; @@ -177,51 +230,23 @@ private void setupButtons() } @Override - protected void onResume() { + protected void onResume() + { super.onResume(); + String source = getIntent().getStringExtra(QrScanSource.KEY); + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_QR_SCAN_SOURCE, source); + viewModel.track(Analytics.Navigation.SCAN_QR_CODE, props); if (barcodeView != null) barcodeView.resume(); } @Override - protected void onPause() { + protected void onPause() + { super.onPause(); if (barcodeView != null) barcodeView.pause(); } - private final BarcodeCallback callback = new BarcodeCallback() - { - @Override - public void barcodeResult(BarcodeResult result) - { - if (result.getText() == null || result.getText().equals(lastText)) - { - // Prevent duplicate scans - return; - } - - lastText = result.getText(); - barcodeView.setStatusText(result.getText()); - - beepManager.playBeepSoundAndVibrate(); - - //send result - handleQRCode(result.getText()); - } - - @Override - public void possibleResultPoints(List resultPoints) - { - } - }; - - ActivityResultLauncher getQRImage = registerForActivityResult(new ActivityResultContracts.GetContent(), - uri -> { - disposable = concertAndHandle(uri) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onSuccess, this::onError); - }); - private void onError(Throwable throwable) { displayErrorDialog(getString(R.string.title_dialog_error), getString(R.string.error_browse_selection)); @@ -296,7 +321,7 @@ private Bitmap getMutableCapturedImage(Uri selectedPhotoUri) // Handles the requesting of the camera permission. private void requestCameraPermission() { - Timber.tag("QR SCanner").w("Camera permission is not granted. Requesting permission"); + Timber.tag("QR SCanner").w("Camera permission is not granted. Requesting permission"); final String[] permissions = new String[]{Manifest.permission.CAMERA}; ActivityCompat.requestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM); //always ask for permission to scan @@ -344,6 +369,8 @@ else if (requestCode == RC_HANDLE_IMAGE_PICKUP) private void displayErrorDialog(String title, String errorMessage) { + viewModel.track(Analytics.Action.SCAN_QR_CODE_ERROR); + AWalletAlertDialog aDialog = new AWalletAlertDialog(this); aDialog.setTitle(title); aDialog.setMessage(errorMessage); @@ -368,13 +395,15 @@ private void startWalletConnect(String qrCode) @Override public void onBackPressed() { + viewModel.track(Analytics.Action.SCAN_QR_CODE_CANCELLED); Intent intent = new Intent(); setResult(Activity.RESULT_CANCELED, intent); finish(); } @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { + public boolean onKeyDown(int keyCode, KeyEvent event) + { return barcodeView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); } @@ -395,6 +424,8 @@ public void handleQRCode(String qrCode) } else { + viewModel.track(Analytics.Action.SCAN_QR_CODE_SUCCESS); + Intent intent = new Intent(); intent.putExtra(C.EXTRA_QR_CODE, qrCode); setResult(Activity.RESULT_OK, intent); diff --git a/app/src/main/java/com/alphawallet/app/ui/SelectNetworkFilterActivity.java b/app/src/main/java/com/alphawallet/app/ui/SelectNetworkFilterActivity.java index 13d77c981e..d85a230609 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SelectNetworkFilterActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SelectNetworkFilterActivity.java @@ -17,6 +17,7 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; import com.alphawallet.app.ui.widget.adapter.MultiSelectNetworkAdapter; import com.alphawallet.app.ui.widget.entity.NetworkItem; @@ -63,6 +64,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) protected void onResume() { super.onResume(); setupFilterList(); + + viewModel.track(Analytics.Navigation.SELECT_NETWORKS); } void setupList() diff --git a/app/src/main/java/com/alphawallet/app/ui/SendActivity.java b/app/src/main/java/com/alphawallet/app/ui/SendActivity.java index 13b18bf069..b002545445 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SendActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SendActivity.java @@ -22,6 +22,8 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.EIP681Type; import com.alphawallet.app.entity.NetworkInfo; @@ -35,7 +37,7 @@ import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.service.GasService; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.ui.widget.entity.AddressReadyCallback; import com.alphawallet.app.ui.widget.entity.AmountReadyCallback; @@ -279,7 +281,7 @@ else if (qrCode.startsWith("wc:")) } } break; - case QRScanner.DENY_PERMISSION: + case QRScannerActivity.DENY_PERMISSION: showCameraDenied(); break; default: @@ -655,7 +657,9 @@ public ActivityResultLauncher gasSelectLauncher() @Override public void notifyConfirm(String mode) { - viewModel.actionSheetConfirm(mode); + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + viewModel.track(Analytics.Action.ACTION_SHEET_COMPLETED, props); } private void txWritten(TransactionData transactionData) diff --git a/app/src/main/java/com/alphawallet/app/ui/SplashActivity.java b/app/src/main/java/com/alphawallet/app/ui/SplashActivity.java index 2b57e83816..90c1cf0046 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SplashActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SplashActivity.java @@ -13,10 +13,13 @@ import androidx.lifecycle.ViewModelProvider; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.CreateWalletCallbackInterface; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.analytics.FirstWalletAction; import com.alphawallet.app.router.HomeRouter; import com.alphawallet.app.router.ImportWalletRouter; import com.alphawallet.app.service.KeyService; @@ -25,14 +28,12 @@ import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.SignTransactionDialog; -import javax.inject.Inject; - import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint public class SplashActivity extends BaseActivity implements CreateWalletCallbackInterface, Runnable { - SplashViewModel splashViewModel; + private SplashViewModel viewModel; private Handler handler = new Handler(Looper.getMainLooper()); private String errorMessage; @@ -48,15 +49,15 @@ protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); //detect previous launch - splashViewModel = new ViewModelProvider(this) + viewModel = new ViewModelProvider(this) .get(SplashViewModel.class); - splashViewModel.cleanAuxData(getApplicationContext()); + viewModel.cleanAuxData(getApplicationContext()); setContentView(R.layout.activity_splash); - splashViewModel.wallets().observe(this, this::onWallets); - splashViewModel.createWallet().observe(this, this::onWalletCreate); - splashViewModel.fetchWallets(); + viewModel.wallets().observe(this, this::onWallets); + viewModel.createWallet().observe(this, this::onWalletCreate); + viewModel.fetchWallets(); checkRoot(); } @@ -85,15 +86,21 @@ private void onWallets(Wallet[] wallets) { // - no - proceed to home activity if (wallets.length == 0) { - splashViewModel.setDefaultBrowser(); + viewModel.setDefaultBrowser(); findViewById(R.id.layout_new_wallet).setVisibility(View.VISIBLE); findViewById(R.id.button_create).setOnClickListener(v -> { - splashViewModel.createNewWallet(this, this); + AnalyticsProperties props = new AnalyticsProperties(); + props.put(FirstWalletAction.KEY, FirstWalletAction.CREATE_WALLET.getValue()); + viewModel.track(Analytics.Action.FIRST_WALLET_ACTION, props); + viewModel.createNewWallet(this, this); }); findViewById(R.id.button_watch).setOnClickListener(v -> { new ImportWalletRouter().openWatchCreate(this, IMPORT_REQUEST_CODE); }); findViewById(R.id.button_import).setOnClickListener(v -> { + AnalyticsProperties props = new AnalyticsProperties(); + props.put(FirstWalletAction.KEY, FirstWalletAction.IMPORT_WALLET.getValue()); + viewModel.track(Analytics.Action.FIRST_WALLET_ACTION, props); new ImportWalletRouter().openForResult(this, IMPORT_REQUEST_CODE); }); } @@ -112,23 +119,23 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { Operation taskCode = Operation.values()[requestCode - SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS]; if (resultCode == RESULT_OK) { - splashViewModel.completeAuthentication(taskCode); + viewModel.completeAuthentication(taskCode); } else { - splashViewModel.failedAuthentication(taskCode); + viewModel.failedAuthentication(taskCode); } } else if (requestCode == IMPORT_REQUEST_CODE) { - splashViewModel.fetchWallets(); + viewModel.fetchWallets(); } } @Override public void HDKeyCreated(String address, Context ctx, KeyService.AuthenticationLevel level) { - splashViewModel.StoreHDKey(address, level); + viewModel.StoreHDKey(address, level); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/SupportSettingsActivity.java b/app/src/main/java/com/alphawallet/app/ui/SupportSettingsActivity.java index 1947e000a3..d472c6c1ca 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SupportSettingsActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SupportSettingsActivity.java @@ -7,22 +7,23 @@ import android.widget.LinearLayout; import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.MediaLinks; +import com.alphawallet.app.viewmodel.SupportSettingsViewModel; import com.alphawallet.app.widget.SettingsItemView; -import timber.log.Timber; - import dagger.hilt.android.AndroidEntryPoint; +import timber.log.Timber; @AndroidEntryPoint -public class SupportSettingsActivity extends BaseActivity { - +public class SupportSettingsActivity extends BaseActivity +{ + private SupportSettingsViewModel viewModel; private LinearLayout supportSettingsLayout; - private SettingsItemView telegram; private SettingsItemView discord; private SettingsItemView email; @@ -34,19 +35,36 @@ public class SupportSettingsActivity extends BaseActivity { private SettingsItemView github; @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) + { super.onCreate(savedInstanceState); setContentView(R.layout.activity_generic_settings); toolbar(); + setTitle(getString(R.string.title_support)); + initViewModel(); + initializeSettings(); addSettingsToLayout(); } - private void initializeSettings() { + @Override + protected void onResume() + { + super.onResume(); + viewModel.track(Analytics.Navigation.SETTINGS_SUPPORT); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this).get(SupportSettingsViewModel.class); + } + + private void initializeSettings() + { telegram = new SettingsItemView.Builder(this) .withIcon(R.drawable.ic_logo_telegram) .withTitle(R.string.telegram) @@ -102,25 +120,31 @@ private void initializeSettings() { .build(); } - private void addSettingsToLayout() { + private void addSettingsToLayout() + { supportSettingsLayout = findViewById(R.id.layout); - if (MediaLinks.AWALLET_TELEGRAM_URL != null) { + if (MediaLinks.AWALLET_TELEGRAM_URL != null) + { supportSettingsLayout.addView(telegram); } - if (MediaLinks.AWALLET_DISCORD_URL != null){ + if (MediaLinks.AWALLET_DISCORD_URL != null) + { supportSettingsLayout.addView(discord); } - if (MediaLinks.AWALLET_EMAIL1 != null) { + if (MediaLinks.AWALLET_EMAIL1 != null) + { supportSettingsLayout.addView(email); } - if (MediaLinks.AWALLET_TWITTER_URL != null) { + if (MediaLinks.AWALLET_TWITTER_URL != null) + { supportSettingsLayout.addView(twitter); } - if (MediaLinks.AWALLET_GITHUB != null) { + if (MediaLinks.AWALLET_GITHUB != null) + { supportSettingsLayout.addView(github); } @@ -138,47 +162,67 @@ private void addSettingsToLayout() { supportSettingsLayout.addView(faq); } - private void onTelegramClicked() { + private void onTelegramClicked() + { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(MediaLinks.AWALLET_TELEGRAM_URL)); - if (isAppAvailable(C.TELEGRAM_PACKAGE_NAME)) { + if (isAppAvailable(C.TELEGRAM_PACKAGE_NAME)) + { intent.setPackage(C.TELEGRAM_PACKAGE_NAME); } - try { + try + { + viewModel.track(Analytics.Action.SUPPORT_TELEGRAM); startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private void onGitHubClicked() { + private void onGitHubClicked() + { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(MediaLinks.AWALLET_GITHUB)); - try { + try + { + viewModel.track(Analytics.Action.SUPPORT_GITHUB); startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private void onDiscordClicked(){ + private void onDiscordClicked() + { Intent intent; - try { + try + { intent = new Intent(Intent.ACTION_VIEW, Uri.parse(MediaLinks.AWALLET_DISCORD_URL)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } catch (Exception e) { + } + catch (Exception e) + { intent = new Intent(Intent.ACTION_VIEW, Uri.parse(MediaLinks.AWALLET_DISCORD_URL)); } - try { + try + { + viewModel.track(Analytics.Action.SUPPORT_DISCORD); startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private void onEmailClicked() { + private void onEmailClicked() + { Intent intent = new Intent(Intent.ACTION_SENDTO); final String at = "@"; String email = @@ -187,94 +231,133 @@ private void onEmailClicked() { "&body=" + Uri.encode(""); intent.setData(Uri.parse(email)); - try { + try + { + viewModel.track(Analytics.Action.SUPPORT_EMAIL); startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private void onLinkedInClicked() { + private void onLinkedInClicked() + { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(MediaLinks.AWALLET_LINKEDIN_URL)); - if (isAppAvailable(C.LINKEDIN_PACKAGE_NAME)) { + if (isAppAvailable(C.LINKEDIN_PACKAGE_NAME)) + { intent.setPackage(C.LINKEDIN_PACKAGE_NAME); } - try { + try + { startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private void onTwitterClicked() { + private void onTwitterClicked() + { Intent intent; - try { + try + { getPackageManager().getPackageInfo(C.TWITTER_PACKAGE_NAME, 0); intent = new Intent(Intent.ACTION_VIEW, Uri.parse(MediaLinks.AWALLET_TWITTER_URL)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } catch (Exception e) { + } + catch (Exception e) + { intent = new Intent(Intent.ACTION_VIEW, Uri.parse(MediaLinks.AWALLET_TWITTER_URL)); } - try { + try + { + viewModel.track(Analytics.Action.SUPPORT_TWITTER); startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private void onRedditClicked() { + private void onRedditClicked() + { Intent intent = new Intent(Intent.ACTION_VIEW); - if (isAppAvailable(C.REDDIT_PACKAGE_NAME)) { + if (isAppAvailable(C.REDDIT_PACKAGE_NAME)) + { intent.setPackage(C.REDDIT_PACKAGE_NAME); } intent.setData(Uri.parse(MediaLinks.AWALLET_REDDIT_URL)); - try { + try + { startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private void onFacebookClicked() { + private void onFacebookClicked() + { Intent intent; - try { + try + { getPackageManager().getPackageInfo(C.FACEBOOK_PACKAGE_NAME, 0); intent = new Intent(Intent.ACTION_VIEW, Uri.parse(MediaLinks.AWALLET_FACEBOOK_URL)); //intent = new Intent(Intent.ACTION_VIEW, Uri.parse(MediaLinks.AWALLET_FACEBOOK_ID)); - } catch (Exception e) { + } + catch (Exception e) + { intent = new Intent(Intent.ACTION_VIEW, Uri.parse(MediaLinks.AWALLET_FACEBOOK_URL)); } - try { + try + { startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private void onBlogClicked() { + private void onBlogClicked() + { } - private void onFaqClicked() { + private void onFaqClicked() + { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(MediaLinks.AWALLET_FAQ_URL)); - try { + try + { + viewModel.track(Analytics.Action.SUPPORT_FAQ); startActivity(intent); - } catch (Exception e) { + } + catch (Exception e) + { Timber.e(e); } } - private boolean isAppAvailable(String packageName) { + private boolean isAppAvailable(String packageName) + { PackageManager pm = getPackageManager(); - try { + try + { pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES); return true; - } catch (Exception e) { + } + catch (Exception e) + { return false; } } diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index fe122797df..66079ed0c3 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -18,11 +18,14 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.TransactionData; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.analytics.ActionSheetSource; import com.alphawallet.app.entity.lifi.Chain; import com.alphawallet.app.entity.lifi.Connection; import com.alphawallet.app.entity.lifi.Quote; @@ -86,6 +89,7 @@ public class SwapActivity extends BaseActivity implements StandardFunctionInterf private ActivityResultLauncher selectSwapProviderLauncher; private ActivityResultLauncher gasSettingsLauncher; private ActivityResultLauncher getRoutesLauncher; + private AnalyticsProperties confirmationDialogProps; @Override protected void onCreate(@Nullable Bundle savedInstanceState) @@ -291,6 +295,7 @@ private void showConfirmDialog() { confirmationDialog.show(); confirmationDialog.fullExpand(); + viewModel.track(Analytics.Navigation.ACTION_SHEET_FOR_TRANSACTION_CONFIRMATION, confirmationDialogProps); } } @@ -306,6 +311,11 @@ private ActionSheetDialog createConfirmationAction(Quote quote) confDialog.setURL(quote.swapProvider.name); confDialog.setCanceledOnTouchOutside(false); confDialog.setGasEstimate(Numeric.toBigInt(quote.transactionRequest.gasLimit)); + + confirmationDialogProps = new AnalyticsProperties(); + confirmationDialogProps.put(Analytics.PROPS_ACTION_SHEET_SOURCE, ActionSheetSource.SWAP.getValue()); + confirmationDialogProps.put(Analytics.PROPS_SWAP_FROM_TOKEN, quote.action.fromToken.symbol); + confirmationDialogProps.put(Analytics.PROPS_SWAP_TO_TOKEN, quote.action.toToken.symbol); } catch (Exception e) { @@ -352,6 +362,8 @@ private void sourceTokenChanged(Token token) protected void onResume() { super.onResume(); + viewModel.track(Analytics.Navigation.TOKEN_SWAP); + if (settingsDialog != null) { settingsDialog.setSwapProviders(viewModel.getPreferredSwapProviders()); @@ -617,6 +629,8 @@ private void txWritten(TransactionData transactionData) successDialog.setTitle(R.string.transaction_succeeded); successDialog.setMessage(transactionData.txHash); successDialog.show(); + + viewModel.track(Analytics.Navigation.ACTION_SHEET_FOR_TRANSACTION_CONFIRMATION_SUCCESSFUL, confirmationDialogProps); } private void txError(Throwable throwable) @@ -625,6 +639,9 @@ private void txError(Throwable throwable) errorDialog.setTitle(R.string.error_transaction_failed); errorDialog.setMessage(throwable.getMessage()); errorDialog.show(); + + confirmationDialogProps.put(Analytics.PROPS_ERROR_MESSAGE, throwable.getMessage()); + viewModel.track(Analytics.Navigation.ACTION_SHEET_FOR_TRANSACTION_CONFIRMATION_FAILED, confirmationDialogProps); } private void onError(ErrorEnvelope errorEnvelope) @@ -648,6 +665,7 @@ private void onError(ErrorEnvelope errorEnvelope) }); errorDialog.setSecondaryButton(R.string.action_cancel, v -> errorDialog.dismiss()); errorDialog.show(); + viewModel.trackError(Analytics.Error.TOKEN_SWAP, errorEnvelope.message); break; case C.ErrorCode.SWAP_QUOTE_ERROR: errorDialog = new AWalletAlertDialog(this); @@ -659,6 +677,7 @@ private void onError(ErrorEnvelope errorEnvelope) }); errorDialog.setSecondaryButton(R.string.action_cancel, v -> errorDialog.dismiss()); errorDialog.show(); + viewModel.trackError(Analytics.Error.TOKEN_SWAP, errorEnvelope.message); break; default: errorDialog = new AWalletAlertDialog(this); @@ -666,6 +685,7 @@ private void onError(ErrorEnvelope errorEnvelope) errorDialog.setMessage(errorEnvelope.message); errorDialog.setButton(R.string.action_cancel, v -> errorDialog.dismiss()); errorDialog.show(); + viewModel.trackError(Analytics.Error.TOKEN_SWAP, errorEnvelope.message); break; } } @@ -705,13 +725,17 @@ public void sendTransaction(Web3Transaction tx) @Override public void dismissed(String txHash, long callbackId, boolean actionCompleted) { - + if (!actionCompleted && TextUtils.isEmpty(txHash)) + { + viewModel.track(Analytics.Action.ACTION_SHEET_CANCELLED, confirmationDialogProps); + } } @Override public void notifyConfirm(String mode) { - + confirmationDialogProps.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + viewModel.track(Analytics.Action.ACTION_SHEET_COMPLETED, confirmationDialogProps); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java b/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java index 2824943515..2be69432d9 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java @@ -56,7 +56,7 @@ import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.ActionSheetDialog; -import com.alphawallet.app.widget.ActionSheetMode; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.app.widget.AmountDisplayWidget; import com.alphawallet.app.widget.ChainName; import com.alphawallet.app.widget.EventDetailWidget; diff --git a/app/src/main/java/com/alphawallet/app/ui/TokenFunctionActivity.java b/app/src/main/java/com/alphawallet/app/ui/TokenFunctionActivity.java index 850988684e..c822b99c2b 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TokenFunctionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TokenFunctionActivity.java @@ -20,10 +20,13 @@ import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.TransactionData; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.analytics.ActionSheetSource; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.entity.RealmToken; import com.alphawallet.app.service.GasService; @@ -74,6 +77,7 @@ public class TokenFunctionActivity extends BaseActivity implements StandardFunct private Realm realm = null; private RealmResults realmTokenUpdates; private ActionSheetDialog confirmationDialog; + private AnalyticsProperties confirmationDialogProps; private void initViews(Token t) { token = t; @@ -121,6 +125,8 @@ private void txError(Throwable throwable) { throwable.getStackTrace(); Timber.d("ERROR: %s", throwable.getMessage()); + + viewModel.trackError(Analytics.Error.TOKEN_SCRIPT, throwable.getMessage()); } private void onWalletUpdate(Wallet w) @@ -300,6 +306,10 @@ private void checkConfirm(Web3Transaction w3tx) confirmationDialog.setURL("TokenScript"); confirmationDialog.setCanceledOnTouchOutside(false); confirmationDialog.show(); + + confirmationDialogProps = new AnalyticsProperties(); + confirmationDialogProps.put(Analytics.PROPS_ACTION_SHEET_SOURCE, ActionSheetSource.TOKENSCRIPT.getValue()); + viewModel.track(Analytics.Navigation.ACTION_SHEET_FOR_TRANSACTION_CONFIRMATION, confirmationDialogProps); } } @@ -310,6 +320,7 @@ private void checkConfirm(Web3Transaction w3tx) private void txWritten(TransactionData transactionData) { confirmationDialog.transactionWritten(transactionData.txHash); //display hash and success in ActionSheet, start 1 second timer to dismiss. + viewModel.track(Analytics.Navigation.ACTION_SHEET_FOR_TRANSACTION_CONFIRMATION_SUCCESSFUL, confirmationDialogProps); } private void calculateEstimateDialog() @@ -335,6 +346,8 @@ private void errorInsufficientFunds(Token currency) dialog.setButtonText(R.string.button_ok); dialog.setButtonListener(v -> dialog.dismiss()); dialog.show(); + + viewModel.trackError(Analytics.Error.TOKEN_SCRIPT, getString(R.string.error_insufficient_funds)); } private void estimateError(final Web3Transaction w3tx) @@ -434,12 +447,19 @@ public void dismissed(String txHash, long callbackId, boolean actionCompleted) setResult(RESULT_OK, intent); finish(); } + else + { + viewModel.track(Analytics.Action.ACTION_SHEET_CANCELLED, confirmationDialogProps); + } } @Override public void notifyConfirm(String mode) { viewModel.actionSheetConfirm(mode); + + confirmationDialogProps.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + viewModel.track(Analytics.Action.ACTION_SHEET_COMPLETED, confirmationDialogProps); } ActivityResultLauncher getGasSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), diff --git a/app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java b/app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java index 3d4b1b4184..68016c92b6 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java @@ -16,9 +16,10 @@ import androidx.appcompat.app.ActionBar; import androidx.lifecycle.ViewModelProvider; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.Transaction; @@ -33,7 +34,7 @@ import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.ActionSheetDialog; -import com.alphawallet.app.widget.ActionSheetMode; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.app.widget.ChainName; import com.alphawallet.app.widget.CopyTextView; import com.alphawallet.app.widget.FunctionButtonBar; @@ -47,8 +48,6 @@ import java.util.Collections; import java.util.List; -import javax.inject.Inject; - import timber.log.Timber; import static com.alphawallet.app.C.Key.WALLET; @@ -447,7 +446,12 @@ public ActivityResultLauncher gasSelectLauncher() } @Override - public void notifyConfirm(String mode) { viewModel.actionSheetConfirm(mode); } + public void notifyConfirm(String mode) + { + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + viewModel.track(Analytics.Action.ACTION_SHEET_COMPLETED, props); + } private void txWritten(TransactionData transactionData) { diff --git a/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java b/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java index 8d72636e54..0c23a8d980 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java @@ -24,6 +24,8 @@ import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.EnsNodeNotSyncCallback; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.SignAuthenticationCallback; @@ -33,7 +35,7 @@ import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.service.GasService; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.TokensAdapterCallback; import com.alphawallet.app.ui.widget.adapter.NonFungibleTokenAdapter; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; @@ -256,7 +258,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) addressInput.setAddress(extracted_address); } break; - case QRScanner.DENY_PERMISSION: + case QRScannerActivity.DENY_PERMISSION: showCameraDenied(); break; default: @@ -424,7 +426,9 @@ public void dismissed(String txHash, long callbackId, boolean actionCompleted) @Override public void notifyConfirm(String mode) { - viewModel.actionSheetConfirm(mode); + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + viewModel.track(Analytics.Action.ACTION_SHEET_COMPLETED, props); } ActivityResultLauncher getGasSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), diff --git a/app/src/main/java/com/alphawallet/app/ui/TransferTicketDetailActivity.java b/app/src/main/java/com/alphawallet/app/ui/TransferTicketDetailActivity.java index bd868600ce..4aa9aefc67 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TransferTicketDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TransferTicketDetailActivity.java @@ -20,7 +20,6 @@ import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; -import android.util.Log; import android.view.View; import android.view.WindowManager; import android.widget.EditText; @@ -40,6 +39,8 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.DisplayState; import com.alphawallet.app.entity.ErrorEnvelope; @@ -50,7 +51,7 @@ import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.service.GasService; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.TokensAdapterCallback; import com.alphawallet.app.ui.widget.adapter.NonFungibleTokenAdapter; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; @@ -72,7 +73,6 @@ import com.alphawallet.token.tools.Numeric; import org.jetbrains.annotations.NotNull; -import org.web3j.protocol.core.methods.response.EthEstimateGas; import java.math.BigDecimal; import java.math.BigInteger; @@ -85,8 +85,6 @@ import java.util.List; import java.util.Locale; -import javax.inject.Inject; - import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; @@ -98,47 +96,39 @@ */ @AndroidEntryPoint public class TransferTicketDetailActivity extends BaseActivity - implements TokensAdapterCallback, StandardFunctionInterface, AddressReadyCallback, ActionSheetCallback { - private static final int SEND_INTENT_REQUEST_CODE = 2; - + implements TokensAdapterCallback, StandardFunctionInterface, AddressReadyCallback, ActionSheetCallback +{ protected TransferTicketDetailViewModel viewModel; private SystemView systemView; private ProgressView progressView; private AWalletAlertDialog dialog; private FunctionButtonBar functionBar; - private Token token; private NonFungibleTokenAdapter adapter; - private TextView validUntil; private TextView textQuantity; - private String ticketIds; private List selection; private DisplayState transferStatus; - private InputAddress addressInput; private String sendAddress; private String ensAddress; - private ActionSheetDialog actionDialog; private AWalletConfirmationDialog confirmationDialog; - private AppCompatRadioButton pickLink; private AppCompatRadioButton pickTransfer; - private LinearLayout pickTicketQuantity; private LinearLayout pickTransferMethod; private LinearLayout pickExpiryDate; private LinearLayout buttonLinkPick; private LinearLayout buttonTransferPick; - private EditText expiryDateEditText; private EditText expiryTimeEditText; private DatePickerDialog datePickerDialog; private TimePickerDialog timePickerDialog; - private SignAuthenticationCallback signCallback; + private ActivityResultLauncher getGasSettings; + private ActivityResultLauncher transferLinkFinalResult; @Nullable private Disposable calcGasCost; @@ -147,19 +137,44 @@ public class TransferTicketDetailActivity extends BaseActivity protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.activity_transfer_detail); - viewModel = new ViewModelProvider(this) - .get(TransferTicketDetailViewModel.class); + toolbar(); + + getIntentData(); + + initViewModel(); + + initViews(); + initResultLaunchers(); + + setupScreen(); + } + + private void getIntentData() + { long chainId = getIntent().getLongExtra(C.EXTRA_CHAIN_ID, MAINNET_ID); token = viewModel.getTokenService().getToken(chainId, getIntent().getStringExtra(C.EXTRA_ADDRESS)); - ticketIds = getIntent().getStringExtra(EXTRA_TOKENID_LIST); transferStatus = DisplayState.values()[getIntent().getIntExtra(EXTRA_STATE, 0)]; selection = token.stringHexToBigIntegerList(ticketIds); + } - toolbar(); + private void initResultLaunchers() + { + getGasSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> actionDialog.setCurrentGasIndex(result)); + + transferLinkFinalResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> { + LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(PRUNE_ACTIVITY)); //TODO: implement prune via result codes + }); + } + + private void initViews() + { systemView = findViewById(R.id.system_view); systemView.hide(); progressView = findViewById(R.id.progress_view); @@ -171,14 +186,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) sendAddress = null; ensAddress = null; - viewModel.progress().observe(this, systemView::showProgress); - viewModel.queueProgress().observe(this, progressView::updateProgress); - viewModel.pushToast().observe(this, this::displayToast); - viewModel.newTransaction().observe(this, this::onTransaction); - viewModel.error().observe(this, this::onError); - viewModel.universalLinkReady().observe(this, this::linkReady); - viewModel.transactionFinalised().observe(this, this::txWritten); - viewModel.transactionError().observe(this, this::txError); //we should import a token and a list of chosen ids RecyclerView list = findViewById(R.id.listTickets); adapter = new NonFungibleTokenAdapter(null, token, selection, viewModel.getAssetDefinitionService()); @@ -194,39 +201,47 @@ protected void onCreate(@Nullable Bundle savedInstanceState) functionBar = findViewById(R.id.layoutButtons); expiryDateEditText = findViewById(R.id.edit_expiry_date); - expiryDateEditText.addTextChangedListener(new TextWatcher() { + expiryDateEditText.addTextChangedListener(new TextWatcher() + { @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { + public void beforeTextChanged(CharSequence s, int start, int count, int after) + { } @Override @SuppressLint("StringFormatInvalid") - public void onTextChanged(CharSequence s, int start, int before, int count) { + public void onTextChanged(CharSequence s, int start, int before, int count) + { validUntil.setText(getString(R.string.link_valid_until, s.toString(), expiryTimeEditText.getText().toString())); } @Override - public void afterTextChanged(Editable s) { + public void afterTextChanged(Editable s) + { } }); expiryTimeEditText = findViewById(R.id.edit_expiry_time); - expiryTimeEditText.addTextChangedListener(new TextWatcher() { + expiryTimeEditText.addTextChangedListener(new TextWatcher() + { @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { + public void beforeTextChanged(CharSequence s, int start, int count, int after) + { } @SuppressLint("StringFormatInvalid") @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { + public void onTextChanged(CharSequence s, int start, int before, int count) + { validUntil.setText(getString(R.string.link_valid_until, expiryDateEditText.getText().toString(), s.toString())); } @Override - public void afterTextChanged(Editable s) { + public void afterTextChanged(Editable s) + { } }); @@ -239,17 +254,31 @@ public void afterTextChanged(Editable s) { functionBar.setupFunctions(this, new ArrayList<>(Collections.singletonList(R.string.action_next))); functionBar.revealButtons(); + } - setupScreen(); + private void initViewModel() + { + viewModel = new ViewModelProvider(this) + .get(TransferTicketDetailViewModel.class); + viewModel.progress().observe(this, systemView::showProgress); + viewModel.queueProgress().observe(this, progressView::updateProgress); + viewModel.pushToast().observe(this, this::displayToast); + viewModel.newTransaction().observe(this, this::onTransaction); + viewModel.error().observe(this, this::onError); + viewModel.universalLinkReady().observe(this, this::linkReady); + viewModel.transactionFinalised().observe(this, this::txWritten); + viewModel.transactionError().observe(this, this::txError); } //TODO: This is repeated code also in SellDetailActivity. Probably should be abstracted out into generic view code routine - private void initQuantitySelector() { + private void initQuantitySelector() + { pickTicketQuantity.setVisibility(View.VISIBLE); RelativeLayout plusButton = findViewById(R.id.layout_quantity_add); plusButton.setOnClickListener(v -> { int quantity = Integer.parseInt(textQuantity.getText().toString()); - if ((quantity + 1) <= adapter.getTicketRangeCount()) { + if ((quantity + 1) <= adapter.getTicketRangeCount()) + { quantity++; textQuantity.setText(String.valueOf(quantity)); selection = token.pruneIDList(ticketIds, quantity); @@ -259,7 +288,8 @@ private void initQuantitySelector() { RelativeLayout minusButton = findViewById(R.id.layout_quantity_minus); minusButton.setOnClickListener(v -> { int quantity = Integer.parseInt(textQuantity.getText().toString()); - if ((quantity - 1) > 0) { + if ((quantity - 1) > 0) + { quantity--; textQuantity.setText(String.valueOf(quantity)); selection = token.pruneIDList(ticketIds, 1); @@ -352,7 +382,7 @@ public void gotAuthorisation(boolean gotAuth) if (gotAuth) { - if(token.isERC721Ticket()) + if (token.isERC721Ticket()) { viewModel.generateSpawnLink(selection, token.getAddress(), calculateExpiryTime()); } @@ -525,7 +555,8 @@ protected void onDestroy() } @Override - public void onTokenClick(View view, Token token, List ids, boolean selection) { + public void onTokenClick(View view, Token token, List ids, boolean selection) + { Context context = view.getContext(); //TODO: what action should be performed when clicking on a range? } @@ -571,12 +602,12 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) addressInput.setAddress(extracted_address); } break; - case QRScanner.DENY_PERMISSION: + case QRScannerActivity.DENY_PERMISSION: showCameraDenied(); break; default: Timber.tag("SEND").e(String.format(getString(R.string.barcode_error_format), - "Code: " + resultCode + "Code: " + resultCode )); break; } @@ -589,7 +620,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) finish(); break; case SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS: - if (actionDialog != null && actionDialog.isShowing()) actionDialog.completeSignRequest(resultCode == RESULT_OK); + if (actionDialog != null && actionDialog.isShowing()) + actionDialog.completeSignRequest(resultCode == RESULT_OK); //signCallback.gotAuthorisation(resultCode == RESULT_OK); break; @@ -614,7 +646,7 @@ private void showCameraDenied() private void linkReady(String universalLink) { int quantity = 1; - if(selection != null) + if (selection != null) { quantity = selection.size(); } @@ -684,11 +716,6 @@ public void cancelAuthentication() confirmationDialog.show(); } - ActivityResultLauncher transferLinkFinalResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> { - LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(PRUNE_ACTIVITY)); //TODO: implement prune via result codes - }); - private void transferLinkFinal(String universalLink) { //create share intent @@ -728,7 +755,7 @@ private void initTimePicker() //set for now String time = String.format(Locale.getDefault(), "%02d:%02d", Calendar.getInstance().get(Calendar.HOUR_OF_DAY), - Calendar.getInstance().get(Calendar.MINUTE)); + Calendar.getInstance().get(Calendar.MINUTE)); expiryTimeEditText.setText(time); } @@ -781,7 +808,7 @@ private void calculateTransactionCost() final String txSendAddress = sendAddress; sendAddress = null; - final byte[] transactionBytes = viewModel.getERC721TransferBytes(txSendAddress,token.getAddress(),ticketIds, token.tokenInfo.chainId); + final byte[] transactionBytes = viewModel.getERC721TransferBytes(txSendAddress, token.getAddress(), ticketIds, token.tokenInfo.chainId); if (token.isEthereum()) { checkConfirm(BigInteger.valueOf(GAS_LIMIT_MIN), transactionBytes, txSendAddress, txSendAddress); @@ -804,7 +831,6 @@ private void handleError(Throwable throwable, final byte[] transactionBytes, fin checkConfirm(BigInteger.ZERO, transactionBytes, txSendAddress, resolvedAddress); } - private void calculateEstimateDialog() { if (dialog != null && dialog.isShowing()) dialog.dismiss(); @@ -819,7 +845,8 @@ private void calculateEstimateDialog() /** * Called to check if we're ready to send user to confirm screen / activity sheet popup */ - private void checkConfirm(final BigInteger sendGasLimit, final byte[] transactionBytes, final String txSendAddress, final String resolvedAddress) { + private void checkConfirm(final BigInteger sendGasLimit, final byte[] transactionBytes, final String txSendAddress, final String resolvedAddress) + { Web3Transaction w3tx = new Web3Transaction( new Address(txSendAddress), @@ -869,7 +896,8 @@ public void sendTransaction(Web3Transaction finalTx) public void dismissed(String txHash, long callbackId, boolean actionCompleted) { //ActionSheet was dismissed - if (!TextUtils.isEmpty(txHash)) { + if (!TextUtils.isEmpty(txHash)) + { Intent intent = new Intent(); intent.putExtra(C.EXTRA_TXHASH, txHash); setResult(RESULT_OK, intent); @@ -878,10 +906,12 @@ public void dismissed(String txHash, long callbackId, boolean actionCompleted) } @Override - public void notifyConfirm(String mode) { viewModel.actionSheetConfirm(mode); } - - ActivityResultLauncher getGasSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> actionDialog.setCurrentGasIndex(result)); + public void notifyConfirm(String mode) + { + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + viewModel.track(Analytics.Action.ACTION_SHEET_COMPLETED, props); + } @Override public ActivityResultLauncher gasSelectLauncher() diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java index be4b655737..0af50cb176 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java @@ -30,6 +30,8 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.DAppFunction; import com.alphawallet.app.entity.NetworkInfo; @@ -37,6 +39,7 @@ import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.analytics.ActionSheetSource; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.walletconnect.WCRequest; import com.alphawallet.app.repository.EthereumNetworkBase; @@ -88,9 +91,9 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa private static final String DEFAULT_IDON = "https://example.walletconnect.org/favicon.ico"; private static final long CONNECT_TIMEOUT = 10 * DateUtils.SECOND_IN_MILLIS; // 10 Seconds timeout private final Handler handler = new Handler(Looper.getMainLooper()); - private LocalBroadcastManager broadcastManager; private final long switchChainDialogCallbackId = 1; - WalletConnectViewModel viewModel; + private WalletConnectViewModel viewModel; + private LocalBroadcastManager broadcastManager; private WCClient client; private WCSession session; private WCPeerMeta peerMeta; @@ -183,7 +186,6 @@ public void onReceive(Context context, Intent intent) Timber.tag(TAG).d("MSG: ADD CHAIN"); onAddChainRequest(intent); break; - } } }; @@ -645,6 +647,8 @@ private void invalidSession() }); dialog.setCancelable(false); dialog.show(); + + viewModel.trackError(Analytics.Error.WALLET_CONNECT, getString(R.string.invalid_walletconnect_session)); } private void initWalletConnectPeerMeta() @@ -776,6 +780,8 @@ private void onSessionRequest(Long id, WCPeerMeta peer, long chainId) confirmationDialog = new ActionSheetDialog(this, peer, chainId, displayIcon, this); confirmationDialog.show(); confirmationDialog.fullExpand(); + + viewModel.track(Analytics.Action.WALLET_CONNECT_SESSION_REQUEST); } private void onEthSign(Long id, WCEthereumSignMessage message) @@ -819,6 +825,10 @@ private void onFailure(@NonNull Throwable throwable) }); dialog.setCancelable(false); dialog.show(); + + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ERROR_MESSAGE, throwable.getMessage()); + viewModel.track(Analytics.Action.WALLET_CONNECT_TRANSACTION_FAILED, props); } private void doSignMessage(final Signable signable) @@ -895,6 +905,8 @@ public void cancelAuthentication() confirmationDialog = new ActionSheetDialog(this, this, signCallback, signable); confirmationDialog.setCanceledOnTouchOutside(false); confirmationDialog.show(); + + viewModel.track(Analytics.Action.WALLET_CONNECT_SIGN_MESSAGE_REQUEST); } private void onEthSignTransaction(Long id, WCEthereumTransaction transaction, long chainId) @@ -907,6 +919,8 @@ private void onEthSignTransaction(Long id, WCEthereumTransaction transaction, lo confirmationDialog = confDialog; confirmationDialog.setSignOnly(); //sign transaction only confirmationDialog.show(); + + viewModel.track(Analytics.Action.WALLET_CONNECT_SIGN_TRANSACTION_REQUEST); } } @@ -919,6 +933,8 @@ private void onEthSendTransaction(Long id, WCEthereumTransaction transaction, lo { confirmationDialog = confDialog; confirmationDialog.show(); + + viewModel.track(Analytics.Action.WALLET_CONNECT_SEND_TRANSACTION_REQUEST); } } @@ -961,6 +977,7 @@ private void killSession() Timber.tag(TAG).d(": Terminate Session: %s", getSessionId()); if (client != null && session != null && client.isConnected()) { + viewModel.track(Analytics.Action.WALLET_CONNECT_SESSION_ENDED); client.killSession(); viewModel.disconnectSession(this, client.sessionId()); handler.postDelayed(this::finish, 5000); @@ -982,6 +999,7 @@ public void onPause() public void onResume() { super.onResume(); + viewModel.track(Analytics.Navigation.WALLET_CONNECT_SESSION_DETAIL); //see if the session is active setupClient(getSessionId()); startMessageCheck(); @@ -1010,6 +1028,8 @@ private void showTimeoutDialog() }); dialog.setCancelable(false); dialog.show(); + + viewModel.track(Analytics.Action.WALLET_CONNECT_CONNECTION_TIMEOUT); }); } } @@ -1030,6 +1050,8 @@ private void showErrorDialog(String message) }); dialog.setCancelable(false); dialog.show(); + + viewModel.trackError(Analytics.Error.WALLET_CONNECT, message); }); } } @@ -1046,6 +1068,8 @@ private void showErrorDialogCancel(String title, String message) dialog.setButton(R.string.action_cancel, v -> dialog.dismiss()); dialog.setCancelable(false); dialog.show(); + + viewModel.trackError(Analytics.Error.WALLET_CONNECT, message); }); } } @@ -1102,6 +1126,8 @@ private void showErrorDialogTerminate(String message) }); dialog.setCancelable(false); dialog.show(); + + viewModel.trackError(Analytics.Error.WALLET_CONNECT, message); }); } } @@ -1200,6 +1226,8 @@ public void transactionSuccess(Web3Transaction web3Tx, String hashData) confirmationDialog.transactionWritten(hashData); requestId = 0; updateSignCount(); + + viewModel.track(Analytics.Action.WALLET_CONNECT_TRANSACTION_SUCCESS); } @Override @@ -1229,6 +1257,10 @@ private void displayTransactionError(final Throwable throwable) dialog.setButtonText(R.string.button_ok); dialog.setButtonListener(v -> dialog.dismiss()); dialog.show(); + + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ERROR_MESSAGE, throwable.getMessage()); + viewModel.track(Analytics.Action.WALLET_CONNECT_TRANSACTION_FAILED, props); }); } } @@ -1240,6 +1272,7 @@ public void dismissed(String txHash, long callbackId, boolean actionCompleted) if (!actionCompleted) { viewModel.rejectRequest(this, getSessionId(), callbackId, getString(R.string.message_reject_request)); + viewModel.track(Analytics.Action.WALLET_CONNECT_TRANSACTION_CANCELLED); } if (fromDappBrowser) switchToDappBrowser(); @@ -1250,7 +1283,10 @@ public void dismissed(String txHash, long callbackId, boolean actionCompleted) @Override public void notifyConfirm(String mode) { - viewModel.actionSheetConfirm(mode); + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + props.put(Analytics.PROPS_ACTION_SHEET_SOURCE, ActionSheetSource.WALLET_CONNECT.getValue()); + viewModel.track(Analytics.Action.ACTION_SHEET_COMPLETED, props); } @Override @@ -1305,6 +1341,7 @@ public void notifyWalletConnectApproval(long selectedChain) infoLayout.setVisibility(View.VISIBLE); chainIdOverride = selectedChain; setupClient(getSessionId()); //should populate this activity + viewModel.track(Analytics.Action.WALLET_CONNECT_SESSION_APPROVED); if (fromDappBrowser) { //switch back to dappBrowser @@ -1316,6 +1353,7 @@ public void notifyWalletConnectApproval(long selectedChain) public void denyWalletConnect() { client.rejectSession(getString(R.string.message_reject_request)); + viewModel.track(Analytics.Action.WALLET_CONNECT_SESSION_REJECTED); finish(); } @@ -1348,6 +1386,8 @@ private void showSwitchChainDialog() confirmationDialog.setCanceledOnTouchOutside(false); confirmationDialog.show(); confirmationDialog.fullExpand(); + + viewModel.track(Analytics.Action.WALLET_CONNECT_SWITCH_NETWORK_REQUEST); } catch (Exception e) { diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java index f38c533eaa..021229dad5 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java @@ -29,10 +29,12 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.analytics.QrScanSource; import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; import com.alphawallet.app.repository.EthereumNetworkRepository; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.viewmodel.WalletConnectViewModel; import com.alphawallet.app.widget.AWalletAlertDialog; import com.bumptech.glide.Glide; @@ -163,6 +165,8 @@ public void onResume() initViewModel(); setupList(); startConnectionCheck(); + + viewModel.track(Analytics.Navigation.WALLET_CONNECT_SESSIONS); } @Override @@ -194,8 +198,9 @@ else if (item.getItemId() == R.id.action_delete) private void openQrScanner() { - Intent intent = new Intent(this, QRScanner.class); + Intent intent = new Intent(this, QRScannerActivity.class); intent.putExtra("wallet", wallet); + intent.putExtra(QrScanSource.KEY, QrScanSource.WALLET_CONNECT.getValue()); intent.putExtra(C.EXTRA_UNIVERSAL_SCAN, true); startActivity(intent); } diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java index 9d9f946406..53b51f98d7 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java @@ -39,6 +39,7 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.BackupOperationType; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.CustomViewSettings; @@ -97,36 +98,10 @@ public class WalletFragment extends BaseFragment implements { public static final String SEARCH_FRAGMENT = "w_search"; private static final String TAG = "WFRAG"; - final ActivityResultLauncher tokenManagementLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - if (result.getData() == null) return; - ArrayList tokenData = result.getData().getParcelableArrayListExtra(ADDED_TOKEN); - Bundle b = new Bundle(); - b.putParcelableArrayList(C.ADDED_TOKEN, tokenData); - getParentFragmentManager().setFragmentResult(C.ADDED_TOKEN, b); - }); private final Handler handler = new Handler(Looper.getMainLooper()); private WalletViewModel viewModel; private SystemView systemView; private TokensAdapter adapter; - ActivityResultLauncher handleBackupClick = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - String keyBackup = null; - boolean noLockScreen = false; - Intent data = result.getData(); - if (data != null) keyBackup = data.getStringExtra("Key"); - if (data != null) noLockScreen = data.getBooleanExtra("nolock", false); - if (result.getResultCode() == RESULT_OK) - { - ((HomeActivity) getActivity()).backupWalletSuccess(keyBackup); - } - else - { - ((HomeActivity) getActivity()).backupWalletFail(keyBackup, noLockScreen); - } - }); private UserAvatar addressAvatar; private View selectedToken; private String importFileName; @@ -138,12 +113,9 @@ public class WalletFragment extends BaseFragment implements private RealmResults realmUpdates; private LargeTitleView largeTitleView; private long realmUpdateTime; - private ActivityResultLauncher networkSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), - result -> - { - //send instruction to restart tokenService - getParentFragmentManager().setFragmentResult(RESET_TOKEN_SERVICE, new Bundle()); - }); + private ActivityResultLauncher networkSettingsHandler; + private ActivityResultLauncher handleBackupClick; + private ActivityResultLauncher tokenManagementLauncher; @Nullable @Override @@ -162,6 +134,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c toolbar(view); } + initResultLaunchers(); + initViews(view); initViewModel(); @@ -194,6 +168,44 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c return view; } + private void initResultLaunchers() + { + tokenManagementLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + if (result.getData() == null) return; + ArrayList tokenData = result.getData().getParcelableArrayListExtra(ADDED_TOKEN); + Bundle b = new Bundle(); + b.putParcelableArrayList(C.ADDED_TOKEN, tokenData); + getParentFragmentManager().setFragmentResult(C.ADDED_TOKEN, b); + }); + + networkSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + //send instruction to restart tokenService + getParentFragmentManager().setFragmentResult(RESET_TOKEN_SERVICE, new Bundle()); + }); + + handleBackupClick = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + String keyBackup = null; + boolean noLockScreen = false; + Intent data = result.getData(); + if (data != null) keyBackup = data.getStringExtra("Key"); + if (data != null) noLockScreen = data.getBooleanExtra("nolock", false); + if (result.getResultCode() == RESULT_OK) + { + ((HomeActivity) getActivity()).backupWalletSuccess(keyBackup); + } + else + { + ((HomeActivity) getActivity()).backupWalletFail(keyBackup, noLockScreen); + } + }); + } + private void initList() { adapter = new TokensAdapter(this, viewModel.getAssetDefinitionService(), viewModel.getTokensService(), @@ -520,6 +532,7 @@ public void onBuyToken() buyEthOptionsView.setOnBuyWithRampListener(v -> { Intent intent = viewModel.getBuyIntent(getCurrentWallet().address); ((HomeActivity) getActivity()).onActivityResult(C.TOKEN_SEND_ACTIVITY, RESULT_OK, intent); + viewModel.track(Analytics.Action.BUY_WITH_RAMP); buyEthDialog.dismiss(); }); buyEthOptionsView.setOnBuyWithCoinbasePayListener(v -> { @@ -539,9 +552,13 @@ public void onResume() { requireActivity().recreate(); } - else if (largeTitleView != null) + else { - largeTitleView.setVisibility(viewModel.getTokensService().isMainNetActive() ? View.VISIBLE : View.GONE); //show or hide Fiat summary + viewModel.track(Analytics.Navigation.WALLET); + if (largeTitleView != null) + { + largeTitleView.setVisibility(viewModel.getTokensService().isMainNetActive() ? View.VISIBLE : View.GONE); //show or hide Fiat summary + } } } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/GasWidgetInterface.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/GasWidgetInterface.java index 68da72215a..424a813b00 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/GasWidgetInterface.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/GasWidgetInterface.java @@ -1,7 +1,7 @@ package com.alphawallet.app.ui.widget.entity; import com.alphawallet.app.web3.entity.Web3Transaction; -import com.alphawallet.app.widget.ActionSheetMode; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import java.math.BigDecimal; import java.math.BigInteger; diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/ActivityViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/ActivityViewModel.java index 23da4def63..cb956a3a2d 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/ActivityViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/ActivityViewModel.java @@ -9,6 +9,7 @@ import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.interact.FetchTransactionsInteract; import com.alphawallet.app.interact.GenericWalletInteract; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.RealmManager; import com.alphawallet.app.service.TokensService; @@ -59,13 +60,15 @@ public LiveData defaultWallet() { AssetDefinitionService assetDefinitionService, TokensService tokensService, TransactionsService transactionsService, - RealmManager realmManager) { + RealmManager realmManager, + AnalyticsServiceType analyticsService) { this.genericWalletInteract = genericWalletInteract; this.fetchTransactionsInteract = fetchTransactionsInteract; this.assetDefinitionService = assetDefinitionService; this.tokensService = tokensService; this.transactionsService = transactionsService; this.realmManager = realmManager; + setAnalyticsService(analyticsService); } public void prepare() diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/AddEditDappViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/AddEditDappViewModel.java new file mode 100644 index 0000000000..886cac7418 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/AddEditDappViewModel.java @@ -0,0 +1,17 @@ +package com.alphawallet.app.viewmodel; + +import com.alphawallet.app.service.AnalyticsServiceType; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; + +@HiltViewModel +public class AddEditDappViewModel extends BaseViewModel +{ + @Inject + AddEditDappViewModel(AnalyticsServiceType analyticsService) + { + setAnalyticsService(analyticsService); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/BaseViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/BaseViewModel.java index fd35da3f75..2f30e1de81 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/BaseViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/BaseViewModel.java @@ -1,109 +1,170 @@ package com.alphawallet.app.viewmodel; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; - import android.app.Activity; import android.content.Context; import android.text.TextUtils; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + import com.alphawallet.app.C; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.ServiceException; import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.service.AnalyticsServiceType; + +import org.json.JSONObject; + import io.reactivex.disposables.Disposable; import timber.log.Timber; public class BaseViewModel extends ViewModel { - protected final MutableLiveData error = new MutableLiveData<>(); - protected final MutableLiveData progress = new MutableLiveData<>(); - protected Disposable disposable; - protected static final MutableLiveData queueCompletion = new MutableLiveData<>(); - protected static final MutableLiveData pushToastMutable = new MutableLiveData<>(); - protected static final MutableLiveData successDialogMutable = new MutableLiveData<>(); - protected static final MutableLiveData errorDialogMutable = new MutableLiveData<>(); - protected static final MutableLiveData refreshTokens = new MutableLiveData<>(); - - @Override - protected void onCleared() - { - cancel(); - } - - private void cancel() - { - if (disposable != null && !disposable.isDisposed()) - { - disposable.dispose(); - } - } - - public LiveData error() - { - return error; - } - - public LiveData progress() - { - return progress; - } - - public LiveData queueProgress() - { - return queueCompletion; - } - - public LiveData pushToast() - { - return pushToastMutable; - } - - public LiveData refreshTokens() { - return refreshTokens; - } - - protected void onError(Throwable throwable) - { - Timber.tag("TAG").d(throwable, "Err"); - if (throwable instanceof ServiceException) - { - error.postValue(((ServiceException) throwable).error); - } - else - { - String message = throwable.getMessage(); - if (TextUtils.isEmpty(message)) - { - error.postValue(new ErrorEnvelope(C.ErrorCode.UNKNOWN, null, throwable)); - } - else - { - error.postValue(new ErrorEnvelope(C.ErrorCode.UNKNOWN, message, throwable)); - } - } - } - - public static void onQueueUpdate(int complete) - { - queueCompletion.postValue(complete); - } - - public static void onPushToast(String message) - { - pushToastMutable.postValue(message); - } - - public void showSendToken(Context context, String address, String symbol, int decimals, Token token) { - //do nothing - } - - public void showTokenList(Activity activity, Token token) { - //do nothing - } - - public void showErc20TokenDetail(Activity context, String address, String symbol, int decimals, Token token) { - //do nothing - } + protected static final MutableLiveData queueCompletion = new MutableLiveData<>(); + protected static final MutableLiveData pushToastMutable = new MutableLiveData<>(); + protected static final MutableLiveData successDialogMutable = new MutableLiveData<>(); + protected static final MutableLiveData errorDialogMutable = new MutableLiveData<>(); + protected static final MutableLiveData refreshTokens = new MutableLiveData<>(); + protected final MutableLiveData error = new MutableLiveData<>(); + protected final MutableLiveData progress = new MutableLiveData<>(); + protected Disposable disposable; + private AnalyticsServiceType analyticsService; + + public static void onQueueUpdate(int complete) + { + queueCompletion.postValue(complete); + } + + public static void onPushToast(String message) + { + pushToastMutable.postValue(message); + } + + @Override + protected void onCleared() + { + cancel(); + } + + private void cancel() + { + if (disposable != null && !disposable.isDisposed()) + { + disposable.dispose(); + } + } + + public LiveData error() + { + return error; + } + + public LiveData progress() + { + return progress; + } + + public LiveData queueProgress() + { + return queueCompletion; + } + + public LiveData pushToast() + { + return pushToastMutable; + } + + public LiveData refreshTokens() + { + return refreshTokens; + } + + protected void onError(Throwable throwable) + { + Timber.e(throwable); + if (throwable instanceof ServiceException) + { + error.postValue(((ServiceException) throwable).error); + } + else + { + String message = TextUtils.isEmpty(throwable.getMessage()) ? + "Unknown Error" : throwable.getMessage(); + error.postValue(new ErrorEnvelope(C.ErrorCode.UNKNOWN, message, throwable)); + } + } + + public void showSendToken(Context context, String address, String symbol, int decimals, Token token) + { + //do nothing + } + + public void showTokenList(Activity activity, Token token) + { + //do nothing + } + + public void showErc20TokenDetail(Activity context, String address, String symbol, int decimals, Token token) + { + //do nothing + } + + protected void setAnalyticsService(AnalyticsServiceType analyticsService) + { + this.analyticsService = analyticsService; + } + + public void identify(String uuid) + { + if (analyticsService != null) + { + analyticsService.identify(uuid); + } + } + + public void track(Analytics.Navigation event) + { + trackEvent(event.getValue()); + } + + public void track(Analytics.Navigation event, AnalyticsProperties props) + { + trackEventWithProps(event.getValue(), props); + } + + public void track(Analytics.Action event) + { + trackEvent(event.getValue()); + } + + public void track(Analytics.Action event, AnalyticsProperties props) + { + trackEventWithProps(event.getValue(), props); + } + + public void trackError(Analytics.Error source, String message) + { + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ERROR_MESSAGE, message); + trackEventWithProps(source.getValue(), props); + } + + private void trackEvent(String event) + { + if (analyticsService != null) + { + analyticsService.track(event); + } + } + + private void trackEventWithProps(String event, AnalyticsProperties props) + { + if (analyticsService != null) + { + analyticsService.track(event, props); + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/BrowserHistoryViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/BrowserHistoryViewModel.java new file mode 100644 index 0000000000..ea2500058d --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/BrowserHistoryViewModel.java @@ -0,0 +1,17 @@ +package com.alphawallet.app.viewmodel; + +import com.alphawallet.app.service.AnalyticsServiceType; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; + +@HiltViewModel +public class BrowserHistoryViewModel extends BaseViewModel +{ + @Inject + BrowserHistoryViewModel(AnalyticsServiceType analyticsService) + { + setAnalyticsService(analyticsService); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/CoinbasePayViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/CoinbasePayViewModel.java index 2094d749c9..8f0584d347 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/CoinbasePayViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/CoinbasePayViewModel.java @@ -4,8 +4,6 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import com.alphawallet.app.C; -import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.coinbasepay.DestinationWallet; import com.alphawallet.app.interact.GenericWalletInteract; @@ -24,7 +22,6 @@ public class CoinbasePayViewModel extends BaseViewModel { private final GenericWalletInteract genericWalletInteract; private final CoinbasePayRepositoryType coinbasePayRepository; - private final AnalyticsServiceType analyticsService; private final MutableLiveData defaultWallet = new MutableLiveData<>(); private final MutableLiveData signature = new MutableLiveData<>(); @@ -37,7 +34,7 @@ public CoinbasePayViewModel(GenericWalletInteract genericWalletInteract, { this.genericWalletInteract = genericWalletInteract; this.coinbasePayRepository = coinbasePayRepository; - this.analyticsService = analyticsService; + setAnalyticsService(analyticsService); } public LiveData defaultWallet() @@ -60,9 +57,6 @@ private void onDefaultWallet(final Wallet wallet) public String getUri(DestinationWallet.Type type, String address, List list) { - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData(type.toString() + ": " + list.get(0)); - analyticsService.track(C.AN_USE_COINBASE_PAY, analyticsProperties); return coinbasePayRepository.getUri(type, address, list); } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/CustomNetworkViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/CustomNetworkViewModel.java index 1f1182a660..eec78d7c4e 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/CustomNetworkViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/CustomNetworkViewModel.java @@ -1,8 +1,11 @@ package com.alphawallet.app.viewmodel; +import com.alphawallet.app.analytics.Analytics; +import com.alphawallet.app.entity.AnalyticsProperties; +import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; -import com.alphawallet.app.entity.NetworkInfo; +import com.alphawallet.app.service.AnalyticsServiceType; import javax.inject.Inject; @@ -15,20 +18,32 @@ public class CustomNetworkViewModel extends BaseViewModel @Inject CustomNetworkViewModel( - EthereumNetworkRepositoryType ethereumNetworkRepository) + EthereumNetworkRepositoryType ethereumNetworkRepository, + AnalyticsServiceType analyticsService) { this.ethereumNetworkRepository = ethereumNetworkRepository; + setAnalyticsService(analyticsService); } - public void saveNetwork(String name, String rpcUrl, long chainId, String symbol, String blockExplorerUrl, String explorerApiUrl, boolean isTestnet, Long oldChainId) { + public void saveNetwork(boolean isEditMode, String name, String rpcUrl, long chainId, String symbol, String blockExplorerUrl, String explorerApiUrl, boolean isTestnet, Long oldChainId) + { this.ethereumNetworkRepository.saveCustomRPCNetwork(name, rpcUrl, chainId, symbol, blockExplorerUrl, explorerApiUrl, isTestnet, oldChainId); + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_CUSTOM_NETWORK_NAME, name); + props.put(Analytics.PROPS_CUSTOM_NETWORK_RPC_URL, rpcUrl); + props.put(Analytics.PROPS_CUSTOM_NETWORK_CHAIN_ID, chainId); + props.put(Analytics.PROPS_CUSTOM_NETWORK_SYMBOL, symbol); + props.put(Analytics.PROPS_CUSTOM_NETWORK_IS_TESTNET, isTestnet); + track(isEditMode? Analytics.Action.EDIT_CUSTOM_CHAIN : Analytics.Action.ADD_CUSTOM_CHAIN, props); } - public NetworkInfo getNetworkInfo(long chainId) { + public NetworkInfo getNetworkInfo(long chainId) + { return this.ethereumNetworkRepository.getNetworkByChain(chainId); } - public boolean isTestNetwork(NetworkInfo network) { + public boolean isTestNetwork(NetworkInfo network) + { return !EthereumNetworkRepository.hasRealValue(network.chainId); } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java index 069d852345..5c67eb2cd1 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java @@ -17,6 +17,7 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.DApp; import com.alphawallet.app.entity.DAppFunction; import com.alphawallet.app.entity.NetworkInfo; @@ -25,9 +26,11 @@ import com.alphawallet.app.entity.SendTransactionInterface; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.analytics.QrScanSource; import com.alphawallet.app.interact.CreateTransactionInteract; import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.GasService; import com.alphawallet.app.service.KeyService; @@ -36,7 +39,7 @@ import com.alphawallet.app.ui.HomeActivity; import com.alphawallet.app.ui.ImportTokenActivity; import com.alphawallet.app.ui.MyAddressActivity; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.SendActivity; import com.alphawallet.app.ui.WalletConnectActivity; import com.alphawallet.app.util.DappBrowserUtils; @@ -61,7 +64,8 @@ import io.realm.Realm; @HiltViewModel -public class DappBrowserViewModel extends BaseViewModel { +public class DappBrowserViewModel extends BaseViewModel +{ private static final int BALANCE_CHECK_INTERVAL_SECONDS = 20; private final MutableLiveData activeNetwork = new MutableLiveData<>(); @@ -85,7 +89,9 @@ public class DappBrowserViewModel extends BaseViewModel { TokensService tokensService, EthereumNetworkRepositoryType ethereumNetworkRepository, KeyService keyService, - GasService gasService) { + GasService gasService, + AnalyticsServiceType analyticsService) + { this.genericWalletInteract = genericWalletInteract; this.assetDefinitionService = assetDefinitionService; this.createTransactionInteract = createTransactionInteract; @@ -93,21 +99,26 @@ public class DappBrowserViewModel extends BaseViewModel { this.ethereumNetworkRepository = ethereumNetworkRepository; this.keyService = keyService; this.gasService = gasService; + setAnalyticsService(analyticsService); } - public AssetDefinitionService getAssetDefinitionService() { + public AssetDefinitionService getAssetDefinitionService() + { return assetDefinitionService; } - public LiveData activeNetwork() { + public LiveData activeNetwork() + { return activeNetwork; } - public LiveData defaultWallet() { + public LiveData defaultWallet() + { return defaultWallet; } - public void findWallet() { + public void findWallet() + { disposable = genericWalletInteract .find() .subscribe(this::onDefaultWallet, this::onError); @@ -123,7 +134,8 @@ public void checkForNetworkChanges() activeNetwork.postValue(ethereumNetworkRepository.getActiveBrowserNetwork()); } - private void onDefaultWallet(final Wallet wallet) { + private void onDefaultWallet(final Wallet wallet) + { defaultWallet.setValue(wallet); } @@ -135,34 +147,39 @@ private void checkBalance(final Wallet wallet) disposable = tokensService.getChainBalance(wallet.address.toLowerCase(), info.chainId) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) - .subscribe(w -> { }, e -> { }); + .subscribe(w -> {}, e -> {}); } } - public void signMessage(Signable message, DAppFunction dAppFunction) { + public void signMessage(Signable message, DAppFunction dAppFunction) + { disposable = createTransactionInteract.sign(defaultWallet.getValue(), message, - getActiveNetwork().chainId) + getActiveNetwork().chainId) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(sig -> dAppFunction.DAppReturn(sig.signature, message), error -> dAppFunction.DAppError(error, message)); } - public void setLastUrl(Context context, String url) { + public void setLastUrl(Context context, String url) + { PreferenceManager.getDefaultSharedPreferences(context) .edit().putString(C.DAPP_LASTURL_KEY, url).apply(); } - public void setHomePage(Context context, String url) { + public void setHomePage(Context context, String url) + { PreferenceManager.getDefaultSharedPreferences(context) .edit().putString(C.DAPP_HOMEPAGE_KEY, url).apply(); } - public String getHomePage(Context context) { + public String getHomePage(Context context) + { return PreferenceManager.getDefaultSharedPreferences(context).getString(C.DAPP_HOMEPAGE_KEY, null); } - public void addToMyDapps(Context context, String title, String url) { + public void addToMyDapps(Context context, String title, String url) + { Intent intent = new Intent(context, AddEditDappActivity.class); DApp dapp = new DApp(title, url); intent.putExtra(AddEditDappActivity.KEY_DAPP, dapp); @@ -170,7 +187,9 @@ public void addToMyDapps(Context context, String title, String url) { context.startActivity(intent); } - public void share(Context context, String url) { + public void share(Context context, String url) + { + track(Analytics.Action.SHARE_URL); Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_TEXT, url); @@ -178,19 +197,24 @@ public void share(Context context, String url) { context.startActivity(intent); } - public void onClearBrowserCacheClicked(Context context) { + public void onClearBrowserCacheClicked(Context context) + { WebView webView = new WebView(context); webView.clearCache(true); Toast.makeText(context, context.getString(R.string.toast_browser_cache_cleared), Toast.LENGTH_SHORT).show(); + track(Analytics.Action.CLEAR_BROWSER_CACHE); } - public void startScan(Activity activity) { - Intent intent = new Intent(activity, QRScanner.class); + public void startScan(Activity activity) + { + Intent intent = new Intent(activity, QRScannerActivity.class); + intent.putExtra(QrScanSource.KEY, QrScanSource.BROWSER_SCREEN.getValue()); activity.startActivityForResult(intent, HomeActivity.DAPP_BARCODE_READER_REQUEST_CODE); } - public List getDappsMasterList(Context context) { + public List getDappsMasterList(Context context) + { return DappBrowserUtils.getDappsList(context); } @@ -277,7 +301,8 @@ public void showMyAddress(Context ctx) public void onDestroy() { - if (balanceTimerDisposable != null && !balanceTimerDisposable.isDisposed()) balanceTimerDisposable.dispose(); + if (balanceTimerDisposable != null && !balanceTimerDisposable.isDisposed()) + balanceTimerDisposable.dispose(); gasService.stopGasPriceCycle(); } @@ -302,7 +327,8 @@ public void startBalanceUpdate() public void stopBalanceUpdate() { - if (balanceTimerDisposable != null && !balanceTimerDisposable.isDisposed()) balanceTimerDisposable.dispose(); + if (balanceTimerDisposable != null && !balanceTimerDisposable.isDisposed()) + balanceTimerDisposable.dispose(); balanceTimerDisposable = null; gasService.stopGasPriceCycle(); } @@ -354,11 +380,10 @@ public String getSessionId(String url) public boolean addCustomChain(WalletAddEthereumChainObject chainObject) { String rpc = extractRpc(chainObject); - String blockExplorer = extractBlockExplorer(chainObject); if (rpc == null) return false; - + this.ethereumNetworkRepository.saveCustomRPCNetwork(chainObject.chainName, rpc, chainObject.getChainId(), - chainObject.nativeCurrency.symbol, blockExplorer, "", false, -1L); + chainObject.nativeCurrency.symbol, extractBlockExplorer(chainObject), "", false, -1L); tokensService.createBaseToken(chainObject.getChainId()) .subscribeOn(Schedulers.io()) @@ -416,6 +441,11 @@ public boolean isMainNetsSelected() return ethereumNetworkRepository.isMainNetSelected(); } + public void setMainNetsSelected(boolean isMainNet) + { + ethereumNetworkRepository.setActiveMainnet(isMainNet); + } + public void addNetworkToFilters(NetworkInfo info) { List filters = ethereumNetworkRepository.getFilterNetworkList(); @@ -427,9 +457,4 @@ public void addNetworkToFilters(NetworkInfo info) tokensService.setupFilter(true); } - - public void setMainNetsSelected(boolean isMainNet) - { - ethereumNetworkRepository.setActiveMainnet(isMainNet); - } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/Erc20DetailViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/Erc20DetailViewModel.java index 23c03216bf..1a7fe54bd7 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/Erc20DetailViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/Erc20DetailViewModel.java @@ -17,6 +17,7 @@ import com.alphawallet.app.repository.OnRampRepositoryType; import com.alphawallet.app.router.MyAddressRouter; import com.alphawallet.app.router.SendTokenRouter; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.TokensService; import com.alphawallet.token.entity.SigReturnType; @@ -52,13 +53,15 @@ public Erc20DetailViewModel(MyAddressRouter myAddressRouter, FetchTransactionsInteract fetchTransactionsInteract, AssetDefinitionService assetDefinitionService, TokensService tokensService, - OnRampRepositoryType onRampRepository) + OnRampRepositoryType onRampRepository, + AnalyticsServiceType analyticsService) { this.myAddressRouter = myAddressRouter; this.fetchTransactionsInteract = fetchTransactionsInteract; this.assetDefinitionService = assetDefinitionService; this.tokensService = tokensService; this.onRampRepository = onRampRepository; + setAnalyticsService(analyticsService); } public LiveData sig() diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java index aa9e56c8c1..6ff2e07eff 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/HomeViewModel.java @@ -115,7 +115,6 @@ public class HomeViewModel extends BaseViewModel { private final EthereumNetworkRepositoryType ethereumNetworkRepository; private final TransactionsService transactionsService; private final MyAddressRouter myAddressRouter; - private final AnalyticsServiceType analyticsService; private final ExternalBrowserRouter externalBrowserRouter; private final OkHttpClient httpClient; private final RealmManager realmManager; @@ -154,12 +153,10 @@ public class HomeViewModel extends BaseViewModel { this.ethereumNetworkRepository = ethereumNetworkRepository; this.myAddressRouter = myAddressRouter; this.transactionsService = transactionsService; - this.analyticsService = analyticsService; this.externalBrowserRouter = externalBrowserRouter; this.httpClient = httpClient; this.realmManager = realmManager; - - + setAnalyticsService(analyticsService); this.preferenceRepository.incrementLaunchCount(); } @@ -461,16 +458,9 @@ public void identify() uuid = UUID.randomUUID().toString(); } - analyticsService.identify(uuid); preferenceRepository.setUniqueId(uuid); - } - - public void actionSheetConfirm(String mode) - { - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData(mode); - analyticsService.track(C.AN_CALL_ACTIONSHEET, analyticsProperties); + identify(uuid); } public void checkTransactionEngine() diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/ImportWalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/ImportWalletViewModel.java index fdb8e15623..37d10734e6 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/ImportWalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/ImportWalletViewModel.java @@ -4,13 +4,14 @@ import android.app.Activity; +import androidx.core.util.Pair; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import com.alphawallet.app.C; -import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.ImportWalletCallback; +import com.alphawallet.app.entity.analytics.ImportWalletType; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.interact.ImportWalletInteract; @@ -40,24 +41,23 @@ public class ImportWalletViewModel extends BaseViewModel implements OnSetWatchWa private final ImportWalletInteract importWalletInteract; private final KeyService keyService; private final AWEnsResolver ensResolver; - private final AnalyticsServiceType analyticsService; - private final MutableLiveData wallet = new MutableLiveData<>(); + private final MutableLiveData> wallet = new MutableLiveData<>(); private final MutableLiveData badSeed = new MutableLiveData<>(); private final MutableLiveData watchExists = new MutableLiveData<>(); - private String importWalletType = ""; @Inject ImportWalletViewModel(ImportWalletInteract importWalletInteract, KeyService keyService, - AnalyticsServiceType analyticsService) { + AnalyticsServiceType analyticsService) + { this.importWalletInteract = importWalletInteract; this.keyService = keyService; this.ensResolver = new AWEnsResolver(TokenRepository.getWeb3jService(MAINNET_ID), keyService.getContext()); - this.analyticsService = analyticsService; + setAnalyticsService(analyticsService); } - public void onKeystore(String keystore, String password, String newPassword, KeyService.AuthenticationLevel level) { - importWalletType = C.AN_KEYSTORE; + public void onKeystore(String keystore, String password, String newPassword, KeyService.AuthenticationLevel level) + { progress.postValue(true); importWalletInteract @@ -65,18 +65,37 @@ public void onKeystore(String keystore, String password, String newPassword, Key .flatMap(wallet -> importWalletInteract.storeKeystoreWallet(wallet, level, ensResolver)) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onWallet, this::onError).isDisposed(); + .subscribe(w -> onWallet(w, ImportWalletType.KEYSTORE), this::onError).isDisposed(); } - public void onPrivateKey(String privateKey, String newPassword, KeyService.AuthenticationLevel level) { - importWalletType = C.AN_PRIVATE_KEY; + public void onPrivateKey(String privateKey, String newPassword, KeyService.AuthenticationLevel level) + { progress.postValue(true); importWalletInteract .importPrivateKey(privateKey, newPassword) .flatMap(wallet -> importWalletInteract.storeKeystoreWallet(wallet, level, ensResolver)) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onWallet, this::onError).isDisposed(); + .subscribe(w -> onWallet(w, ImportWalletType.PRIVATE_KEY), this::onError).isDisposed(); + } + + public void onSeed(String walletAddress, KeyService.AuthenticationLevel level) + { + if (walletAddress == null) + { + Timber.e("walletAddress is null"); + progress.postValue(false); + badSeed.postValue(true); + } + else + { + progress.postValue(true); + //begin key storage process + disposable = importWalletInteract.storeHDWallet(walletAddress, level, ensResolver) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(w -> onWallet(w, ImportWalletType.SEED_PHRASE), this::onError); //signal to UI wallet import complete + } } @Override @@ -94,43 +113,33 @@ public void onWatchWallet(String address) disposable = importWalletInteract.storeWatchWallet(address, ensResolver) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(wallet::postValue, this::onError); //signal to UI wallet import complete + .subscribe(w -> onWallet(w, ImportWalletType.WATCH), this::onError); //signal to UI wallet import complete } - public LiveData wallet() { + public LiveData> wallet() + { return wallet; } - public LiveData badSeed() { return badSeed; } - public LiveData watchExists() { return watchExists; } - private void onWallet(Wallet wallet) { - progress.postValue(false); - this.wallet.postValue(wallet); - track(); + public LiveData badSeed() + { + return badSeed; } - public void onError(Throwable throwable) { - error.postValue(new ErrorEnvelope(C.ErrorCode.UNKNOWN, throwable.getMessage())); + public LiveData watchExists() + { + return watchExists; } - public void onSeed(String walletAddress, KeyService.AuthenticationLevel level) + private void onWallet(Wallet wallet, ImportWalletType type) { - importWalletType = C.AN_SEED_PHRASE; - if (walletAddress == null) - { - progress.postValue(false); - Timber.e("ERROR"); - badSeed.postValue(true); - } - else - { - progress.postValue(true); - //begin key storage process - disposable = importWalletInteract.storeHDWallet(walletAddress, level, ensResolver) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onWallet, this::onError); //signal to UI wallet import complete - } + progress.postValue(false); + this.wallet.postValue(new Pair<>(wallet, type)); + } + + public void onError(Throwable throwable) + { + error.postValue(new ErrorEnvelope(C.ErrorCode.UNKNOWN, throwable.getMessage())); } // public void getAuthorisation(String walletAddress, Activity activity, SignAuthenticationCallback callback) @@ -185,12 +194,4 @@ public void failedAuthentication(Operation taskCode) { keyService.failedAuthentication(taskCode); } - - public void track() - { - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setWalletType(importWalletType); - - analyticsService.track(C.AN_IMPORT_WALLET, analyticsProperties); - } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/MyDappsViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/MyDappsViewModel.java new file mode 100644 index 0000000000..e51edea345 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/MyDappsViewModel.java @@ -0,0 +1,17 @@ +package com.alphawallet.app.viewmodel; + +import com.alphawallet.app.service.AnalyticsServiceType; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; + +@HiltViewModel +public class MyDappsViewModel extends BaseViewModel +{ + @Inject + MyDappsViewModel(AnalyticsServiceType analyticsService) + { + setAnalyticsService(analyticsService); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java index e626daf0d4..0888d9857c 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/NameThisWalletViewModel.java @@ -13,6 +13,7 @@ import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.repository.TokenRepository; import com.alphawallet.app.repository.WalletItem; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.util.ens.EnsResolver; @@ -39,13 +40,16 @@ public class NameThisWalletViewModel extends BaseViewModel Disposable ensResolveDisposable; @Inject - NameThisWalletViewModel(GenericWalletInteract genericWalletInteract, @ApplicationContext Context context) + NameThisWalletViewModel( + GenericWalletInteract genericWalletInteract, + @ApplicationContext Context context, + AnalyticsServiceType analyticsService) { this.genericWalletInteract = genericWalletInteract; this.ensResolver = new AWEnsResolver(TokenRepository.getWeb3jService(MAINNET_ID), context); + setAnalyticsService(analyticsService); } - @Override protected void onCleared() { diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/NewSettingsViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/NewSettingsViewModel.java index 2f4a6ec723..b9573d16d7 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/NewSettingsViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/NewSettingsViewModel.java @@ -17,6 +17,7 @@ import com.alphawallet.app.router.ManageWalletsRouter; import com.alphawallet.app.router.MyAddressRouter; import com.alphawallet.app.service.TickerService; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.TransactionsService; import com.alphawallet.app.util.LocaleUtils; @@ -52,7 +53,8 @@ public class NewSettingsViewModel extends BaseViewModel LocaleRepositoryType localeRepository, CurrencyRepositoryType currencyRepository, TransactionsService transactionsService, - TickerService tickerService) + TickerService tickerService, + AnalyticsServiceType analyticsService) { this.genericWalletInteract = genericWalletInteract; this.myAddressRouter = myAddressRouter; @@ -62,6 +64,7 @@ public class NewSettingsViewModel extends BaseViewModel this.currencyRepository = currencyRepository; this.transactionsService = transactionsService; this.tickerService = tickerService; + setAnalyticsService(analyticsService); } public ArrayList getLocaleList(Context context) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/QrScannerViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/QrScannerViewModel.java new file mode 100644 index 0000000000..0da67f75eb --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/QrScannerViewModel.java @@ -0,0 +1,18 @@ +package com.alphawallet.app.viewmodel; + +import com.alphawallet.app.service.AnalyticsServiceType; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; + +@HiltViewModel +public class QrScannerViewModel extends BaseViewModel +{ + + @Inject + public QrScannerViewModel(AnalyticsServiceType analyticsService) + { + setAnalyticsService(analyticsService); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SelectNetworkFilterViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SelectNetworkFilterViewModel.java index 2723515ce3..5102deb130 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SelectNetworkFilterViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SelectNetworkFilterViewModel.java @@ -5,6 +5,7 @@ import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; import com.alphawallet.app.repository.PreferenceRepositoryType; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.TokensService; import com.alphawallet.app.ui.widget.entity.NetworkItem; @@ -24,10 +25,12 @@ public class SelectNetworkFilterViewModel extends BaseViewModel { @Inject public SelectNetworkFilterViewModel(EthereumNetworkRepositoryType ethereumNetworkRepositoryType, TokensService tokensService, - PreferenceRepositoryType preferenceRepository) { + PreferenceRepositoryType preferenceRepository, + AnalyticsServiceType analyticsService) { this.networkRepository = ethereumNetworkRepositoryType; this.tokensService = tokensService; this.preferenceRepository = preferenceRepository; + setAnalyticsService(analyticsService); } public NetworkInfo[] getNetworkList() { diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java index f5bafdb5dc..174e31a57b 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SendViewModel.java @@ -52,7 +52,6 @@ public class SendViewModel extends BaseViewModel { private final AssetDefinitionService assetDefinitionService; private final KeyService keyService; private final CreateTransactionInteract createTransactionInteract; - private final AnalyticsServiceType analyticsService; @Inject public SendViewModel(MyAddressRouter myAddressRouter, @@ -73,7 +72,7 @@ public SendViewModel(MyAddressRouter myAddressRouter, this.assetDefinitionService = assetDefinitionService; this.keyService = keyService; this.createTransactionInteract = createTransactionInteract; - this.analyticsService = analyticsService; + setAnalyticsService(analyticsService); } public MutableLiveData transactionFinalised() @@ -170,12 +169,4 @@ public void sendTransaction(Web3Transaction finalTx, Wallet wallet, long chainId .subscribe(transactionFinalised::postValue, transactionError::postValue); } - - public void actionSheetConfirm(String mode) - { - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData(mode); - - analyticsService.track(C.AN_CALL_ACTIONSHEET, analyticsProperties); - } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java index 5bb14189f2..d3cd360f48 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SplashViewModel.java @@ -8,7 +8,6 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; import com.alphawallet.app.entity.CreateWalletCallbackInterface; import com.alphawallet.app.entity.Operation; @@ -16,6 +15,7 @@ import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.interact.FetchWalletsInteract; import com.alphawallet.app.repository.PreferenceRepositoryType; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.KeyService; import java.io.File; @@ -28,7 +28,7 @@ import io.reactivex.schedulers.Schedulers; @HiltViewModel -public class SplashViewModel extends ViewModel +public class SplashViewModel extends BaseViewModel { private static final String LEGACY_CERTIFICATE_DB = "CERTIFICATE_CACHE-db.realm"; private static final String LEGACY_AUX_DB_PREFIX = "AuxData-"; @@ -43,11 +43,13 @@ public class SplashViewModel extends ViewModel @Inject SplashViewModel(FetchWalletsInteract fetchWalletsInteract, PreferenceRepositoryType preferenceRepository, - KeyService keyService) { + KeyService keyService, + AnalyticsServiceType analyticsService) + { this.fetchWalletsInteract = fetchWalletsInteract; this.preferenceRepository = preferenceRepository; this.keyService = keyService; - + setAnalyticsService(analyticsService); // increase launch count // this.preferenceRepository.incrementLaunchCount(); } @@ -61,14 +63,19 @@ public void fetchWallets() } //on wallet error ensure execution still continues and splash screen terminates - private void onError(Throwable throwable) { + @Override + protected void onError(Throwable throwable) + { wallets.postValue(new Wallet[0]); } - public LiveData wallets() { + public LiveData wallets() + { return wallets; } - public LiveData createWallet() { + + public LiveData createWallet() + { return createWallet; } @@ -89,7 +96,10 @@ public void StoreHDKey(String address, KeyService.AuthenticationLevel authLevel) wallet.type = WalletType.HDKEY; wallet.authLevel = authLevel; fetchWalletsInteract.storeWallet(wallet) - .map(w -> { preferenceRepository.setCurrentWalletAddress(w.address); return w; }) + .map(w -> { + preferenceRepository.setCurrentWalletAddress(w.address); + return w; + }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(newWallet -> wallets.postValue(new Wallet[]{newWallet}), this::onError).isDisposed(); @@ -152,11 +162,13 @@ public void setDefaultBrowser() preferenceRepository.setActiveBrowserNetwork(MAINNET_ID); } - public long getInstallTime() { + public long getInstallTime() + { return preferenceRepository.getInstallTime(); } - public void setInstallTime(long time) { + public void setInstallTime(long time) + { preferenceRepository.setInstallTime(time); } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SupportSettingsViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SupportSettingsViewModel.java new file mode 100644 index 0000000000..160385ddc1 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SupportSettingsViewModel.java @@ -0,0 +1,17 @@ +package com.alphawallet.app.viewmodel; + +import com.alphawallet.app.service.AnalyticsServiceType; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; + +@HiltViewModel +public class SupportSettingsViewModel extends BaseViewModel +{ + @Inject + SupportSettingsViewModel(AnalyticsServiceType analyticsService) + { + setAnalyticsService(analyticsService); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java index d3c2a55b4e..adf2f00e32 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SwapViewModel.java @@ -21,6 +21,7 @@ import com.alphawallet.app.interact.CreateTransactionInteract; import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.repository.SwapRepositoryType; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.KeyService; import com.alphawallet.app.service.SwapService; @@ -87,7 +88,8 @@ public SwapViewModel( TokensService tokensService, SwapService swapService, CreateTransactionInteract createTransactionInteract, - KeyService keyService) + KeyService keyService, + AnalyticsServiceType analyticsService) { this.assetDefinitionService = assetDefinitionService; this.preferenceRepository = preferenceRepository; @@ -96,6 +98,7 @@ public SwapViewModel( this.swapService = swapService; this.createTransactionInteract = createTransactionInteract; this.keyService = keyService; + setAnalyticsService(analyticsService); } public AssetDefinitionService getAssetDefinitionService() 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 2bcbc4ea20..0f64665473 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java @@ -13,6 +13,7 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; +import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.DAppFunction; import com.alphawallet.app.entity.Operation; @@ -90,7 +91,8 @@ * Stormbird in Singapore */ @HiltViewModel -public class TokenFunctionViewModel extends BaseViewModel { +public class TokenFunctionViewModel extends BaseViewModel +{ private final AssetDefinitionService assetDefinitionService; private final CreateTransactionInteract createTransactionInteract; private final GasService gasService; @@ -100,7 +102,6 @@ public class TokenFunctionViewModel extends BaseViewModel { private final GenericWalletInteract genericWalletInteract; private final OpenSeaService openseaService; private final FetchTransactionsInteract fetchTransactionsInteract; - private final AnalyticsServiceType analyticsService; private final MutableLiveData insufficientFunds = new MutableLiveData<>(); private final MutableLiveData invalidAddress = new MutableLiveData<>(); private final MutableLiveData sig = new MutableLiveData<>(); @@ -151,7 +152,7 @@ public class TokenFunctionViewModel extends BaseViewModel { this.genericWalletInteract = genericWalletInteract; this.openseaService = openseaService; this.fetchTransactionsInteract = fetchTransactionsInteract; - this.analyticsService = analyticsService; + setAnalyticsService(analyticsService); } public AssetDefinitionService getAssetDefinitionService() @@ -184,7 +185,10 @@ public LiveData newScriptFound() return newScriptFound; } - public LiveData scriptUpdateInProgress() { return scriptUpdateInProgress; } + public LiveData scriptUpdateInProgress() + { + return scriptUpdateInProgress; + } public MutableLiveData transactionFinalised() { @@ -709,10 +713,9 @@ public void sendTransaction(Web3Transaction finalTx, long chainId, String overri public void actionSheetConfirm(String mode) { - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData(mode); - - analyticsService.track(C.AN_CALL_ACTIONSHEET, analyticsProperties); + AnalyticsProperties props = new AnalyticsProperties(); + props.put(Analytics.PROPS_ACTION_SHEET_MODE, mode); + track(Analytics.Action.ACTION_SHEET_COMPLETED, props); } public Single showTransferSelectCount(Context ctx, Token token, BigInteger tokenId) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/TransactionDetailViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/TransactionDetailViewModel.java index 8e27b14b8d..9e4f43cba7 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/TransactionDetailViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/TransactionDetailViewModel.java @@ -66,7 +66,6 @@ public class TransactionDetailViewModel extends BaseViewModel { private final KeyService keyService; private final TokensService tokenService; private final GasService gasService; - private final AnalyticsServiceType analyticsService; private final MutableLiveData latestBlock = new MutableLiveData<>(); private final MutableLiveData latestTx = new MutableLiveData<>(); @@ -107,7 +106,7 @@ public LiveData latestBlock() { this.keyService = keyService; this.gasService = gasService; this.createTransactionInteract = createTransactionInteract; - this.analyticsService = analyticsService; + setAnalyticsService(analyticsService); } public MutableLiveData transactionFinalised() @@ -303,12 +302,4 @@ public void sendTransaction(Web3Transaction finalTx, Wallet wallet, long chainId .subscribe(transactionFinalised::postValue, transactionError::postValue); } - - public void actionSheetConfirm(String mode) - { - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData(mode); - - analyticsService.track(C.AN_CALL_ACTIONSHEET, analyticsProperties); - } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java index 0e8f662119..9246b608a0 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java @@ -9,11 +9,9 @@ import androidx.lifecycle.MutableLiveData; import com.alphawallet.app.C; -import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ContractType; import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.DisplayState; -import com.alphawallet.app.entity.GasSettings; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.TransactionData; @@ -38,8 +36,6 @@ import com.alphawallet.token.entity.SignableBytes; import com.alphawallet.token.tools.ParseMagicLink; -import org.web3j.protocol.core.methods.response.EthEstimateGas; - import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; @@ -56,7 +52,8 @@ * Created by James on 21/02/2018. */ @HiltViewModel -public class TransferTicketDetailViewModel extends BaseViewModel { +public class TransferTicketDetailViewModel extends BaseViewModel +{ private final MutableLiveData defaultWallet = new MutableLiveData<>(); private final MutableLiveData newTransaction = new MutableLiveData<>(); private final MutableLiveData universalLinkReady = new MutableLiveData<>(); @@ -69,7 +66,6 @@ public class TransferTicketDetailViewModel extends BaseViewModel { private final FetchTransactionsInteract fetchTransactionsInteract; private final AssetDefinitionService assetDefinitionService; private final GasService gasService; - private final AnalyticsServiceType analyticsService; private final TokensService tokensService; private ParseMagicLink parser; @@ -85,29 +81,43 @@ public class TransferTicketDetailViewModel extends BaseViewModel { AssetDefinitionService assetDefinitionService, GasService gasService, AnalyticsServiceType analyticsService, - TokensService tokensService) { + TokensService tokensService) + { this.genericWalletInteract = genericWalletInteract; this.keyService = keyService; this.createTransactionInteract = createTransactionInteract; this.fetchTransactionsInteract = fetchTransactionsInteract; this.assetDefinitionService = assetDefinitionService; this.gasService = gasService; - this.analyticsService = analyticsService; this.tokensService = tokensService; + setAnalyticsService(analyticsService); } public MutableLiveData transactionFinalised() { return transactionFinalised; } - public MutableLiveData transactionError() { return transactionError; } + + public MutableLiveData transactionError() + { + return transactionError; + } public LiveData defaultWallet() { return defaultWallet; } - public LiveData newTransaction() { return newTransaction; } - public LiveData universalLinkReady() { return universalLinkReady; } + + public LiveData newTransaction() + { + return newTransaction; + } + + public LiveData universalLinkReady() + { + return universalLinkReady; + } + private void initParser() { if (parser == null) @@ -126,13 +136,14 @@ public void prepare(Token token) gasService.startGasPriceCycle(token.tokenInfo.chainId); } - private void onDefaultWallet(Wallet wallet) { + private void onDefaultWallet(Wallet wallet) + { defaultWallet.setValue(wallet); } public Wallet getWallet() { - return defaultWallet.getValue(); + return defaultWallet.getValue(); } public void setWallet(Wallet wallet) @@ -210,7 +221,7 @@ public void createTokenTransfer(String to, Token token, List transfe { final byte[] data = TokenRepository.createTicketTransferData(to, transferList, token); disposable = createTransactionInteract.create(defaultWallet.getValue(), token.getAddress(), - BigInteger.ZERO, gasService.getGasPrice(), new BigInteger(C.DEFAULT_GAS_LIMIT_FOR_NONFUNGIBLE_TOKENS), data, token.tokenInfo.chainId) + BigInteger.ZERO, gasService.getGasPrice(), new BigInteger(C.DEFAULT_GAS_LIMIT_FOR_NONFUNGIBLE_TOKENS), data, token.tokenInfo.chainId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(newTransaction::postValue, this::onError); @@ -289,21 +300,15 @@ public void sendTransaction(Web3Transaction finalTx, Wallet wallet, long chainId transactionError::postValue); } - public byte[] getERC721TransferBytes(String to, String contractAddress, String tokenId, long chainId) { + public byte[] getERC721TransferBytes(String to, String contractAddress, String tokenId, long chainId) + { Token token = tokensService.getToken(chainId, contractAddress); List tokenIds = token.stringHexToBigIntegerList(tokenId); return TokenRepository.createERC721TransferFunction(to, token, tokenIds); } - public void actionSheetConfirm(String mode) + public TokensService getTokenService() { - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData(mode); - - analyticsService.track(C.AN_CALL_ACTIONSHEET, analyticsProperties); - } - - public TokensService getTokenService() { return tokensService; } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java index 89a4d7c82e..1ecd7c99ca 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java @@ -81,7 +81,6 @@ public class WalletConnectViewModel extends BaseViewModel private final RealmManager realmManager; private final GasService gasService; private final TokensService tokensService; - private final AnalyticsServiceType analyticsService; private final EthereumNetworkRepositoryType ethereumNetworkRepository; private final HashMap clientBuffer = new HashMap<>(); @@ -111,8 +110,8 @@ public class WalletConnectViewModel extends BaseViewModel this.realmManager = realmManager; this.gasService = gasService; this.tokensService = tokensService; - this.analyticsService = analyticsService; this.ethereumNetworkRepository = ethereumNetworkRepository; + setAnalyticsService(analyticsService); prepareDisposable = null; disposable = genericWalletInteract .find() @@ -611,14 +610,6 @@ public String getNetworkSymbol(long chainId) return info.symbol; } - public void actionSheetConfirm(String mode) - { - AnalyticsProperties analyticsProperties = new AnalyticsProperties(); - analyticsProperties.setData("(WC)" + mode); //disambiguate signs/sends etc through WC - - analyticsService.track(C.AN_CALL_ACTIONSHEET, analyticsProperties); - } - public void prepareIfRequired() { if (prepareDisposable == null) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java index 848e236d89..4a81a7f24c 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java @@ -1,7 +1,6 @@ package com.alphawallet.app.viewmodel; import static com.alphawallet.app.C.EXTRA_ADDRESS; -import static com.alphawallet.app.repository.TokensRealmSource.databaseKey; import static com.alphawallet.app.widget.CopyTextView.KEY_ADDRESS; import android.app.Activity; @@ -22,6 +21,7 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletType; +import com.alphawallet.app.entity.analytics.QrScanSource; import com.alphawallet.app.entity.tokendata.TokenGroup; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; @@ -36,11 +36,12 @@ import com.alphawallet.app.router.ManageWalletsRouter; import com.alphawallet.app.router.MyAddressRouter; import com.alphawallet.app.router.TokenDetailRouter; +import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.RealmManager; import com.alphawallet.app.service.TokensService; import com.alphawallet.app.ui.NameThisWalletActivity; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.TokenManagementActivity; import com.alphawallet.app.widget.WalletFragmentActionsView; import com.google.android.material.bottomsheet.BottomSheetBehavior; @@ -50,7 +51,6 @@ import org.web3j.crypto.Keys; import java.math.BigDecimal; -import java.util.ArrayList; import javax.inject.Inject; @@ -81,9 +81,9 @@ public class WalletViewModel extends BaseViewModel private final CoinbasePayRouter coinbasePayRouter; private final ManageWalletsRouter manageWalletsRouter; private final RealmManager realmManager; + private final OnRampRepositoryType onRampRepository; private long lastBackupCheck = 0; private BottomSheetDialog dialog; - private final OnRampRepositoryType onRampRepository; @Inject WalletViewModel( @@ -98,7 +98,8 @@ public class WalletViewModel extends BaseViewModel ManageWalletsRouter manageWalletsRouter, PreferenceRepositoryType preferenceRepository, RealmManager realmManager, - OnRampRepositoryType onRampRepository) + OnRampRepositoryType onRampRepository, + AnalyticsServiceType analyticsService) { this.fetchTokensInteract = fetchTokensInteract; this.tokenDetailRouter = tokenDetailRouter; @@ -112,21 +113,42 @@ public class WalletViewModel extends BaseViewModel this.preferenceRepository = preferenceRepository; this.realmManager = realmManager; this.onRampRepository = onRampRepository; + setAnalyticsService(analyticsService); } - public LiveData tokens() { + public LiveData tokens() + { return tokens; } - public LiveData defaultWallet() { return defaultWallet; } - public LiveData backupEvent() { return backupEvent; } - public LiveData> onFiatValues() { return fiatValues; } - public String getWalletAddr() { return defaultWallet.getValue() != null ? defaultWallet.getValue().address : ""; } - public WalletType getWalletType() { return defaultWallet.getValue() != null ? defaultWallet.getValue().type : WalletType.KEYSTORE; } + public LiveData defaultWallet() + { + return defaultWallet; + } + + public LiveData backupEvent() + { + return backupEvent; + } + + public LiveData> onFiatValues() + { + return fiatValues; + } + + public String getWalletAddr() + { + return defaultWallet.getValue() != null ? defaultWallet.getValue().address : ""; + } + + public WalletType getWalletType() + { + return defaultWallet.getValue() != null ? defaultWallet.getValue().type : WalletType.KEYSTORE; + } public void prepare() { - lastBackupCheck = System.currentTimeMillis() - BALANCE_BACKUP_CHECK_INTERVAL + 5*DateUtils.SECOND_IN_MILLIS; + lastBackupCheck = System.currentTimeMillis() - BALANCE_BACKUP_CHECK_INTERVAL + 5 * DateUtils.SECOND_IN_MILLIS; //load the activity meta list disposable = genericWalletInteract .find() @@ -216,7 +238,8 @@ public void setKeyWarningDismissTime(String walletAddr) genericWalletInteract.updateWarningTime(walletAddr); } - public void setTokenEnabled(Token token, boolean enabled) { + public void setTokenEnabled(Token token, boolean enabled) + { changeTokenEnableInteract.setEnable(defaultWallet.getValue(), token, enabled); token.tokenInfo.isEnabled = enabled; } @@ -234,7 +257,8 @@ public void showMyAddress(Context context) dialog.dismiss(); ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText(KEY_ADDRESS, Keys.toChecksumAddress(getWalletAddr())); - if (clipboard != null) { + if (clipboard != null) + { clipboard.setPrimaryClip(clip); } @@ -265,9 +289,11 @@ public void showMyAddress(Context context) dialog.show(); } - public void showQRCodeScanning(Activity activity) { - Intent intent = new Intent(activity, QRScanner.class); + public void showQRCodeScanning(Activity activity) + { + Intent intent = new Intent(activity, QRScannerActivity.class); intent.putExtra(C.EXTRA_UNIVERSAL_SCAN, true); + intent.putExtra(QrScanSource.KEY, QrScanSource.WALLET_SCREEN.getValue()); activity.startActivityForResult(intent, C.REQUEST_UNIVERSAL_SCAN); } @@ -321,7 +347,8 @@ public void showTokenDetail(Activity activity, Token token) public void checkBackup(double fiatValue) { - if (TextUtils.isEmpty(getWalletAddr()) || System.currentTimeMillis() < (lastBackupCheck + BALANCE_BACKUP_CHECK_INTERVAL)) return; + if (TextUtils.isEmpty(getWalletAddr()) || System.currentTimeMillis() < (lastBackupCheck + BALANCE_BACKUP_CHECK_INTERVAL)) + return; lastBackupCheck = System.currentTimeMillis(); double walletUSDValue = tokensService.convertToUSD(fiatValue); @@ -381,20 +408,23 @@ public void showManageWallets(Context context, boolean clearStack) manageWalletsRouter.open(context, clearStack); } - public boolean isMarshMallowWarningShown() { + public boolean isMarshMallowWarningShown() + { return preferenceRepository.isMarshMallowWarningShown(); } - public void setMarshMallowWarning(boolean shown) { + public void setMarshMallowWarning(boolean shown) + { preferenceRepository.setMarshMallowWarning(shown); } public void saveAvatar(Wallet wallet) { - genericWalletInteract.updateWalletItem(wallet, WalletItem.ENS_AVATAR, () -> { }); + genericWalletInteract.updateWalletItem(wallet, WalletItem.ENS_AVATAR, () -> {}); } - public Intent getBuyIntent(String address) { + public Intent getBuyIntent(String address) + { Intent intent = new Intent(); intent.putExtra(C.DAPP_URL_LOAD, onRampRepository.getUri(address, null)); return intent; diff --git a/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java b/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java index 68a046275b..c65b9cb328 100644 --- a/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java +++ b/app/src/main/java/com/alphawallet/app/web3/entity/Web3Transaction.java @@ -12,7 +12,7 @@ import com.alphawallet.app.util.Hex; import com.alphawallet.app.util.StyledStringBuilder; import com.alphawallet.app.walletconnect.entity.WCEthereumTransaction; -import com.alphawallet.app.widget.ActionSheetMode; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.token.entity.MagicLinkInfo; import org.web3j.protocol.core.methods.request.Transaction; diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java index d6a950eeaf..2f7e8726a3 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java @@ -23,6 +23,7 @@ import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.TXSpeed; import com.alphawallet.app.entity.Transaction; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.app.entity.nftassets.NFTAsset; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.SharedPreferenceRepository; @@ -515,8 +516,6 @@ public void handleClick(String action, int id) } break; } - - actionSheetCallback.notifyConfirm(mode.toString()); } private BigDecimal getTransactionAmount() @@ -563,6 +562,7 @@ public void gotAuthorisation(boolean gotAuth) { confirmationWidget.startProgressCycle(1); signCallback.gotAuthorisationForSigning(gotAuth, signWidget.getSignable()); + actionSheetCallback.notifyConfirm(mode.getValue()); } else { @@ -691,6 +691,7 @@ public void gotAuthorisation(boolean gotAuth) confirmationWidget.startProgressCycle(4); //send the transaction actionSheetCallback.signTransaction(formTransaction()); + actionSheetCallback.notifyConfirm(mode.getValue()); } @Override @@ -785,6 +786,7 @@ public void gotAuthorisation(boolean gotAuth) confirmationWidget.startProgressCycle(4); //send the transaction actionSheetCallback.sendTransaction(formTransaction()); + actionSheetCallback.notifyConfirm(mode.getValue()); } @Override diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheetMode.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheetMode.java deleted file mode 100644 index 75403efff8..0000000000 --- a/app/src/main/java/com/alphawallet/app/widget/ActionSheetMode.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.alphawallet.app.widget; - -/** - * Created by JB on 12/01/2021. - */ -public enum ActionSheetMode -{ - SEND_TRANSACTION, - SEND_TRANSACTION_DAPP, - SEND_TRANSACTION_WC, - SIGN_MESSAGE, - SIGN_TRANSACTION, - SPEEDUP_TRANSACTION, - CANCEL_TRANSACTION, - MESSAGE, - WALLET_CONNECT_REQUEST, - NODE_STATUS_INFO -} diff --git a/app/src/main/java/com/alphawallet/app/widget/GasWidget.java b/app/src/main/java/com/alphawallet/app/widget/GasWidget.java index 49cd808292..90ef428494 100644 --- a/app/src/main/java/com/alphawallet/app/widget/GasWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/GasWidget.java @@ -19,6 +19,7 @@ import com.alphawallet.app.entity.GasPriceSpread; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.TXSpeed; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.TokensRealmSource; import com.alphawallet.app.repository.entity.RealmGasSpread; diff --git a/app/src/main/java/com/alphawallet/app/widget/GasWidget2.java b/app/src/main/java/com/alphawallet/app/widget/GasWidget2.java index fc8329e408..372395621f 100644 --- a/app/src/main/java/com/alphawallet/app/widget/GasWidget2.java +++ b/app/src/main/java/com/alphawallet/app/widget/GasWidget2.java @@ -18,6 +18,7 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.GasPriceSpread; import com.alphawallet.app.entity.TXSpeed; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.TokensRealmSource; import com.alphawallet.app.repository.entity.Realm1559Gas; diff --git a/app/src/main/java/com/alphawallet/app/widget/InputAddress.java b/app/src/main/java/com/alphawallet/app/widget/InputAddress.java index fd66ad3393..41299d4021 100644 --- a/app/src/main/java/com/alphawallet/app/widget/InputAddress.java +++ b/app/src/main/java/com/alphawallet/app/widget/InputAddress.java @@ -25,7 +25,8 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.ENSCallback; import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.entity.analytics.QrScanSource; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.adapter.AutoCompleteAddressAdapter; import com.alphawallet.app.ui.widget.entity.AddressReadyCallback; import com.alphawallet.app.ui.widget.entity.BoxStatus; @@ -189,7 +190,8 @@ private void setViews() { //QR Scanner scanQrIcon.setOnClickListener(v -> { - Intent intent = new Intent(context, QRScanner.class); + Intent intent = new Intent(context, QRScannerActivity.class); + intent.putExtra(QrScanSource.KEY, QrScanSource.ADDRESS_TEXT_FIELD.getValue()); intent.putExtra(C.EXTRA_CHAIN_ID, chainOverride); ((Activity) context).startActivityForResult(intent, C.BARCODE_READER_REQUEST_CODE); }); diff --git a/app/src/main/java/com/alphawallet/app/widget/InputView.java b/app/src/main/java/com/alphawallet/app/widget/InputView.java index 7ed64226fc..23c4d098e7 100644 --- a/app/src/main/java/com/alphawallet/app/widget/InputView.java +++ b/app/src/main/java/com/alphawallet/app/widget/InputView.java @@ -7,7 +7,6 @@ import android.content.res.TypedArray; import android.text.TextUtils; import android.util.AttributeSet; -import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.inputmethod.EditorInfo; @@ -18,7 +17,8 @@ import android.widget.TextView; import com.alphawallet.app.C; -import com.alphawallet.app.ui.QRScanning.QRScanner; +import com.alphawallet.app.entity.analytics.QrScanSource; +import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.entity.BoxStatus; import com.alphawallet.app.util.Utils; @@ -113,7 +113,8 @@ private void getAttrs(Context context, AttributeSet attrs) { if (!noCam) { scanQrIcon.setOnClickListener(v -> { - Intent intent = new Intent(context, QRScanner.class); + Intent intent = new Intent(context, QRScannerActivity.class); + intent.putExtra(QrScanSource.KEY, QrScanSource.ADDRESS_TEXT_FIELD.getValue()); ((Activity) context).startActivityForResult(intent, C.BARCODE_READER_REQUEST_CODE); }); } diff --git a/app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerTest.java b/app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerActivityTest.java similarity index 86% rename from app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerTest.java rename to app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerActivityTest.java index 29cf9973b6..7d62e9db35 100644 --- a/app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerTest.java +++ b/app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerActivityTest.java @@ -16,14 +16,14 @@ @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowRealm.class}) -public class QRScannerTest +public class QRScannerActivityTest { @Test @Config(sdk = 23) public void given_api_23_when_onCreate_then_notify_feature_not_supported() { - try (ActivityScenario scenario = ActivityScenario.launch(QRScanner.class)) + try (ActivityScenario scenario = ActivityScenario.launch(QRScannerActivity.class)) { assertThat(scenario.getState(), equalTo(Lifecycle.State.DESTROYED)); assertThat(ShadowToast.getTextOfLatestToast(), equalTo("QR scanning requires Android 7.0 (API level 24) or above.")); From 5d0008faacf9b3ce570ff38f4f5c1c45de206123 Mon Sep 17 00:00:00 2001 From: James Brown Date: Wed, 2 Nov 2022 19:40:21 +1100 Subject: [PATCH 129/183] Use Phi ticker for both networks (#2900) --- .../java/com/alphawallet/app/service/TickerService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index 152db1d135..831df164c1 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -16,6 +16,7 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; +import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; @@ -434,6 +435,10 @@ private void checkPeggedTickers(long chainId, TokenTicker ticker) ethTickers.put(ARBITRUM_MAIN_ID, ticker); ethTickers.put(OPTIMISTIC_MAIN_ID, ticker); } + else if (chainId == PHI_V2_MAIN_ID) + { + ethTickers.put(PHI_MAIN_ID, ticker); + } } private void addToTokenTickers(BigInteger tickerInfo, long tickerTime) @@ -527,6 +532,7 @@ private int addPhiTickers(int tickerCount) System.currentTimeMillis()); ethTickers.put(PHI_V2_MAIN_ID, phiTicker); + ethTickers.put(PHI_MAIN_ID, phiTicker); return tickerCount + 1; } } From e101b95a9b992ef357c266d14c0d39dd32492d77 Mon Sep 17 00:00:00 2001 From: James Brown Date: Thu, 3 Nov 2022 03:01:15 +1100 Subject: [PATCH 130/183] Fix for NPE encountered (#2899) * Fix for NPE encountered * Update tests --- .../alphawallet/app/web3j/ens/NameHash.java | 62 ++++++++++++------- .../java/com/alphawallet/app/ENSTest.java | 20 +++++- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java b/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java index 6f50e4ce7d..98f41bd8e4 100644 --- a/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java @@ -12,6 +12,9 @@ */ package com.alphawallet.app.web3j.ens; +import org.web3j.crypto.Hash; +import org.web3j.utils.Numeric; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.IDN; @@ -19,31 +22,37 @@ import java.util.Arrays; import java.util.Locale; -import org.web3j.crypto.Hash; -import org.web3j.utils.Numeric; - /** ENS name hash implementation. */ -public class NameHash { - +public class NameHash +{ private static final byte[] EMPTY = new byte[32]; - public static byte[] nameHashAsBytes(String ensName) { + public static byte[] nameHashAsBytes(String ensName) throws EnsResolutionException + { return Numeric.hexStringToByteArray(nameHash(ensName)); } - public static String nameHash(String ensName) { + public static String nameHash(String ensName) throws EnsResolutionException + { String normalisedEnsName = normalise(ensName); return Numeric.toHexString(nameHash(normalisedEnsName.split("\\."))); } - private static byte[] nameHash(String[] labels) { - if (labels.length == 0 || labels[0].equals("")) { + private static byte[] nameHash(String[] labels) + { + if (labels.length == 0 || labels[0].equals("")) + { return EMPTY; - } else { + } + else + { String[] tail; - if (labels.length == 1) { - tail = new String[] {}; - } else { + if (labels.length == 1) + { + tail = new String[]{}; + } + else + { tail = Arrays.copyOfRange(labels, 1, labels.length); } @@ -65,16 +74,22 @@ private static byte[] nameHash(String[] labels) { * @return normalised ens name * @throws EnsResolutionException if the name cannot be normalised */ - public static String normalise(String ensName) { - try { - return IDN.toASCII(ensName, IDN.USE_STD3_ASCII_RULES).toLowerCase(Locale.ROOT); - } catch (IllegalArgumentException e) { + public static String normalise(String ensName) + { + try + { + return IDN.toASCII(ensName, IDN.USE_STD3_ASCII_RULES).toLowerCase(Locale.ROOT); //java.lang.NullPointerException: Attempt to invoke virtual method 'char[] java.lang.String.toCharArray()' on a null object reference + } + catch (Exception e) + { throw new EnsResolutionException("Invalid ENS name provided: " + ensName); } } - public static byte[] toUtf8Bytes(String string) { - if (string == null || string.isEmpty()) { + public static byte[] toUtf8Bytes(String string) + { + if (string == null || string.isEmpty()) + { return null; } return string.getBytes(StandardCharsets.UTF_8); @@ -88,13 +103,16 @@ public static byte[] toUtf8Bytes(String string) { * @return Encoded name in Hex format. * @throws IOException */ - public static String dnsEncode(String name) throws IOException { + public static String dnsEncode(String name) throws IOException + { String[] parts = name.split("\\."); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - for (String part : parts) { + for (String part : parts) + { byte[] bytes = toUtf8Bytes("_" + normalise(part)); - if (bytes == null) { + if (bytes == null) + { break; } bytes[0] = (byte) (bytes.length - 1); diff --git a/app/src/test/java/com/alphawallet/app/ENSTest.java b/app/src/test/java/com/alphawallet/app/ENSTest.java index 4571a6b97f..afd249041e 100644 --- a/app/src/test/java/com/alphawallet/app/ENSTest.java +++ b/app/src/test/java/com/alphawallet/app/ENSTest.java @@ -9,7 +9,9 @@ import com.alphawallet.app.service.AWHttpService; import com.alphawallet.app.util.ens.AWEnsResolver; import com.alphawallet.app.web3j.ens.Contracts; +import com.alphawallet.app.web3j.ens.EnsResolutionException; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.web3j.protocol.Web3j; @@ -101,8 +103,11 @@ public void testReverseResolve() throws Exception { ("vitalik.eth")); } + + @Test - public void testNameHash() { + public void testNameHash() + { assertEquals( nameHash(""), ("0x0000000000000000000000000000000000000000000000000000000000000000")); @@ -115,4 +120,17 @@ public void testNameHash() { nameHash("foo.eth"), ("0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f")); } + + @Test + public void testNPE() + { + Assert.assertThrows(EnsResolutionException.class, + this::nameHashNPE); + } + + private void nameHashNPE() throws EnsResolutionException + { + String test = nameHash(null); + System.out.println("Should have triggered exception"); + } } From 60a99d14b1b00c39431d27d1bf38ce627db8dbf2 Mon Sep 17 00:00:00 2001 From: justindg Date: Wed, 2 Nov 2022 23:34:14 -0700 Subject: [PATCH 131/183] Add Swap UI Test (#2903) * Add Swap UI Test * Include settings --- .../java/com/alphawallet/app/SwapTest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 app/src/androidTest/java/com/alphawallet/app/SwapTest.java diff --git a/app/src/androidTest/java/com/alphawallet/app/SwapTest.java b/app/src/androidTest/java/com/alphawallet/app/SwapTest.java new file mode 100644 index 0000000000..57aff8466c --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/SwapTest.java @@ -0,0 +1,31 @@ +package com.alphawallet.app; + +import static androidx.test.espresso.Espresso.pressBack; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.alphawallet.app.assertions.Should.shouldSee; +import static com.alphawallet.app.steps.Steps.createNewWallet; +import static com.alphawallet.app.util.Helper.click; + +import com.alphawallet.app.util.Helper; + +import org.junit.Test; + +public class SwapTest extends BaseE2ETest +{ + @Test + public void should_see_swap_window() + { + createNewWallet(); + click(withText("0 ETH")); + click(withId(R.id.more_button)); + click(withText("Swap")); + shouldSee("Select Exchanges"); + click(withText("DODO")); + Helper.wait(3); + pressBack(); + Helper.wait(3); + click(withId(R.id.action_settings)); + shouldSee("Settings"); + } +} From fd72641bdba48b384eb0fb591544ecdfa8d5ee44 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Fri, 4 Nov 2022 11:53:42 +0800 Subject: [PATCH 132/183] Prevent TapJacking (#2907) --- app/src/main/res/layout/activity_home.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index 7206a7004f..db9b164d78 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -1,5 +1,6 @@ From d363340f92503738b4b0e7119ff84e760b8a466b Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Mon, 7 Nov 2022 10:47:25 +0800 Subject: [PATCH 133/183] Check code format according to .editorconfig (#2898) * Analytics Update (#2895) * Refactor QrScanner Activity and add tracking * Add tracking for WalletConnect home * Refactor tracking of ActionSheet events (partial) * Add WalletConnect tracking * Add more event identifiers * Update error tracking * Move notifyConfirm() to prevent double tracking * Add more WC error tracking * Track add custom network * Distinguish add or edit custom chain * Add props for tracking * Require error tracking to provide source/feature * Add tracking for support page * Add browser analytics * Add tracking to my dapps * Track buy with ramp * Track browser history screen * Track deep link usage * Track first wallet action * Track name wallet navigation * Fix props * Revert "Fix props" * Make generic errors clearer * test * Check code format with EditorConfigChecker * Update CI * Check more file types * Remove CheckStyle * Check all files * Fix CI syntax error * Fix code style * Set fail-fast to false * Fix merge error * Increase max line length * Run codestyle job only on Ubuntu * Remove final new line * Fix test * Insert final new line * Fix format * Fix e2e test Co-authored-by: justindg --- .editorconfig | 4 +- .github/workflows/checkstyle.yml | 29 - .github/workflows/codestyle.yml | 27 + .github/workflows/lint-pr.yml | 5 +- .github/workflows/lint.yml | 2 +- .gitignore | 3 +- .husky/pre-commit | 4 + .../java/com/alphawallet/app/steps/Steps.java | 2 +- .../main/java/com/alphawallet/app/App.java | 3 +- .../app/service/TickerService.java | 85 +- .../app/di/EthereumNetworkBaseTest.java | 2 +- build.gradle | 4 - build.sh | 8 +- checkstyle.xml | 341 --- codestyle.gradle | 90 - package-lock.json | 2139 ++++++++++++++++- package.json | 15 +- 17 files changed, 2256 insertions(+), 507 deletions(-) delete mode 100644 .github/workflows/checkstyle.yml create mode 100644 .github/workflows/codestyle.yml create mode 100755 .husky/pre-commit delete mode 100644 checkstyle.xml delete mode 100644 codestyle.gradle diff --git a/.editorconfig b/.editorconfig index b7bac97ba6..6c31af5522 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,8 +3,8 @@ charset = utf-8 end_of_line = lf indent_size = 4 indent_style = space -insert_final_newline = false -max_line_length = 100 +insert_final_newline = true +max_line_length = 200 tab_width = 4 ij_continuation_indent_size = 8 ij_formatter_off_tag = @formatter:off diff --git a/.github/workflows/checkstyle.yml b/.github/workflows/checkstyle.yml deleted file mode 100644 index 88987fcd84..0000000000 --- a/.github/workflows/checkstyle.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Check Style -on: - pull_request: -jobs: - lint: - name: Run CheckStyle - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Set up JDK - uses: actions/setup-java@v3 - with: - distribution: zulu - java-version: 11 - cache: gradle - - name: Run - run: ./gradlew --no-daemon checkStyleChanged - - name: Upload report - uses: actions/upload-artifact@v2 - if: ${{ always() }} # IMPORTANT: Upload reports regardless of status - with: - name: checkstyle-reports - path: build/reports/checkstyle/ diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml new file mode 100644 index 0000000000..3c02b29da4 --- /dev/null +++ b/.github/workflows/codestyle.yml @@ -0,0 +1,27 @@ +name: Check code format +on: + pull_request: +jobs: + lint: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup NodeJS + uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Install dependencies + run: npm install + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v34 + - name: Check all changed files + run: | + for file in ${{ steps.changed-files.outputs.all_changed_files }}; do + npx ec "$file" + done + diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index d30d46fc52..42f08d3b86 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -18,10 +18,11 @@ jobs: run: ./gradlew :app:detekt continue-on-error: true - name: Run Android Lint - run: ./gradlew :app:lintAnalyticsDebug -x checkStyleMain -x checkStyleTest + run: ./gradlew :app:lintAnalyticsDebug - name: Run Android Lint Reporter to report Lint and Detekt result to PR env: PR_NUMBER: ${{ github.event.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - ./gradlew report -PgithubPullRequestId=$PR_NUMBER -PgithubToken=$GITHUB_TOKEN \ No newline at end of file + ./gradlew report -PgithubPullRequestId=$PR_NUMBER -PgithubToken=$GITHUB_TOKEN + diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d771eb99c0..0d721cb00c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,4 +21,4 @@ jobs: - name: Run Kotlin lint run: ./gradlew :app:detekt - name: Run Android Lint - run: ./gradlew :app:lintAnalyticsDebug -x checkStyleMain -x checkStyleTest \ No newline at end of file + run: ./gradlew :app:lintAnalyticsDebug diff --git a/.gitignore b/.gitignore index 30de5e7d17..aa4d612d51 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,5 @@ fastlane/.google-play-key.json DCIM/ vendor/ .project -output/ \ No newline at end of file +output/ +node_modules/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000000..d24fdfc601 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index e6894599af..1b1a3a40fd 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -190,7 +190,7 @@ public static void importKSWalletFromFrontPage(String keystore, String password) click(withText("Continue")); onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(R.id.input_password)))))).perform(replaceText(password)); click(withText("Continue")); - Helper.wait(5); + Helper.wait(15); } public static void importKSWalletFromSettingsPage(String keystore, String password) diff --git a/app/src/main/java/com/alphawallet/app/App.java b/app/src/main/java/com/alphawallet/app/App.java index 04713efcc1..f8d48b1a4a 100644 --- a/app/src/main/java/com/alphawallet/app/App.java +++ b/app/src/main/java/com/alphawallet/app/App.java @@ -37,7 +37,8 @@ public void onCreate() Timber.plant(new ReleaseTree()); } - int defaultTheme = PreferenceManager.getDefaultSharedPreferences(this).getInt("theme", C.THEME_AUTO); + int defaultTheme = PreferenceManager.getDefaultSharedPreferences(this) + .getInt("theme", C.THEME_AUTO); if (defaultTheme == C.THEME_LIGHT) { diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index 831df164c1..e76b083e8f 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -86,7 +86,8 @@ public class TickerService private static final String CHAIN_IDS = "[CHAIN_ID]"; private static final String CURRENCY_TOKEN = "[CURRENCY]"; private static final String COINGECKO_CHAIN_CALL = "https://api.coingecko.com/api/v3/simple/price?ids=" + CHAIN_IDS + "&vs_currencies=" + CURRENCY_TOKEN + "&include_24hr_change=true"; - private static final String COINGECKO_API = "https://api.coingecko.com/api/v3/simple/token_price/" + CHAIN_IDS + "?contract_addresses=" + CONTRACT_ADDR + "&vs_currencies=" + CURRENCY_TOKEN + "&include_24hr_change=true"; + private static final String COINGECKO_API = String.format("https://api.coingecko.com/api/v3/simple/token_price/%s?contract_addresses=%s&vs_currencies=%s&include_24hr_change=true", + CHAIN_IDS, CONTRACT_ADDR, CURRENCY_TOKEN); private static final String DEXGURU_API = "https://api.dex.guru/v1/tokens/" + CONTRACT_ADDR + "-" + CHAIN_IDS; private static final String PHI_TICKER_API = "https://price.phi.network/api/ticker?filter=WPHI"; private static final String CURRENCY_CONV = "currency"; @@ -133,8 +134,8 @@ public void updateTickers() sharedPrefs.commit(); tickerUpdateTimer = Observable.interval(0, UPDATE_TICKER_CYCLE, TimeUnit.MINUTES) - .doOnNext(l -> tickerUpdate()) - .subscribe(); + .doOnNext(l -> tickerUpdate()) + .subscribe(); } private void tickerUpdate() @@ -168,13 +169,22 @@ private Double storeCurrentRate(Double rate) if (rate == 0.0) { TokenTicker tt = localSource.getCurrentTicker(TokensRealmSource.databaseKey(0, CURRENCY_CONV)); - if (tt != null) { return Double.parseDouble(tt.price); } - else { return 0.0; } + if (tt != null) + { + return Double.parseDouble(tt.price); + } + else + { + return 0.0; + } } else { TokenTicker currencyTicker = new TokenTicker(Double.toString(rate), "0", currentCurrencySymbolTxt, null, System.currentTimeMillis()); - localSource.updateERC20Tickers(0, new HashMap() {{ put(CURRENCY_CONV, currencyTicker); }}); + localSource.updateERC20Tickers(0, new HashMap() + {{ + put(CURRENCY_CONV, currencyTicker); + }}); return rate; } } @@ -275,7 +285,7 @@ public Single syncERC20Tickers(long chainId, List erc20T for (TokenCardMeta tcm : erc20Tokens) { if (!dexGuruQuery.containsKey(tcm.tokenId) // don't include any token in the dexguru queue - && (!currentTickerMap.containsKey(tcm.getAddress()) + && (!currentTickerMap.containsKey(tcm.getAddress()) || currentTickerMap.get(tcm.getAddress()) < staleTime)) //include tokens who's tickers have gone stale { lookupMap.put(tcm.getAddress().toLowerCase(), tcm); @@ -316,7 +326,10 @@ private Map fetchERC20TokenTickers(long chainId, Collection if (apiChainName == null) return erc20Tickers; final Map lookupMap = new HashMap<>(); - for (TokenCardMeta tcm : erc20Tokens) { lookupMap.put(tcm.getAddress().toLowerCase(), tcm); } + for (TokenCardMeta tcm : erc20Tokens) + { + lookupMap.put(tcm.getAddress().toLowerCase(), tcm); + } //build ticker header StringBuilder sb = new StringBuilder(); @@ -562,7 +575,8 @@ private TokenTicker decodeCoinGeckoTicker(JSONObject eth) fiatPrice = eth.getDouble("usd") * currentConversionRate; fiatChangeStr = eth.getString("usd_24h_change"); } - if (!TextUtils.isEmpty(fiatChangeStr) && Character.isDigit(fiatChangeStr.charAt(0))) changeValue = BigDecimal.valueOf(eth.getDouble(currentCurrencySymbolTxt.toLowerCase() + "_24h_change")); + if (!TextUtils.isEmpty(fiatChangeStr) && Character.isDigit(fiatChangeStr.charAt(0))) + changeValue = BigDecimal.valueOf(eth.getDouble(currentCurrencySymbolTxt.toLowerCase() + "_24h_change")); tTicker = new TokenTicker(String.valueOf(fiatPrice), changeValue.setScale(3, RoundingMode.DOWN).toString(), currentCurrencySymbolTxt, "", System.currentTimeMillis()); @@ -579,14 +593,14 @@ private TokenTicker decodeCoinGeckoTicker(JSONObject eth) public Single convertPair(String currency1, String currency2) { return Single.fromCallable(() -> { - if (currency1 == null || currency2 == null || currency1.equals(currency2)) return (Double)1.0; + if (currency1 == null || currency2 == null || currency1.equals(currency2)) return (Double) 1.0; String conversionURL = "http://currencies.apps.grandtrunk.net/getlatest/" + currency1 + "/" + currency2; double rate = 0.0; Request request = new Request.Builder() .url(conversionURL) - .addHeader("Connection","close") + .addHeader("Connection", "close") .get() .build(); @@ -609,8 +623,8 @@ public Single convertPair(String currency1, String currency2) }); } - private String callSmartContractFunction(Web3j web3j, - Function function, String contractAddress) throws Exception { + private String callSmartContractFunction(Web3j web3j, Function function, String contractAddress) + { String encodedFunction = FunctionEncoder.encode(function); try @@ -628,20 +642,24 @@ private String callSmartContractFunction(Web3j web3j, } catch (Exception e) { - e.printStackTrace(); + Timber.e(e); return null; } } - private static Function getTickers() { + private static Function getTickers() + { return new Function( "getTickers", Arrays.asList(), - Collections.singletonList(new TypeReference>() {})); + Collections.singletonList(new TypeReference>() + { + })); } /** * Potentially used by forks to add a custom ticker + * * @param chainId * @param ticker */ @@ -656,6 +674,7 @@ public void addCustomTicker(long chainId, TokenTicker ticker) /** * Potentially used by forks + * * @param chainId * @param address * @param ticker @@ -666,12 +685,14 @@ public void addCustomTicker(long chainId, String address, TokenTicker ticker) if (ticker != null && address != null) { Single.fromCallable(() -> { - localSource.updateERC20Tickers(chainId, new HashMap() - {{ put(address, ticker); }}); - return true; - }).subscribeOn(Schedulers.io()) - .observeOn(Schedulers.io()) - .subscribe().isDisposed(); + localSource.updateERC20Tickers(chainId, new HashMap() + {{ + put(address, ticker); + }}); + return true; + }).subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + .subscribe().isDisposed(); } } @@ -720,6 +741,7 @@ private void initCurrency() /** * Returns the current ISO currency string eg EUR, AUD etc. + * * @return 3 character currency ISO text */ public static String getCurrencySymbolTxt() @@ -745,7 +767,8 @@ private void resetTickerUpdate() } // Update this list from here: https://api.coingecko.com/api/v3/asset_platforms - public static final Map coinGeckoChainIdToAPIName = new HashMap(){{ + public static final Map coinGeckoChainIdToAPIName = new HashMap() + {{ put(MAINNET_ID, "ethereum"); put(GNOSIS_ID, "xdai"); put(BINANCE_MAIN_ID, "binance-smart-chain"); @@ -767,7 +790,8 @@ private void resetTickerUpdate() put(CRONOS_MAIN_ID, "cronos"); }}; - private static final Map dexGuruChainIdToAPISymbol = new HashMap(){{ + private static final Map dexGuruChainIdToAPISymbol = new HashMap() + {{ put(MAINNET_ID, "eth"); put(BINANCE_MAIN_ID, "bsc"); put(POLYGON_ID, "polygon"); @@ -780,7 +804,8 @@ public void deleteTickers() } // Update from https://api.coingecko.com/api/v3/coins/list - public static final Map chainPairs = new HashMap(){{ + public static final Map chainPairs = new HashMap() + {{ put(MAINNET_ID, "ethereum"); put(CLASSIC_ID, "ethereum-classic"); put(POA_ID, "poa-network"); @@ -812,7 +837,10 @@ private String getCoinGeckoChainCall() boolean firstPair = true; for (long chainId : chainPairs.keySet()) { - if (ethTickers.containsKey(chainId)) { continue; } + if (ethTickers.containsKey(chainId)) + { + continue; + } if (!firstPair) tokenList.append(","); firstPair = false; tokenList.append(chainPairs.get(chainId)); @@ -825,7 +853,10 @@ private boolean receivedAllChainPairs() { for (long chainId : chainPairs.keySet()) { - if (!ethTickers.containsKey(chainId)) { return false; } + if (!ethTickers.containsKey(chainId)) + { + return false; + } } return true; diff --git a/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java b/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java index f95f12fea2..935261ff4e 100644 --- a/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java +++ b/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java @@ -28,7 +28,7 @@ public void should_getNodeURLByNetworkId_when_use_production_key() public void should_construct_infura_url_when_getNodeURLByNetworkId_given_production_key() { assertThat(EthereumNetworkBase.getNodeURLByNetworkId(1L), equalTo("https://mainnet.infura.io/v3/fake-key-for-testing")); - assertThat(EthereumNetworkBase.getNodeURLByNetworkId(3L), equalTo("https://ropsten.infura.io/v3/fake-key-for-testing")); + assertThat(EthereumNetworkBase.getNodeURLByNetworkId(3L), equalTo("https://rpc.ankr.com/eth_ropsten")); } @Test diff --git a/build.gradle b/build.gradle index c355f044db..1de078a0b4 100644 --- a/build.gradle +++ b/build.gradle @@ -11,8 +11,6 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:7.0.3' - //NB - there is an issue with newer versions of gradle. The APK balloons out, so far haven't diagnosed why. - //If you want to try upgrading gradle plugin past 3.5.4 you will need to also diagnose the APK ballooning issue. classpath "io.realm:realm-gradle-plugin:10.11.1" // WARNING WARNING WARNING // you are about to add here a dependency to be used in the Android app @@ -25,8 +23,6 @@ buildscript { } allprojects { - //apply from: rootProject.file("codestyle.gradle") - repositories { google() jcenter() diff --git a/build.sh b/build.sh index 75cdf3a57f..2289678e41 100644 --- a/build.sh +++ b/build.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -cd dmz && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -cd lib && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -cd util && ../gradlew -i build -x checkStyleMain -x checkStyleTest && ../gradlew -i test && cd .. -./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt -x checkStyleMain -x checkStyleTest \ No newline at end of file +cd dmz && ../gradlew -i build && ../gradlew -i test && cd .. +cd lib && ../gradlew -i build && ../gradlew -i test && cd .. +cd util && ../gradlew -i build && ../gradlew -i test && cd .. +./gradlew clean jacocoTestNoAnalyticsDebugUnitTestReport -x lint -x detekt diff --git a/checkstyle.xml b/checkstyle.xml deleted file mode 100644 index d1c044eded..0000000000 --- a/checkstyle.xml +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/codestyle.gradle b/codestyle.gradle deleted file mode 100644 index e642c669e4..0000000000 --- a/codestyle.gradle +++ /dev/null @@ -1,90 +0,0 @@ -import java.util.regex.Matcher -import java.util.regex.Pattern - -apply plugin: 'checkstyle' - -checkstyle { - // default path is config/checkstyle/checkstyle.xml - toolVersion "10.3.4" - ignoreFailures false - maxWarnings 0 - configFile rootProject.file("checkstyle.xml") -} - -// Customize all the Checkstyle tasks -tasks.withType(Checkstyle) { - // Specify all files that should be checked - classpath = files() - source "${project.rootDir}" - - reports { - html { - enabled true - destination rootProject.file("build/reports/checkstyle/checkstyle.html") - } - xml { - enabled true - destination rootProject.file("build/reports/checkstyle/checkstyle.xml") - } - } -} - -// Execute Checkstyle on all files -task checkstyle(type: Checkstyle) { -} - -// Execute Checkstyle on all modified files -task checkstyleChanged(type: Checkstyle) { - def changedFiles = getChangedFiles() - include changedFiles -} - -/** - * Get all files that are changed but not deleted nor renamed. - * Compares to master or the specified target branch. - * - * @return list of all changed files - */ -def getChangedFiles() { - // Get the target and source branch - def baseRef = System.getenv("GITHUB_BASE_REF") - def headRef = System.getenv("GITHUB_HEAD_REF") - - def targetBranch = 'origin/' + (baseRef ? baseRef : getParentBranch()) - def sourceBranch = headRef ? 'origin/' + headRef : "" - - // Get list of all changed files including status - def systemOutStream = new ByteArrayOutputStream() - def command = "git diff --name-only $targetBranch $sourceBranch" - command.execute().waitForProcessOutput(systemOutStream, System.err) - def allFiles = systemOutStream.toString().trim().split('\n') - systemOutStream.close() - - allFiles.toList() -} - -/** - * Determines the parent branch. - * - * @return the found parent branch or master if not possible - */ -def getParentBranch() { - def branch = "" - // Get short name of the HEAD branch - def branchDeterminer = "git rev-parse --abbrev-ref HEAD".execute() - branchDeterminer.in.eachLine { line -> branch = line } - branchDeterminer.err.eachLine { line -> println line } - branchDeterminer.waitFor() - // Search all branches for parent - def branchLine = 'git show-branch -a'.execute().text.readLines().find { - it.contains('*') && !(it ==~ ".*\\[$branch[~^\\]].*") - } - try { - // Filter parent branch name - def parent = (branchLine =~ /\[([^~^\]]*)[~^\]]/)[0][1] - return parent - } catch (Exception ignored) { - println "Could not determine parent branch, compare to master" - return "master" - } -} diff --git a/package-lock.json b/package-lock.json index e07f5c087a..fc8648e450 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,2150 @@ { "name": "alpha-wallet-android", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "alpha-wallet-android", + "version": "1.0.0", + "license": "GPL-3.0", + "dependencies": { + "normalize.css": "^8.0.0" + }, + "devDependencies": { + "editorconfig-checker": "4.0.0", + "husky": "^8.0.0", + "lint-staged": "^13.0.3" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "node_modules/commander": { + "version": "9.4.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/editorconfig-checker": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/editorconfig-checker/-/editorconfig-checker-4.0.0.tgz", + "integrity": "sha512-Vd0bfNHFsacoy+4l7TTSXpoCwBD6njW5OTz9ftYSTkKZokC4nPzFMVg1ZBci3BzXqxpT/pt5b+t3raKJ9EYvrg==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.0", + "rimraf": "^3.0.2", + "tar": "^6.0.0" + }, + "bin": { + "ec": "dist/index.js", + "editorconfig-checker": "dist/index.js" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "dev": true, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/husky": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/husky/-/husky-8.0.1.tgz", + "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lint-staged": { + "version": "13.0.3", + "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-13.0.3.tgz", + "integrity": "sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==", + "dev": true, + "dependencies": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.17", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^6.1.0", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.1.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize.css": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz", + "integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A==" + }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rxjs": { + "version": "7.5.7", + "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-7.5.7.tgz", + "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/tar": { + "version": "6.1.12", + "resolved": "https://registry.npmmirror.com/tar/-/tar-6.1.12.tgz", + "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.1.3.tgz", + "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", + "dev": true, + "engines": { + "node": ">= 14" + } + } + }, "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "commander": { + "version": "9.4.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "editorconfig-checker": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/editorconfig-checker/-/editorconfig-checker-4.0.0.tgz", + "integrity": "sha512-Vd0bfNHFsacoy+4l7TTSXpoCwBD6njW5OTz9ftYSTkKZokC4nPzFMVg1ZBci3BzXqxpT/pt5b+t3raKJ9EYvrg==", + "dev": true, + "requires": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.0", + "rimraf": "^3.0.2", + "tar": "^6.0.0" + } + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "execa": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "dev": true + }, + "husky": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/husky/-/husky-8.0.1.tgz", + "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true + }, + "lint-staged": { + "version": "13.0.3", + "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-13.0.3.tgz", + "integrity": "sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==", + "dev": true, + "requires": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.17", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^6.1.0", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.1.1" + } + }, + "listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "normalize.css": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz", "integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A==" + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + }, + "dependencies": { + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + } + } + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + } + } + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rxjs": { + "version": "7.5.7", + "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-7.5.7.tgz", + "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + } + }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + }, + "tar": { + "version": "6.1.12", + "resolved": "https://registry.npmmirror.com/tar/-/tar-6.1.12.tgz", + "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.1.3.tgz", + "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", + "dev": true } } } diff --git a/package.json b/package.json index 4ce54ccdc6..7287014736 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "alpha-wallet-android", "version": "1.0.0", - "description": "Each module has its own README. Please click the name of the module to go to the corrisponding README file.", + "description": "Open source Ethereum wallet", "main": "gulpfile.js", "directories": { "lib": "lib" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "prepare": "husky install" }, "repository": { "type": "git", @@ -21,5 +22,15 @@ "homepage": "https://github.com/AlphaWallet/alpha-wallet-android#readme", "dependencies": { "normalize.css": "^8.0.0" + }, + "devDependencies": { + "editorconfig-checker": "4.0.0", + "husky": "^8.0.0", + "lint-staged": "^13.0.3" + }, + "lint-staged": { + "**/*": [ + "npx ec" + ] } } From 4d35f5077b4fb4b414e3ebdf4ba3cb83a4e9f4fc Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Mon, 7 Nov 2022 16:47:56 +0800 Subject: [PATCH 134/183] fix malicious dapp make app crash (#2911) * Fix potential NPE * Fix crash when sign invalid message --- .../app/web3/SignCallbackJSInterface.java | 2 +- lib/build.gradle | 2 +- .../token/entity/EthereumMessage.java | 22 +++++++------- .../token/entity/EthereumMessageTest.java | 29 +++++++++++++++++++ 4 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 lib/src/test/java/com/alphawallet/token/entity/EthereumMessageTest.java diff --git a/app/src/main/java/com/alphawallet/app/web3/SignCallbackJSInterface.java b/app/src/main/java/com/alphawallet/app/web3/SignCallbackJSInterface.java index 37ad9670f0..47d34b7bda 100644 --- a/app/src/main/java/com/alphawallet/app/web3/SignCallbackJSInterface.java +++ b/app/src/main/java/com/alphawallet/app/web3/SignCallbackJSInterface.java @@ -77,7 +77,7 @@ public void signTransaction( String gasLimit, String gasPrice, String payload) { - if (value.equals("undefined") || value == null) value = "0"; + if (value == null || value.equals("undefined")) value = "0"; if (gasPrice == null) gasPrice = "0"; Web3Transaction transaction = new Web3Transaction( TextUtils.isEmpty(recipient) ? Address.EMPTY : new Address(recipient), diff --git a/lib/build.gradle b/lib/build.gradle index 602fe07e6b..d368921cb8 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -15,7 +15,7 @@ dependencies { implementation files('..\\app\\libs\\core-4.8.8-android.jar') implementation files('..\\app\\libs\\crypto-4.8.8-android.jar') implementation files('..\\app\\libs\\utils-4.8.8-android.jar') - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13.2' implementation 'org.bouncycastle:bcprov-jdk15on:1.62' // https://mvnrepository.com/artifact/com.github.cliftonlabs/json-simple implementation group: 'com.github.cliftonlabs', name: 'json-simple', version: '3.1.0' diff --git a/lib/src/main/java/com/alphawallet/token/entity/EthereumMessage.java b/lib/src/main/java/com/alphawallet/token/entity/EthereumMessage.java index ece5b6d5ce..f81da30576 100644 --- a/lib/src/main/java/com/alphawallet/token/entity/EthereumMessage.java +++ b/lib/src/main/java/com/alphawallet/token/entity/EthereumMessage.java @@ -1,5 +1,7 @@ package com.alphawallet.token.entity; +import static com.alphawallet.token.tools.Numeric.cleanHexPrefix; + import com.alphawallet.token.tools.Numeric; import java.io.ByteArrayOutputStream; @@ -7,8 +9,6 @@ import java.nio.CharBuffer; import java.nio.charset.StandardCharsets; -import static com.alphawallet.token.tools.Numeric.cleanHexPrefix; - /** * Class for EthereumMessages to be signed. * Weiwu, Aug 2020 @@ -26,6 +26,8 @@ public EthereumMessage(String message, String displayOrigin, long leafPosition, this.displayOrigin = displayOrigin; this.leafPosition = leafPosition; this.messageType = type; + + message = message == null ? "" : message; this.prehash = getEthereumMessage(message); this.userMessage = message; } @@ -70,16 +72,14 @@ public CharSequence getUserMessage() { return userMessage; } - else + + try { - try - { - return hexToUtf8(userMessage); - } - catch (NumberFormatException e) - { - return userMessage; - } + return hexToUtf8(userMessage); + } + catch (Exception e) + { + return userMessage; } } diff --git a/lib/src/test/java/com/alphawallet/token/entity/EthereumMessageTest.java b/lib/src/test/java/com/alphawallet/token/entity/EthereumMessageTest.java new file mode 100644 index 0000000000..9f38e46844 --- /dev/null +++ b/lib/src/test/java/com/alphawallet/token/entity/EthereumMessageTest.java @@ -0,0 +1,29 @@ +package com.alphawallet.token.entity; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import org.junit.Test; + +public class EthereumMessageTest +{ + @Test + public void should_get_message() + { + EthereumMessage message = new EthereumMessage("aaaaa", "", 1, null); + assertThat(message.getMessage(), equalTo("aaaaa")); + assertThat(message.getUserMessage(), equalTo("aaaaa")); + + message = new EthereumMessage("68656c6c6f", "", 1, null); + assertThat(message.getMessage(), equalTo("68656c6c6f")); + assertThat(message.getUserMessage(), equalTo("hello")); + + message = new EthereumMessage("0x68656c6c6f", "", 1, null); + assertThat(message.getMessage(), equalTo("0x68656c6c6f")); + assertThat(message.getUserMessage(), equalTo("hello")); + + message = new EthereumMessage(null, "", 1, null); + assertThat(message.getMessage(), equalTo("")); + assertThat(message.getUserMessage(), equalTo("")); + } +} \ No newline at end of file From 40c5bcfa8540e64a16cbf15dbe21369b1d3acc29 Mon Sep 17 00:00:00 2001 From: justindg Date: Mon, 7 Nov 2022 03:40:05 -0800 Subject: [PATCH 135/183] Fix Swap Issues (#2918) * Set max button disabled by default * Replaced AddressIcon with ImageView * Replace dead link --- app/src/main/assets/swap_providers_list.json | 4 ++-- .../app/ui/SelectSwapProvidersActivity.java | 2 +- .../ui/widget/adapter/SwapProviderAdapter.java | 17 +++++++++++++---- app/src/main/res/drawable/masking_circle.xml | 13 +++---------- app/src/main/res/layout/item_asset_image.xml | 2 +- app/src/main/res/layout/item_exchange.xml | 5 +++-- app/src/main/res/layout/token_selector.xml | 3 ++- 7 files changed, 25 insertions(+), 21 deletions(-) diff --git a/app/src/main/assets/swap_providers_list.json b/app/src/main/assets/swap_providers_list.json index 6bfd9baaf9..54d19d0af4 100644 --- a/app/src/main/assets/swap_providers_list.json +++ b/app/src/main/assets/swap_providers_list.json @@ -33,7 +33,7 @@ "key": "superfluid", "name": "Superfluid", "url": "https://www.superfluid.finance/", - "logoURI": "https://www.superfluid.finance/icons/icon-72x72.png" + "logoURI": "https://www.superfluid.finance/assets/favicon/favicon-32x32.png" }, { "key": "uniswap", @@ -107,4 +107,4 @@ "url": "https://sushi.com/", "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/sushi.png" } -] \ No newline at end of file +] diff --git a/app/src/main/java/com/alphawallet/app/ui/SelectSwapProvidersActivity.java b/app/src/main/java/com/alphawallet/app/ui/SelectSwapProvidersActivity.java index c70087e814..d5822ebfbf 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SelectSwapProvidersActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SelectSwapProvidersActivity.java @@ -47,7 +47,7 @@ private void initViews() { RecyclerView recyclerView = findViewById(R.id.list); recyclerView.setLayoutManager(new LinearLayoutManager(this)); - adapter = new SwapProviderAdapter(viewModel.getSwapProviders()); + adapter = new SwapProviderAdapter(this, viewModel.getSwapProviders()); recyclerView.setAdapter(adapter); } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SwapProviderAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SwapProviderAdapter.java index 724af0fdca..dffec42370 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SwapProviderAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SwapProviderAdapter.java @@ -1,5 +1,6 @@ package com.alphawallet.app.ui.widget.adapter; +import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -7,11 +8,13 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.appcompat.widget.AppCompatImageView; import androidx.recyclerview.widget.RecyclerView; import com.alphawallet.app.R; import com.alphawallet.app.entity.lifi.SwapProvider; -import com.alphawallet.app.widget.AddressIcon; +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.DrawableImageViewTarget; import com.google.android.material.checkbox.MaterialCheckBox; import java.util.List; @@ -19,9 +22,11 @@ public class SwapProviderAdapter extends RecyclerView.Adapter { private final List data; + private final Context context; - public SwapProviderAdapter(List data) + public SwapProviderAdapter(Context context, List data) { + this.context = context; this.data = data; } @@ -45,7 +50,11 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) holder.subtitle.setText(item.url); - holder.icon.bindData(item.logoURI, -1, "", ""); + Glide.with(context) + .load(item.logoURI) + .placeholder(R.drawable.ic_logo) + .circleCrop() + .into(new DrawableImageViewTarget(holder.icon)); holder.layout.setOnClickListener(v -> holder.checkBox.setChecked(!item.isChecked)); @@ -69,7 +78,7 @@ public int getItemCount() static class ViewHolder extends RecyclerView.ViewHolder { RelativeLayout layout; - AddressIcon icon; + AppCompatImageView icon; TextView title; TextView subtitle; MaterialCheckBox checkBox; diff --git a/app/src/main/res/drawable/masking_circle.xml b/app/src/main/res/drawable/masking_circle.xml index 2656d493c3..04ab999632 100644 --- a/app/src/main/res/drawable/masking_circle.xml +++ b/app/src/main/res/drawable/masking_circle.xml @@ -1,12 +1,5 @@ - - \ No newline at end of file + android:shape="oval"> + + diff --git a/app/src/main/res/layout/item_asset_image.xml b/app/src/main/res/layout/item_asset_image.xml index 55384c05d0..47dce539e5 100644 --- a/app/src/main/res/layout/item_asset_image.xml +++ b/app/src/main/res/layout/item_asset_image.xml @@ -43,7 +43,7 @@ android:id="@+id/overlay" android:layout_width="match_parent" android:layout_height="match_parent" - android:src="@drawable/masking_circle" + android:src="@drawable/select_masking_circle" android:visibility="gone" /> - @@ -50,4 +51,4 @@ android:clickable="false" android:focusable="false" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/token_selector.xml b/app/src/main/res/layout/token_selector.xml index 6240cc5f16..b26d608fbd 100644 --- a/app/src/main/res/layout/token_selector.xml +++ b/app/src/main/res/layout/token_selector.xml @@ -124,6 +124,7 @@ style="@style/Aw.Typography.Control" android:layout_width="match_parent" android:layout_height="wrap_content" + android:enabled="false" android:gravity="end" android:lines="1" android:text="@string/seekbar_max" @@ -146,4 +147,4 @@ style="@style/Aw.Component.Separator" android:layout_marginTop="@dimen/cozy_20" /> - \ No newline at end of file + From a907ea3652151e40eb95c984f504934ff76dbe19 Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 8 Nov 2022 15:57:01 +1100 Subject: [PATCH 136/183] Add IPFS connection point (#2920) * Shift to using type interface for IPFSService to make it possible to implement IO-free unit tests * Update IPFS usage and add unit testing for new service. * Fix certificate test * Updates as suggested --- .github/workflows/codestyle.yml | 21 +- .../app/TokenScriptCertificateTest.java | 18 +- .../app/di/RepositoriesModule.java | 295 ++++++++++-------- .../app/entity/ContractInteract.java | 34 +- .../alphawallet/app/entity/QueryResponse.java | 23 ++ .../app/entity/tokenscript/TestScript.java | 70 +++++ .../app/service/AssetDefinitionService.java | 98 +++--- .../alphawallet/app/service/IPFSService.java | 131 ++++++++ .../app/service/IPFSServiceType.java | 14 + .../service/TransactionsNetworkClient.java | 30 +- .../java/com/alphawallet/app/util/Utils.java | 20 +- .../alphawallet/app/web3j/ens/NameHash.java | 11 +- .../com/alphawallet/app/IPFSServiceTest.java | 68 ++++ 13 files changed, 596 insertions(+), 237 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/entity/QueryResponse.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/tokenscript/TestScript.java create mode 100644 app/src/main/java/com/alphawallet/app/service/IPFSService.java create mode 100644 app/src/main/java/com/alphawallet/app/service/IPFSServiceType.java create mode 100644 app/src/test/java/com/alphawallet/app/IPFSServiceTest.java diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index 3c02b29da4..12adccc228 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -22,6 +22,23 @@ jobs: - name: Check all changed files run: | for file in ${{ steps.changed-files.outputs.all_changed_files }}; do - npx ec "$file" + npx ec -no-color "$file" >> format-error.txt || true done - + if [[ -s "format-error.txt" ]]; then + exit 1 + else + exit 0 + fi + - name: Collect results + if: ${{ failure() }} + uses: actions/upload-artifact@v1 + with: + name: format-error + path: format-error.txt + - name: comment PR + if: ${{ failure() }} + uses: machine-learning-apps/pr-comment@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + path: format-error.txt diff --git a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java index d8c85166b3..b609e61eb3 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TokenScriptCertificateTest.java @@ -24,9 +24,9 @@ import androidx.test.espresso.action.ViewActions; -import com.alphawallet.app.resources.Contracts; import com.alphawallet.app.util.EthUtils; import com.alphawallet.app.util.Helper; +import com.alphawallet.app.resources.Contracts; import org.junit.Test; import org.web3j.crypto.Credentials; @@ -42,10 +42,12 @@ */ public class TokenScriptCertificateTest extends BaseE2ETest { - private final String doorContractAddress; + private String doorContractAddress; private final String contractOwnerPk = "0x69c22d654be7fe75e31fbe26cb56c93ec91144fab67cb71529c8081971635069"; private final Web3j web3j; + private final boolean useMumbai = false; //for local testing + private static final Map WALLETS_ON_GANACHE = new HashMap() { { @@ -83,6 +85,12 @@ public TokenScriptCertificateTest() //Always use zero nonce for determining the contract address doorContractAddress = EthUtils.calculateContractAddress(deployCredentials.getAddress(), 0L); + + if (useMumbai) + { + //If using Mumbai for this test: + doorContractAddress = "0xA0343dfd68FcD7F18153b8AB87936c5A9C1Da20e"; + } } @Test @@ -103,7 +111,7 @@ public void should_view_signature_details() assertThat(getWalletAddress(), equalTo(ownerAddress)); addNewNetwork("Ganache", GANACHE_URL); - selectTestNet("Ganache"); + selectTestNet(useMumbai ? "Mumbai" : "Ganache"); //Ensure we're on the wallet page switchToWallet(ownerAddress); @@ -139,6 +147,8 @@ public void should_view_signature_details() shouldSee("Smart Token Labs"); shouldSee("ECDSA"); - shouldSee("Contract Owner"); // Note this may fail once we pull owner() from contract, test will need to be changed to contract owner, which for this test is: 0xA20efc4B9537d27acfD052003e311f762620642D + shouldSee("Contract Owner"); // Note this may fail once we pull owner() from contract, + // test will need to be changed to contract owner, + // which for this test is: 0xA20efc4B9537d27acfD052003e311f762620642D } } diff --git a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java index 446f65604c..56cf427dab 100644 --- a/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java +++ b/app/src/main/java/com/alphawallet/app/di/RepositoriesModule.java @@ -31,6 +31,8 @@ import com.alphawallet.app.service.AnalyticsServiceType; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.service.GasService; +import com.alphawallet.app.service.IPFSService; +import com.alphawallet.app.service.IPFSServiceType; import com.alphawallet.app.service.KeyService; import com.alphawallet.app.service.KeystoreAccountService; import com.alphawallet.app.service.NotificationService; @@ -57,83 +59,93 @@ @Module @InstallIn(SingletonComponent.class) -public class RepositoriesModule { - @Singleton - @Provides - PreferenceRepositoryType providePreferenceRepository(@ApplicationContext Context context) { - return new SharedPreferenceRepository(context); - } - - @Singleton - @Provides - AccountKeystoreService provideAccountKeyStoreService(@ApplicationContext Context context, KeyService keyService) { +public class RepositoriesModule +{ + @Singleton + @Provides + PreferenceRepositoryType providePreferenceRepository(@ApplicationContext Context context) + { + return new SharedPreferenceRepository(context); + } + + @Singleton + @Provides + AccountKeystoreService provideAccountKeyStoreService(@ApplicationContext Context context, KeyService keyService) + { File file = new File(context.getFilesDir(), KEYSTORE_FOLDER); - return new KeystoreAccountService(file, context.getFilesDir(), keyService); - } + return new KeystoreAccountService(file, context.getFilesDir(), keyService); + } - @Singleton + @Singleton @Provides - TickerService provideTickerService(OkHttpClient httpClient, PreferenceRepositoryType sharedPrefs, TokenLocalSource localSource) { - return new TickerService(httpClient, sharedPrefs, localSource); + TickerService provideTickerService(OkHttpClient httpClient, PreferenceRepositoryType sharedPrefs, TokenLocalSource localSource) + { + return new TickerService(httpClient, sharedPrefs, localSource); } - @Singleton - @Provides - EthereumNetworkRepositoryType provideEthereumNetworkRepository( + @Singleton + @Provides + EthereumNetworkRepositoryType provideEthereumNetworkRepository( PreferenceRepositoryType preferenceRepository, - @ApplicationContext Context context - ) + @ApplicationContext Context context + ) { return new EthereumNetworkRepository(preferenceRepository, context); } - @Singleton - @Provides + @Singleton + @Provides WalletRepositoryType provideWalletRepository( - PreferenceRepositoryType preferenceRepositoryType, - AccountKeystoreService accountKeystoreService, - EthereumNetworkRepositoryType networkRepository, - WalletDataRealmSource walletDataRealmSource, - KeyService keyService) { - return new WalletRepository( - preferenceRepositoryType, accountKeystoreService, networkRepository, walletDataRealmSource, keyService); - } - - @Singleton - @Provides - TransactionRepositoryType provideTransactionRepository( - EthereumNetworkRepositoryType networkRepository, - AccountKeystoreService accountKeystoreService, + PreferenceRepositoryType preferenceRepositoryType, + AccountKeystoreService accountKeystoreService, + EthereumNetworkRepositoryType networkRepository, + WalletDataRealmSource walletDataRealmSource, + KeyService keyService) + { + return new WalletRepository( + preferenceRepositoryType, accountKeystoreService, networkRepository, walletDataRealmSource, keyService); + } + + @Singleton + @Provides + TransactionRepositoryType provideTransactionRepository( + EthereumNetworkRepositoryType networkRepository, + AccountKeystoreService accountKeystoreService, TransactionLocalSource inDiskCache, - TransactionsService transactionsService) { - return new TransactionRepository( - networkRepository, - accountKeystoreService, - inDiskCache, - transactionsService); - } + TransactionsService transactionsService) + { + return new TransactionRepository( + networkRepository, + accountKeystoreService, + inDiskCache, + transactionsService); + } - @Singleton - @Provides - OnRampRepositoryType provideOnRampRepository(@ApplicationContext Context context) { - return new OnRampRepository(context); - } + @Singleton + @Provides + OnRampRepositoryType provideOnRampRepository(@ApplicationContext Context context) + { + return new OnRampRepository(context); + } @Singleton @Provides - SwapRepositoryType provideSwapRepository(@ApplicationContext Context context) { + SwapRepositoryType provideSwapRepository(@ApplicationContext Context context) + { return new SwapRepository(context); } @Singleton @Provides - CoinbasePayRepositoryType provideCoinbasePayRepository() { + CoinbasePayRepositoryType provideCoinbasePayRepository() + { return new CoinbasePayRepository(); } - @Singleton + @Singleton @Provides - TransactionLocalSource provideTransactionInDiskCache(RealmManager realmManager) { + TransactionLocalSource provideTransactionInDiskCache(RealmManager realmManager) + { return new TransactionsRealmCache(realmManager); } @@ -147,105 +159,120 @@ TransactionsNetworkClientType provideBlockExplorerClient( return new TransactionsNetworkClient(httpClient, gson, realmManager); } - @Singleton + @Singleton @Provides TokenRepositoryType provideTokenRepository( EthereumNetworkRepositoryType ethereumNetworkRepository, TokenLocalSource tokenLocalSource, - OkHttpClient httpClient, - @ApplicationContext Context context, - TickerService tickerService) { - return new TokenRepository( - ethereumNetworkRepository, - tokenLocalSource, - httpClient, - context, - tickerService); + OkHttpClient httpClient, + @ApplicationContext Context context, + TickerService tickerService) + { + return new TokenRepository( + ethereumNetworkRepository, + tokenLocalSource, + httpClient, + context, + tickerService); } @Singleton @Provides - TokenLocalSource provideRealmTokenSource(RealmManager realmManager, EthereumNetworkRepositoryType ethereumNetworkRepository) { - return new TokensRealmSource(realmManager, ethereumNetworkRepository); + TokenLocalSource provideRealmTokenSource(RealmManager realmManager, EthereumNetworkRepositoryType ethereumNetworkRepository) + { + return new TokensRealmSource(realmManager, ethereumNetworkRepository); } - @Singleton - @Provides - WalletDataRealmSource provideRealmWalletDataSource(RealmManager realmManager) { - return new WalletDataRealmSource(realmManager); - } + @Singleton + @Provides + WalletDataRealmSource provideRealmWalletDataSource(RealmManager realmManager) + { + return new WalletDataRealmSource(realmManager); + } - @Singleton - @Provides - TokensService provideTokensService(EthereumNetworkRepositoryType ethereumNetworkRepository, - TokenRepositoryType tokenRepository, - TickerService tickerService, - OpenSeaService openseaService, - AnalyticsServiceType analyticsService) { - return new TokensService(ethereumNetworkRepository, tokenRepository, tickerService, openseaService, analyticsService); - } + @Singleton + @Provides + TokensService provideTokensServices(EthereumNetworkRepositoryType ethereumNetworkRepository, + TokenRepositoryType tokenRepository, + TickerService tickerService, + OpenSeaService openseaService, + AnalyticsServiceType analyticsService) + { + return new TokensService(ethereumNetworkRepository, tokenRepository, tickerService, openseaService, analyticsService); + } - @Singleton - @Provides - TransactionsService provideTransactionsService(TokensService tokensService, - EthereumNetworkRepositoryType ethereumNetworkRepositoryType, - TransactionsNetworkClientType transactionsNetworkClientType, - TransactionLocalSource transactionLocalSource) { - return new TransactionsService(tokensService, ethereumNetworkRepositoryType, transactionsNetworkClientType, transactionLocalSource); - } + @Singleton + @Provides + IPFSServiceType provideIPFSService(OkHttpClient client) + { + return new IPFSService(client); + } @Singleton @Provides - GasService provideGasService(EthereumNetworkRepositoryType ethereumNetworkRepository, - OkHttpClient client, - RealmManager realmManager) + TransactionsService provideTransactionsServices(TokensService tokensService, + EthereumNetworkRepositoryType ethereumNetworkRepositoryType, + TransactionsNetworkClientType transactionsNetworkClientType, + TransactionLocalSource transactionLocalSource) + { + return new TransactionsService(tokensService, ethereumNetworkRepositoryType, transactionsNetworkClientType, transactionLocalSource); + } + + @Singleton + @Provides + GasService provideGasService(EthereumNetworkRepositoryType ethereumNetworkRepository, OkHttpClient client, RealmManager realmManager) { return new GasService(ethereumNetworkRepository, client, realmManager); } - @Singleton - @Provides - OpenSeaService provideOpenseaService() { - return new OpenSeaService(); - } - - @Singleton - @Provides - SwapService provideSwapService() { - return new SwapService(); - } - - @Singleton - @Provides - AlphaWalletService provideFeemasterService(OkHttpClient okHttpClient, - TransactionRepositoryType transactionRepository, - Gson gson) { - return new AlphaWalletService(okHttpClient, transactionRepository, gson); - } - - @Singleton - @Provides - NotificationService provideNotificationService(@ApplicationContext Context ctx) { - return new NotificationService(ctx); - } - - @Singleton - @Provides - AssetDefinitionService provideAssetDefinitionService(OkHttpClient okHttpClient, @ApplicationContext Context ctx, NotificationService notificationService, RealmManager realmManager, - TokensService tokensService, TokenLocalSource tls, TransactionRepositoryType trt, - AlphaWalletService alphaService) { - return new AssetDefinitionService(okHttpClient, ctx, notificationService, realmManager, tokensService, tls, trt, alphaService); - } - - @Singleton - @Provides - KeyService provideKeyService(@ApplicationContext Context ctx, AnalyticsServiceType analyticsService) { - return new KeyService(ctx, analyticsService); - } - - @Singleton - @Provides - AnalyticsServiceType provideAnalyticsService(@ApplicationContext Context ctx) { - return new AnalyticsService(ctx); - } + @Singleton + @Provides + OpenSeaService provideOpenseaService() + { + return new OpenSeaService(); + } + + @Singleton + @Provides + SwapService provideSwapService() + { + return new SwapService(); + } + + @Singleton + @Provides + AlphaWalletService provideFeemasterService(OkHttpClient okHttpClient, TransactionRepositoryType transactionRepository, Gson gson) + { + return new AlphaWalletService(okHttpClient, transactionRepository, gson); + } + + @Singleton + @Provides + NotificationService provideNotificationService(@ApplicationContext Context ctx) + { + return new NotificationService(ctx); + } + + @Singleton + @Provides + AssetDefinitionService providingAssetDefinitionServices(IPFSServiceType ipfsService, @ApplicationContext Context ctx, NotificationService notificationService, RealmManager realmManager, + TokensService tokensService, TokenLocalSource tls, + AlphaWalletService alphaService) + { + return new AssetDefinitionService(ipfsService, ctx, notificationService, realmManager, tokensService, tls, alphaService); + } + + @Singleton + @Provides + KeyService provideKeyService(@ApplicationContext Context ctx, AnalyticsServiceType analyticsService) + { + return new KeyService(ctx, analyticsService); + } + + @Singleton + @Provides + AnalyticsServiceType provideAnalyticsService(@ApplicationContext Context ctx) + { + return new AnalyticsService(ctx); + } } diff --git a/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java b/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java index 9bc532e363..bdfaf2a92d 100644 --- a/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java +++ b/app/src/main/java/com/alphawallet/app/entity/ContractInteract.java @@ -7,6 +7,7 @@ import com.alphawallet.app.C; import com.alphawallet.app.entity.nftassets.NFTAsset; import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.service.IPFSService; import com.alphawallet.app.util.Utils; import org.web3j.abi.TypeReference; @@ -22,8 +23,6 @@ import io.reactivex.Single; import io.reactivex.schedulers.Schedulers; import okhttp3.OkHttpClient; -import okhttp3.Request; -import timber.log.Timber; /** * Created by JB on 7/05/2022. @@ -31,7 +30,7 @@ public class ContractInteract { private final Token token; - protected static OkHttpClient client; + protected static IPFSService client; public ContractInteract(Token token) { @@ -55,21 +54,7 @@ private String loadMetaData(String tokenURI) setupClient(); - Request request = new Request.Builder() - .url(Utils.parseIPFS(tokenURI)) - .get() - .build(); - - try (okhttp3.Response response = client.newCall(request).execute()) - { - return response.body().string(); - } - catch (Exception e) - { - Timber.e(e); - } - - return ""; + return client.getContent(tokenURI); } public NFTAsset fetchTokenMetadata(BigInteger tokenId) @@ -112,12 +97,13 @@ private static void setupClient() { if (client == null) { - client = new OkHttpClient.Builder() - .connectTimeout(C.CONNECT_TIMEOUT*4, TimeUnit.SECONDS) - .readTimeout(C.READ_TIMEOUT*4, TimeUnit.SECONDS) - .writeTimeout(C.WRITE_TIMEOUT, TimeUnit.SECONDS) - .retryOnConnectionFailure(true) - .build(); + client = new IPFSService( + new OkHttpClient.Builder() + .connectTimeout(C.CONNECT_TIMEOUT*2, TimeUnit.SECONDS) + .readTimeout(C.READ_TIMEOUT*2, TimeUnit.SECONDS) + .writeTimeout(C.WRITE_TIMEOUT*2, TimeUnit.SECONDS) + .retryOnConnectionFailure(false) + .build()); } } } diff --git a/app/src/main/java/com/alphawallet/app/entity/QueryResponse.java b/app/src/main/java/com/alphawallet/app/entity/QueryResponse.java new file mode 100644 index 0000000000..a232a2f2db --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/QueryResponse.java @@ -0,0 +1,23 @@ +package com.alphawallet.app.entity; + +/** + * Created by JB on 5/11/2022. + */ +public class QueryResponse +{ + public final int code; + public final String body; + + public QueryResponse(int code, String body) + { + this.code = code; + this.body = body; + } + + public boolean isSuccessful() + { + return code >= 200 && code <= 299; + } +} + + diff --git a/app/src/main/java/com/alphawallet/app/entity/tokenscript/TestScript.java b/app/src/main/java/com/alphawallet/app/entity/tokenscript/TestScript.java new file mode 100644 index 0000000000..ab104d6afc --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/tokenscript/TestScript.java @@ -0,0 +1,70 @@ +package com.alphawallet.app.entity.tokenscript; + +/** + * Created by JB on 6/11/2022. + */ +public abstract class TestScript +{ + public static String testScriptXXLF = " STL Office Token" + + " STL Office Tokens Boleto de admisión" + + " Boleto de admisiónes 入場券" + + " 入場券 " + + " 0xC3eeCa3Feb9Dbc06c6e749702AcB8d56A07BFb05 " + + " Unlock 开锁" + + " Abrir " + + " " + + " Lock 关锁" + + " Cerrar " + + " Mint Ape 1 " + + " " + + " Mint Ape 2 " + + " " + + " Mint STL Token" + + " " + + " " + + " "; +} 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 88e6099de9..d8349c6077 100644 --- a/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java +++ b/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java @@ -25,6 +25,7 @@ import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.ContractType; import com.alphawallet.app.entity.FragmentMessenger; +import com.alphawallet.app.entity.QueryResponse; import com.alphawallet.app.entity.TokenLocator; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.nftassets.NFTAsset; @@ -36,7 +37,6 @@ import com.alphawallet.app.entity.tokenscript.TokenscriptFunction; import com.alphawallet.app.repository.TokenLocalSource; import com.alphawallet.app.repository.TokensRealmSource; -import com.alphawallet.app.repository.TransactionRepositoryType; import com.alphawallet.app.repository.entity.RealmAuxData; import com.alphawallet.app.repository.entity.RealmCertificateData; import com.alphawallet.app.repository.entity.RealmTokenScriptData; @@ -112,8 +112,6 @@ import io.realm.Sort; import io.realm.exceptions.RealmException; import io.realm.exceptions.RealmPrimaryKeyConstraintException; -import okhttp3.OkHttpClient; -import okhttp3.Request; import timber.log.Timber; @@ -135,7 +133,7 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface private static final String EIP5169_KEY_OWNER = "Contract Owner"; //TODO Source this from the contract via owner() private final Context context; - private final OkHttpClient okHttpClient; + private final IPFSServiceType ipfsService; private final Map assetChecked; //Mapping of contract address to when they were last fetched from server private FileObserver fileObserver; //Observer which scans the override directory waiting for file change @@ -145,7 +143,6 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface private final TokensService tokensService; private final TokenLocalSource tokenLocalSource; private final AlphaWalletService alphaWalletService; - private final TransactionRepositoryType transactionRepository; private TokenDefinition cachedDefinition = null; private final ConcurrentHashMap eventList = new ConcurrentHashMap<>(); //List of events built during file load private final Semaphore assetLoadingLock; // used to block if someone calls getAssetDefinitionASync() while loading @@ -158,17 +155,16 @@ public class AssetDefinitionService implements ParseResult, AttributeInterface @Nullable private Disposable checkEventDisposable; - /* Designed with the assmuption that only a single instance of this class at any given time + /* Designed with the assumption that only a single instance of this class at any given time * ^^ The "service" part of AssetDefinitionService is the keyword here. * This is shorthand in the project to indicate this is a singleton that other classes inject. * This is the design pattern of the app. See class RepositoriesModule for constructors which are called at App init only */ - public AssetDefinitionService(OkHttpClient client, Context ctx, NotificationService svs, - RealmManager rm, TokensService tokensService, - TokenLocalSource trs, TransactionRepositoryType trt, - AlphaWalletService alphaService) + public AssetDefinitionService (IPFSServiceType ipfsSvs, Context ctx, NotificationService svs, + RealmManager rm, TokensService tokensService, + TokenLocalSource trs, AlphaWalletService alphaService) { context = ctx; - okHttpClient = client; + ipfsService = ipfsSvs; assetChecked = new ConcurrentHashMap<>(); notificationService = svs; realmManager = rm; @@ -178,7 +174,6 @@ public AssetDefinitionService(OkHttpClient client, Context ctx, NotificationServ { }; //no overridden functions tokenLocalSource = trs; - transactionRepository = trt; assetLoadingLock = new Semaphore(1); eventConnection = new Semaphore(1); //deleteAllEventData(); @@ -1052,64 +1047,52 @@ private Single fetchXMLFromServer(String address) }); } - private Pair downloadScript(String Uri, long currentFileTime) throws PackageManager.NameNotFoundException + private Pair downloadScript(String Uri, long currentFileTime) { - boolean isIPFS = false; - if (TextUtils.isEmpty(Uri)) return new Pair<>("", false); - SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH); - format.setTimeZone(TimeZone.getTimeZone("UTC")); - String dateFormat = format.format(new Date(currentFileTime)); - - //convert uri if using IPFS: - Uri = Utils.parseIPFS(Uri); - - //prepare Android headers - PackageManager manager = context.getPackageManager(); - PackageInfo info = manager.getPackageInfo( - context.getPackageName(), 0); - String appVersion = info.versionName; - String OSVersion = String.valueOf(Build.VERSION.RELEASE); - - Request.Builder bld = new Request.Builder() - .url(Uri) - .get(); - - if (!Uri.toLowerCase().contains("ipfs.io")) - { - bld.addHeader("Accept", "text/xml; charset=UTF-8") - .addHeader("X-Client-Name", "AlphaWallet") - .addHeader("X-Client-Version", appVersion) - .addHeader("X-Platform-Name", "Android") - .addHeader("X-Platform-Version", OSVersion) - .addHeader("If-Modified-Since", dateFormat); - } - else - { - isIPFS = true; - } + boolean isIPFS = Utils.isIPFS(Uri); - Request request = bld.build(); - - try (okhttp3.Response response = okHttpClient.newCall(request) - .execute()) + try { - switch (response.code()) + QueryResponse response = ipfsService.performIO(Uri, getHeaders(currentFileTime)); + switch (response.code) { default: case HttpURLConnection.HTTP_NOT_MODIFIED: break; case HttpURLConnection.HTTP_OK: - return new Pair<>(response.body().string(), isIPFS); + return new Pair<>(response.body, isIPFS); } } catch (Exception e) { - Timber.e(e); + Timber.w(e); } return new Pair<>("", false); } + private String[] getHeaders(long currentFileTime) throws PackageManager.NameNotFoundException + { + SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + String dateFormat = format.format(new Date(currentFileTime)); + + PackageManager manager = context.getPackageManager(); + PackageInfo info = manager.getPackageInfo( + context.getPackageName(), 0); + String appVersion = info.versionName; + String OSVersion = String.valueOf(Build.VERSION.RELEASE); + + return new String[] { + "Accept", "text/xml; charset=UTF-8", + "X-Client-Name", "AlphaWallet", + "X-Client-Version", appVersion, + "X-Platform-Name", "Android", + "X-Platform-Version", OSVersion, + "If-Modified-Since", dateFormat + }; + } + private boolean definitionIsOutOfDate(TokenDefinition td) { return td != null && !td.nameSpace.equals(TokenDefinition.TOKENSCRIPT_NAMESPACE); @@ -1477,8 +1460,8 @@ private void storeAuxData(String walletAddress, String databaseKey, BigInteger t } } - private void storeEventValue(String walletAddress, EventDefinition ev, EthLog.LogResult log, Attribute attr, - String selectVal) + private void storeEventValue (String walletAddress, EventDefinition ev, EthLog.LogResult log, Attribute attr, + String selectVal) { //store result BigInteger tokenId = EventUtils.getTokenId(ev, log); @@ -1895,7 +1878,8 @@ public String checkFunctionDenied(Token token, String actionName, List getAttributeResultsForTokenIds(Map> attrResults, List requiredAttributeNames, BigInteger tokenId) + private Map getAttributeResultsForTokenIds(Map> attrResults, List requiredAttributeNames, + BigInteger tokenId) { Map results = new HashMap<>(); if (!attrResults.containsKey(tokenId)) return results; //check values @@ -2708,4 +2692,4 @@ private void deleteAWRealm() }); } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/alphawallet/app/service/IPFSService.java b/app/src/main/java/com/alphawallet/app/service/IPFSService.java new file mode 100644 index 0000000000..b4cea7e0a6 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/service/IPFSService.java @@ -0,0 +1,131 @@ +package com.alphawallet.app.service; + +import android.text.TextUtils; + +import com.alphawallet.app.entity.QueryResponse; +import com.alphawallet.app.entity.tokenscript.TestScript; +import com.alphawallet.app.util.Utils; + +import java.io.IOException; +import java.net.SocketTimeoutException; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import timber.log.Timber; + +/** + * Created by JB on 3/11/2022. + */ +public class IPFSService implements IPFSServiceType +{ + private final OkHttpClient client; + + public IPFSService(OkHttpClient okHttpClient) + { + this.client = okHttpClient; + } + + public String getContent(String url) + { + try + { + QueryResponse response = performIO(url, null); + + if (response.isSuccessful()) + { + return response.body; + } + else + { + return ""; + } + } + catch (Exception e) + { + Timber.w(e); + return ""; + } + } + + public QueryResponse performIO(String url, String[] headers) throws IOException + { + if (!Utils.isValidUrl(url)) throw new IOException("URL not valid"); + + if (Utils.isIPFS(url)) //note that URL might contain IPFS, but not pass 'isValidUrl' + { + return getFromIPFS(url); + } + else + { + return get(url, headers); + } + } + + private QueryResponse get(String url, String[] headers) throws IOException + { + Request.Builder bld = new Request.Builder() + .url(url) + .get(); + + if (headers != null) addHeaders(bld, headers); + + Response response = client.newCall(bld.build()).execute(); + return new QueryResponse(response.code(), response.body().string()); + } + + private QueryResponse getFromIPFS(String url) throws IOException + { + if (isTestCode(url)) return loadTestCode(); + + //try Infura first + String tryIPFS = Utils.resolveIPFS(url, Utils.IPFS_IO_RESOLVER); + //attempt to load content + QueryResponse r; + try + { + r = get(tryIPFS, null); + } + catch (SocketTimeoutException e) + { + //timeout, try second node. Any other failure simply throw back to calling function + tryIPFS = Utils.resolveIPFS(url, Utils.IPFS_INFURA_RESOLVER); + r = get(tryIPFS, null); //if this throws it will be picked up by calling function + } + + return r; + } + + private void addHeaders(Request.Builder bld, String[] headers) throws IOException + { + if (headers.length % 2 != 0) + throw new IOException("Headers must be even value: [{name, value}, {...}]"); + + String name = null; + + for (String header : headers) + { + if (name == null) + { + name = header; + } + else + { + bld.addHeader(name, header); + name = null; + } + } + } + + //For testing + private boolean isTestCode(String url) + { + return (!TextUtils.isEmpty(url) && url.endsWith("QmXXLFBeSjXAwAhbo1344wJSjLgoUrfUK9LE57oVubaRRp")); + } + + private QueryResponse loadTestCode() + { + //restore the TokenScript for the certificate test + return new QueryResponse(200, TestScript.testScriptXXLF); + } +} diff --git a/app/src/main/java/com/alphawallet/app/service/IPFSServiceType.java b/app/src/main/java/com/alphawallet/app/service/IPFSServiceType.java new file mode 100644 index 0000000000..1e5ac9c281 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/service/IPFSServiceType.java @@ -0,0 +1,14 @@ +package com.alphawallet.app.service; + +import com.alphawallet.app.entity.QueryResponse; + +import java.io.IOException; + +/** + * Created by JB on 4/11/2022. + */ +public interface IPFSServiceType +{ + String getContent(String url); + QueryResponse performIO(String url, String[] headers) throws IOException; +} diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java index ce974a573f..8730490860 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java @@ -34,6 +34,7 @@ import com.alphawallet.app.repository.entity.RealmToken; import com.alphawallet.app.repository.entity.RealmTransaction; import com.alphawallet.app.repository.entity.RealmTransfer; +import com.alphawallet.app.util.Utils; import com.alphawallet.token.entity.ContractAddress; import com.google.gson.Gson; @@ -423,6 +424,11 @@ private EtherscanTransaction[] readTransactions(NetworkInfo networkInfo, TokensS fullUrl = sb.toString(); + if (!Utils.isValidUrl(fullUrl)) + { + return new EtherscanTransaction[0]; + } + Request request = new Request.Builder() .url(fullUrl) .get() @@ -617,8 +623,8 @@ private int calcTokenDecimals(EtherscanEvent ev0) return tokenDecimal; } - private void writeAssets(Map> eventMap, Token token, String walletAddress, - String contractAddress, TokensService svs, boolean newToken) + private void writeAssets (Map> eventMap, Token token, String walletAddress, + String contractAddress, TokensService svs, boolean newToken) { List additions = new ArrayList<>(); List removals = new ArrayList<>(); @@ -664,6 +670,11 @@ private String readNextTxBatch(String walletAddress, NetworkInfo networkInfo, lo "&page=1&offset=" + TRANSFER_RESULT_MAX + "&sort=asc" + getNetworkAPIToken(networkInfo); + if (!Utils.isValidUrl(fullUrl)) + { + return "0"; + } + Request request = new Request.Builder() .url(fullUrl) .header("User-Agent", "Chrome/74.0.3729.169") @@ -703,7 +714,7 @@ else if (networkInfo.chainId == POLYGON_ID || networkInfo.chainId == POLYGON_TES } else if (networkInfo.chainId == AURORA_MAINNET_ID || networkInfo.chainId == AURORA_TESTNET_ID) { - return AURORASCAN_API_KEY; + return AURORASCAN_API_KEY; } else { @@ -714,7 +725,8 @@ else if (networkInfo.chainId == AURORA_MAINNET_ID || networkInfo.chainId == AURO private EtherscanTransaction[] readCovalentTransactions(TokensService svs, String accountAddress, NetworkInfo networkInfo, boolean ascending, int page, int pageSize) throws JSONException { String covalent = "" + networkInfo.chainId + "/address/" + accountAddress.toLowerCase() + "/transactions_v2/?"; - String args = "block-signed-at-asc=" + (ascending ? "true" : "false") + "&page-number=" + (page - 1) + "&page-size=" + pageSize + "&key=" + keyProvider.getCovalentKey(); //read logs to get all the transfers + String args = "block-signed-at-asc=" + (ascending ? "true" : "false") + "&page-number=" + (page - 1) + "&page-size=" + + pageSize + "&key=" + keyProvider.getCovalentKey(); //read logs to get all the transfers String fullUrl = networkInfo.etherscanAPI.replace(COVALENT, covalent); String result = null; @@ -958,8 +970,8 @@ private void resetBlockRead(Realm r, long chainId, String walletAddress) } } - private void writeEvents(Realm instance, EtherscanEvent[] events, String walletAddress, - @NonNull NetworkInfo networkInfo, final boolean isNFT) throws Exception + private void writeEvents (Realm instance, EtherscanEvent[] events, String walletAddress, + @NonNull NetworkInfo networkInfo, final boolean isNFT) throws Exception { String TO_TOKEN = "[TO_ADDRESS]"; String FROM_TOKEN = "[FROM_ADDRESS]"; @@ -972,12 +984,14 @@ private void writeEvents(Realm instance, EtherscanEvent[] events, String walletA //write event list for (EtherscanEvent ev : events) { - boolean scanAsNFT = isNFT || ((ev.tokenDecimal == null || ev.tokenDecimal.length() == 0 || ev.tokenDecimal.equals("0")) && (ev.tokenID != null && ev.tokenID.length() > 0)); + boolean scanAsNFT = isNFT || ((ev.tokenDecimal == null || ev.tokenDecimal.length() == 0 || ev.tokenDecimal.equals("0")) && + (ev.tokenID != null && ev.tokenID.length() > 0)); Transaction tx = scanAsNFT ? ev.createNFTTransaction(networkInfo) : ev.createTransaction(networkInfo); //find tx name String activityName = tx.getEventName(walletAddress); - String valueList = VALUES.replace(TO_TOKEN, ev.to).replace(FROM_TOKEN, ev.from).replace(AMOUNT_TOKEN, scanAsNFT ? ev.tokenID : ev.value); //Etherscan sometimes interprets NFT transfers as FT's + //Etherscan sometimes interprets NFT transfers as FT's + String valueList = VALUES.replace(TO_TOKEN, ev.to).replace(FROM_TOKEN, ev.from).replace(AMOUNT_TOKEN, scanAsNFT ? ev.tokenID : ev.value); storeTransferData(r, tx.hash, valueList, activityName, ev.contractAddress); //ensure we have fetched the transaction for each hash writeTransaction(r, tx, ev.contractAddress, networkInfo.etherscanAPI.contains(COVALENT) ? null : txFetches); diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index 0faf60c106..7aa601cfaa 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -110,9 +110,10 @@ public static String formatUrl(String url) public static boolean isValidUrl(String url) { + if (TextUtils.isEmpty(url)) return false; Pattern p = Patterns.WEB_URL; Matcher m = p.matcher(url.toLowerCase()); - return m.matches(); + return m.matches() || isIPFS(url); } public static boolean isAlNum(String testStr) @@ -834,30 +835,35 @@ public static boolean isContractCall(Context context, String operationName) private static final String IPFS_PREFIX = "ipfs://"; private static final String IPFS_DESIGNATOR = "/ipfs/"; - private static final String IPFS_INFURA_RESOLVER = "https://alphawallet.infura-ipfs.io"; - private static final String IPFS_IO_RESOLVER = "https://ipfs.io"; + public static final String IPFS_INFURA_RESOLVER = "https://alphawallet.infura-ipfs.io"; + public static final String IPFS_IO_RESOLVER = "https://ipfs.io"; public static boolean isIPFS(String url) { - return url.contains(IPFS_DESIGNATOR) || url.startsWith(IPFS_PREFIX); + return url.contains(IPFS_DESIGNATOR) || url.startsWith(IPFS_PREFIX) || shouldBeIPFS(url); } public static String parseIPFS(String URL) + { + return resolveIPFS(URL, IPFS_INFURA_RESOLVER); + } + + public static String resolveIPFS(String URL, String resolver) { if (TextUtils.isEmpty(URL)) return URL; String parsed = URL; int ipfsIndex = URL.lastIndexOf(IPFS_DESIGNATOR); if (ipfsIndex >= 0) { - parsed = IPFS_INFURA_RESOLVER + URL.substring(ipfsIndex); + parsed = resolver + URL.substring(ipfsIndex); } else if (URL.startsWith(IPFS_PREFIX)) { - parsed = IPFS_INFURA_RESOLVER + IPFS_DESIGNATOR + URL.substring(IPFS_PREFIX.length()); + parsed = resolver + IPFS_DESIGNATOR + URL.substring(IPFS_PREFIX.length()); } else if (shouldBeIPFS(URL)) //have seen some NFTs designating only the IPFS hash { - parsed = IPFS_INFURA_RESOLVER + IPFS_DESIGNATOR + URL; + parsed = resolver + IPFS_DESIGNATOR + URL; } return parsed; diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java b/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java index 98f41bd8e4..5f1cf9ed50 100644 --- a/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/NameHash.java @@ -12,6 +12,7 @@ */ package com.alphawallet.app.web3j.ens; +import android.text.TextUtils; import org.web3j.crypto.Hash; import org.web3j.utils.Numeric; @@ -76,9 +77,13 @@ private static byte[] nameHash(String[] labels) */ public static String normalise(String ensName) { + if (TextUtils.isEmpty(ensName)) + { + return ""; + } try { - return IDN.toASCII(ensName, IDN.USE_STD3_ASCII_RULES).toLowerCase(Locale.ROOT); //java.lang.NullPointerException: Attempt to invoke virtual method 'char[] java.lang.String.toCharArray()' on a null object reference + return IDN.toASCII(ensName, IDN.USE_STD3_ASCII_RULES).toLowerCase(Locale.ROOT); } catch (Exception e) { @@ -110,6 +115,10 @@ public static String dnsEncode(String name) throws IOException ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); for (String part : parts) { + if (TextUtils.isEmpty(part)) + { + break; + } byte[] bytes = toUtf8Bytes("_" + normalise(part)); if (bytes == null) { diff --git a/app/src/test/java/com/alphawallet/app/IPFSServiceTest.java b/app/src/test/java/com/alphawallet/app/IPFSServiceTest.java new file mode 100644 index 0000000000..8a6de2e391 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/IPFSServiceTest.java @@ -0,0 +1,68 @@ +package com.alphawallet.app; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import com.alphawallet.app.entity.QueryResponse; +import com.alphawallet.app.service.IPFSService; +import com.alphawallet.app.service.IPFSServiceType; + +import org.junit.Test; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; + +/** + * Created by JB on 6/11/2022. + */ +public class IPFSServiceTest +{ + private final IPFSServiceType ipfsService; + + public IPFSServiceTest() + { + ipfsService = new IPFSService( + new OkHttpClient.Builder() + .connectTimeout(C.CONNECT_TIMEOUT*2, TimeUnit.SECONDS) + .readTimeout(C.READ_TIMEOUT*2, TimeUnit.SECONDS) + .writeTimeout(C.WRITE_TIMEOUT*2, TimeUnit.SECONDS) + .retryOnConnectionFailure(false) + .build()); + } + + //there seems to be issues with resolving IPFS files on the test machine, + //so it's best to have unit tests which don't require to resolve the connection + + @Test + public void testUrls() throws Exception + { + //test custom route use for testing in various ways (to test we're resolving IPFS in all currently seen ways) + + String resp = ipfsService.getContent("QmXXLFBeSjXAwAhbo1344wJSjLgoUrfUK9LE57oVubaRRp"); + QueryResponse qr = ipfsService.performIO("ipfs://QmXXLFBeSjXAwAhbo1344wJSjLgoUrfUK9LE57oVubaRRp", null); + + assertFalse(TextUtils.isEmpty(qr.body)); //check test is not returning a false positive + assertEquals(qr.body, resp); + assertTrue(qr.isSuccessful()); + + assertThrows( + IOException.class, + () -> ipfsService.performIO("", null)); + + //Bad IFPS link, should fail + assertThrows(IOException.class, + () -> ipfsService.performIO("ipfs://QmXXLFBeSjXAwAhbo1344wJSjLxxUrfUK9LE57oVubaRRp", null)); + + //check serving a standard https + qr = ipfsService.performIO("https://www.timeanddate.com/", null); + + assertFalse(TextUtils.isEmpty(qr.body)); + assertTrue(qr.isSuccessful()); + + //TODO: Check update; pass an out of date header to TS repo endpoint + } +} From 65cd17654528851e50ee7a1ca4497fb96050ae31 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 8 Nov 2022 14:37:26 +0800 Subject: [PATCH 137/183] 2864 refactor dappbrowser url bar to widget (#2881) * Add Dapp browser e2e test * Refactor * Wait WebView loading complete --- .../java/com/alphawallet/app/BaseE2ETest.java | 18 +- .../com/alphawallet/app/DappBrowserTest.java | 120 ++++- .../alphawallet/app/assertions/Should.java | 5 + .../java/com/alphawallet/app/steps/Steps.java | 7 + .../java/com/alphawallet/app/util/Helper.java | 50 ++ .../app/ui/DappBrowserFragment.java | 484 +++--------------- .../alphawallet/app/widget/AddressBar.java | 338 ++++++++++++ .../app/widget/AddressBarListener.java | 11 + app/src/main/res/layout/fragment_webview.xml | 11 +- 9 files changed, 620 insertions(+), 424 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/widget/AddressBar.java create mode 100644 app/src/main/java/com/alphawallet/app/widget/AddressBarListener.java diff --git a/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java b/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java index 13f7084cb0..7da0085ce6 100644 --- a/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java +++ b/app/src/androidTest/java/com/alphawallet/app/BaseE2ETest.java @@ -3,12 +3,10 @@ import static androidx.test.espresso.Espresso.setFailureHandler; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; - import static com.alphawallet.app.steps.Steps.closeSecurityWarning; import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObject; import androidx.test.uiautomator.UiObjectNotFoundException; @@ -18,13 +16,14 @@ import com.alphawallet.app.util.CustomFailureHandler; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.junit.runner.RunWith; +import timber.log.Timber; + @RunWith(AndroidJUnit4.class) public abstract class BaseE2ETest { @@ -42,19 +41,26 @@ protected void starting(Description description) = new ActivityScenarioRule<>(SplashActivity.class); @Before - public void setUp() throws UiObjectNotFoundException + public void setUp() { dismissANRSystemDialog(); closeSecurityWarning(); } - private void dismissANRSystemDialog() throws UiObjectNotFoundException + private void dismissANRSystemDialog() { UiDevice device = UiDevice.getInstance(getInstrumentation()); UiObject waitButton = device.findObject(new UiSelector().textContains("wait")); if (waitButton.exists()) { - waitButton.click(); + try + { + waitButton.click(); + } + catch (UiObjectNotFoundException e) + { + Timber.e(e); + } } } } diff --git a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java index 7ad0a0c9e3..82af16a667 100644 --- a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java @@ -1,32 +1,138 @@ package com.alphawallet.app; +import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.Espresso.pressBack; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.pressImeActionButton; +import static androidx.test.espresso.action.ViewActions.pressKey; +import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.alphawallet.app.assertions.Should.shouldNotSee; import static com.alphawallet.app.assertions.Should.shouldSee; import static com.alphawallet.app.steps.Steps.createNewWallet; import static com.alphawallet.app.steps.Steps.navigateToBrowser; +import static com.alphawallet.app.steps.Steps.openOptionsMenu; import static com.alphawallet.app.steps.Steps.selectTestNet; -import static com.alphawallet.app.steps.Steps.visit; +import static com.alphawallet.app.util.Helper.click; +import static com.alphawallet.app.util.Helper.waitUntilLoaded; +import static junit.framework.TestCase.assertTrue; + +import static org.hamcrest.core.IsNot.not; + +import android.view.KeyEvent; + +import androidx.annotation.NonNull; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.espresso.action.ViewActions; import com.alphawallet.app.util.Helper; +import org.junit.Before; import org.junit.Test; public class DappBrowserTest extends BaseE2ETest { + private static final String DEFAULT_HOME_PAGE = "https://alphawallet.com/browser/"; + private static final String URL_DAPP = "https://app.1inch.io/"; + + @Override + @Before + public void setUp() + { + super.setUp(); + createNewWallet(); + visit(DEFAULT_HOME_PAGE); + } @Test public void should_switch_network() { - String urlString = "https://opensea.io"; - - createNewWallet(); - visit(urlString); shouldSee("Ethereum"); - Helper.wait(5); + waitUntilLoaded(); selectTestNet("Görli"); navigateToBrowser(); - Helper.wait(3); + waitUntilLoaded(); pressBack(); shouldSee("Görli"); } + + @Test + public void should_suggest_websites() + { + onView(withId(R.id.url_tv)).perform(click()); + click(withId(R.id.clear_url)); + onView(withId(R.id.url_tv)).perform(pressKey(KeyEvent.KEYCODE_R), pressKey(KeyEvent.KEYCODE_A)); + Helper.wait(2); + onView(withId(R.id.url_tv)).perform(pressKey(KeyEvent.KEYCODE_TAB), pressKey(KeyEvent.KEYCODE_DPAD_DOWN)); + waitUntilLoaded(); + onView(withId(R.id.url_tv)).perform(pressKey(KeyEvent.KEYCODE_ENTER)); + assertUrlContains("alphawallet.app.entity.DApp@"); + } + + @Test + public void should_navigate_forward_or_backward() + { + visit(URL_DAPP); + assertUrlContains(URL_DAPP); + Helper.wait(2); + click(withId(R.id.back)); + waitUntilLoaded(); + assertUrlContains(DEFAULT_HOME_PAGE); + Helper.wait(2); + click(withId(R.id.next)); + waitUntilLoaded(); + assertUrlContains(URL_DAPP); + } + + @Test + public void should_clear_url_and_show_keyboard() + { + assertUrlContains(DEFAULT_HOME_PAGE); + onView(withId(R.id.url_tv)).perform(click()); + click(withId(R.id.clear_url)); + assertUrlContains(""); + assertTrue(Helper.isSoftKeyboardShown(ApplicationProvider.getApplicationContext())); + } + + @Test + public void should_hide_buttons_when_typing_url() + { + shouldSee(R.id.back); + shouldSee(R.id.next); + + onView(withId(R.id.url_tv)).perform(ViewActions.click()); + + shouldNotSee(R.id.back); + shouldNotSee(R.id.next); + } + + @Test + public void should_set_homepage() + { + visit(URL_DAPP); + waitUntilLoaded(); + openOptionsMenu(); + click(withText("Set as Home Page")); + Helper.wait(2); + click(withId(R.id.home)); + waitUntilLoaded(); + assertUrlContains(URL_DAPP); + } + + @NonNull + private void visit(String url) + { + navigateToBrowser(); + onView(withId(R.id.url_tv)).perform(replaceText(url), pressImeActionButton()); + waitUntilLoaded(); + } + + @NonNull + private void assertUrlContains(String expectedUrl) + { + onView(withId(R.id.url_tv)).check(matches(withSubstring(expectedUrl))); + } } diff --git a/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java b/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java index ac965d7de9..643175c8e9 100644 --- a/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java +++ b/app/src/androidTest/java/com/alphawallet/app/assertions/Should.java @@ -30,6 +30,11 @@ public static void shouldNotSee(String text) onView(isRoot()).perform(waitUntil(not(withSubstring(text)), TIMEOUT_IN_SECONDS)); } + public static void shouldNotSee(int id) + { + onView(isRoot()).perform(waitUntil(not(withId(id)), TIMEOUT_IN_SECONDS)); + } + public static void shouldSee(int id) { onView(isRoot()).perform(waitUntil(withId(id), 10 * 60)); diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index 1b1a3a40fd..e5b8f15f0b 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -1,6 +1,7 @@ package com.alphawallet.app.steps; import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu; import static androidx.test.espresso.Espresso.pressBack; import static androidx.test.espresso.action.ViewActions.pressImeActionButton; import static androidx.test.espresso.action.ViewActions.replaceText; @@ -23,6 +24,7 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.core.StringStartsWith.startsWith; +import androidx.test.core.app.ApplicationProvider; import androidx.test.espresso.ViewInteraction; import androidx.test.espresso.action.ViewActions; @@ -270,4 +272,9 @@ public static void selectCurrency(String currency) Helper.wait(1); pressBack(); } + + public static void openOptionsMenu() + { + openActionBarOverflowOrOptionsMenu(ApplicationProvider.getApplicationContext()); + } } diff --git a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java index 952e194a39..5a88e835f1 100644 --- a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java +++ b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java @@ -1,5 +1,6 @@ package com.alphawallet.app.util; +import static android.content.Context.INPUT_METHOD_SERVICE; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.RootMatchers.isDialog; @@ -10,8 +11,10 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.core.AllOf.allOf; +import android.content.Context; import android.view.KeyEvent; import android.view.View; +import android.view.inputmethod.InputMethodManager; import androidx.test.espresso.PerformException; import androidx.test.espresso.UiController; @@ -21,6 +24,8 @@ import androidx.test.espresso.util.HumanReadables; import androidx.test.espresso.util.TreeIterables; +import com.alphawallet.app.R; + import org.hamcrest.Matcher; import org.hamcrest.Matchers; @@ -218,4 +223,49 @@ private static void waitUntilShown(String title) } } } + + public static boolean isSoftKeyboardShown(Context context) + { + InputMethodManager imm = + (InputMethodManager) context.getSystemService(INPUT_METHOD_SERVICE); + return imm.isAcceptingText(); + } + + public static void waitUntilLoaded() + { + waitStart(); + waitComplete(); + } + + private static void waitComplete() + { + for (int i = 0; i < DEFAULT_TIMEOUT_IN_SECONDS; i++) + { + try + { + onView(withId(R.id.progressBar)).check(matches(not(isDisplayed()))); + break; + } + catch (Error | Exception e) + { + Helper.wait(1); + } + } + } + + private static void waitStart() + { + for (int i = 0; i < DEFAULT_TIMEOUT_IN_SECONDS; i++) + { + try + { + onView(withId(R.id.progressBar)).check(matches(isDisplayed())); + break; + } + catch (Error | Exception e) + { + Helper.wait(1); + } + } + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index a30e69998c..e0d07b82b4 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -2,21 +2,17 @@ import static com.alphawallet.app.C.ETHER_DECIMALS; import static com.alphawallet.app.C.RESET_TOOLBAR; -import static com.alphawallet.app.entity.CryptoFunctions.sigFromByteArray; import static com.alphawallet.app.entity.Operation.SIGN_DATA; import static com.alphawallet.app.entity.tokens.Token.TOKEN_BALANCE_PRECISION; import static com.alphawallet.app.ui.HomeActivity.RESET_TOKEN_SERVICE; import static com.alphawallet.app.ui.MyAddressActivity.KEY_ADDRESS; -import static com.alphawallet.app.util.KeyboardUtils.showKeyboard; import static com.alphawallet.app.util.Utils.isValidUrl; import static com.alphawallet.app.widget.AWalletAlertDialog.ERROR; import static com.alphawallet.app.widget.AWalletAlertDialog.WARNING; import static org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction; import android.Manifest; -import android.animation.Animator; import android.animation.LayoutTransition; -import android.animation.ValueAnimator; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ClipData; @@ -29,15 +25,12 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import android.text.Editable; import android.text.TextUtils; -import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; import android.webkit.ConsoleMessage; import android.webkit.GeolocationPermissions; import android.webkit.PermissionRequest; @@ -47,7 +40,6 @@ import android.webkit.WebHistoryItem; import android.webkit.WebView; import android.webkit.WebViewClient; -import android.widget.AutoCompleteTextView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; @@ -91,14 +83,12 @@ import com.alphawallet.app.service.WalletConnectService; import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.widget.OnDappHomeNavClickListener; -import com.alphawallet.app.ui.widget.adapter.DappBrowserSuggestionsAdapter; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.ui.widget.entity.DappBrowserSwipeInterface; import com.alphawallet.app.ui.widget.entity.DappBrowserSwipeLayout; import com.alphawallet.app.ui.widget.entity.ItemClickListener; import com.alphawallet.app.util.BalanceUtils; import com.alphawallet.app.util.DappBrowserUtils; -import com.alphawallet.app.util.KeyboardUtils; import com.alphawallet.app.util.LocaleUtils; import com.alphawallet.app.util.QRParser; import com.alphawallet.app.util.Utils; @@ -117,6 +107,8 @@ import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.ActionSheetDialog; +import com.alphawallet.app.widget.AddressBar; +import com.alphawallet.app.widget.AddressBarListener; import com.alphawallet.app.widget.TestNetDialog; import com.alphawallet.token.entity.EthereumMessage; import com.alphawallet.token.entity.EthereumTypedMessage; @@ -128,8 +120,6 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import org.web3j.crypto.Keys; -import org.web3j.crypto.Sign; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.methods.response.EthCall; @@ -142,14 +132,10 @@ import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; -import java.security.SignatureException; -import java.util.concurrent.TimeUnit; import dagger.hilt.android.AndroidEntryPoint; -import io.reactivex.Observable; import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import io.realm.Realm; import io.realm.RealmResults; @@ -159,7 +145,8 @@ public class DappBrowserFragment extends BaseFragment implements OnSignTransactionListener, OnSignPersonalMessageListener, OnSignTypedMessageListener, OnSignMessageListener, OnEthCallListener, OnWalletAddEthereumChainObjectListener, OnWalletActionListener, URLLoadInterface, ItemClickListener, OnDappHomeNavClickListener, DappBrowserSwipeInterface, - SignAuthenticationCallback, ActionSheetCallback, TestNetDialog.TestNetDialogCallback { + SignAuthenticationCallback, ActionSheetCallback, TestNetDialog.TestNetDialogCallback +{ public static final String SEARCH = "SEARCH"; public static final String PERSONAL_MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n"; public static final String CURRENT_FRAGMENT = "currentFragment"; @@ -181,11 +168,11 @@ public class DappBrowserFragment extends BaseFragment implements OnSignTransacti /** * Below object is used to set Animation duration for expand/collapse and rotate */ - private final int ANIMATION_DURATION = 100; private final Handler handler = new Handler(Looper.getMainLooper()); private ValueCallback uploadMessage; ActivityResultLauncher getContent = registerForActivityResult(new ActivityResultContracts.GetContent(), - new ActivityResultCallback() { + new ActivityResultCallback() + { @Override public void onActivityResult(Uri uri) { @@ -201,25 +188,21 @@ public void onActivityResult(Uri uri) private DappBrowserViewModel viewModel; private DappBrowserSwipeLayout swipeRefreshLayout; private Web3View web3; - private AutoCompleteTextView urlTv; private ProgressBar progressBar; private Wallet wallet; private NetworkInfo activeNetwork; private AWalletAlertDialog chainSwapDialog; private AWalletAlertDialog resultDialog; - private DappBrowserSuggestionsAdapter adapter; private String loadOnInit; //Web3 needs to be fully set up and initialised before any dapp loading can be done private boolean homePressed; private AddEthereumChainPrompt addCustomChainDialog; private Toolbar toolbar; - private ImageView back; - private ImageView next; - private ImageView clear; private ImageView refresh; private FrameLayout webFrame; private TextView balance; private TextView symbol; - private View layoutNavigation; + private AddressBar addressBar; + // Handle resizing the browser view when the soft keyboard pops up and goes. // The issue this fixes is where you need to enter data at the bottom of the webpage, // and the keyboard hides the input field @@ -252,7 +235,8 @@ else if (heightDifference == 0 && layoutParams.bottomMargin != navBarHeight) //go back into full screen mode, and expand URL bar out layoutParams.bottomMargin = 0; webFrame.setLayoutParams(layoutParams); - shrinkSearchBar(); + toolbar.getMenu().setGroupVisible(R.id.dapp_browser_menu, true); + addressBar.shrinkSearchBar(); } return insets; @@ -261,7 +245,6 @@ else if (heightDifference == 0 && layoutParams.bottomMargin != navBarHeight) private PermissionRequest requestCallback = null; private String geoOrigin; private String walletConnectSession; - private boolean focusFlag; private String currentWebpageTitle; private String currentFragment; ActivityResultLauncher getNetwork = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), @@ -284,15 +267,12 @@ else if (heightDifference == 0 && layoutParams.bottomMargin != navBarHeight) // This thread stays in operation until a new page load is complete. private String loadUrlAfterReload; private DAppFunction dAppFunction; - @Nullable - private Disposable disposable; @Override public void onCreate(@Nullable Bundle savedInstanceState) { LocaleUtils.setActiveLocale(getContext()); super.onCreate(savedInstanceState); - focusFlag = false; getChildFragmentManager() .setFragmentResultListener(DAPP_CLICK, this, (requestKey, bundle) -> { @@ -305,7 +285,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) } else if (removedDapp != null) { - adapter.removeSuggestion(removedDapp); + addressBar.removeSuggestion(removedDapp); } }); } @@ -341,7 +321,37 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c View view = inflater.inflate(webViewID, container, false); initViewModel(); initView(view); - setupAddressBar(); + + addressBar.setup(viewModel.getDappsMasterList(getContext()), new AddressBarListener() + { + @Override + public boolean onLoad(String urlText) + { + addToBackStack(DAPP_BROWSER); + boolean handled = loadUrl(urlText); + detachFragments(); + cancelSearchSession(); + return handled; + } + + @Override + public void onClear() + { + cancelSearchSession(); + } + + @Override + public void loadNext() + { + goToNextPage(); + } + + @Override + public void loadPrevious() + { + backPressed(); + } + }); attachFragment(DAPP_BROWSER); @@ -386,7 +396,7 @@ private void showFragment(Fragment fragment, String tag) .add(R.id.frame, fragment, tag) .commit(); - setBackForwardButtons(); + addressBar.updateNavigationButtons(web3.copyBackForwardList()); } private void detachFragments() @@ -402,15 +412,13 @@ private void homePressed() homePressed = true; detachFragments(); currentFragment = DAPP_BROWSER; - if (urlTv != null) - urlTv.getText().clear(); + addressBar.clear(); if (web3 != null) { resetDappBrowser(); } - //blank forward / backward arrows - setBackForwardButtons(); + addressBar.updateNavigationButtons(web3.copyBackForwardList()); } @Override @@ -426,7 +434,7 @@ public void onDestroy() super.onDestroy(); viewModel.onDestroy(); stopBalanceListener(); - if (disposable != null && !disposable.isDisposed()) disposable.dispose(); + addressBar.destroy(); } private void setupMenu(@NotNull View baseView) @@ -462,7 +470,7 @@ private void setupMenu(@NotNull View baseView) return true; }); if (add != null) add.setOnMenuItemClickListener(menuItem -> { - viewModel.addToMyDapps(getContext(), currentWebpageTitle, urlTv.getText().toString()); + viewModel.addToMyDapps(getContext(), currentWebpageTitle, addressBar.getUrl()); return true; }); if (history != null) history.setOnMenuItemClickListener(menuItem -> { @@ -491,7 +499,7 @@ private void setupMenu(@NotNull View baseView) if (setAsHomePage != null) { setAsHomePage.setOnMenuItemClickListener(menuItem -> { - viewModel.setHomePage(getContext(), urlTv.getText().toString()); + viewModel.setHomePage(getContext(), addressBar.getUrl()); return true; }); } @@ -509,7 +517,6 @@ private void updateNetworkMenuItem() private void initView(@NotNull View view) { web3 = view.findViewById(R.id.web3view); - urlTv = view.findViewById(R.id.url_tv); Bundle savedState = readBundleFromLocal(); if (savedState != null) { @@ -522,14 +529,13 @@ private void initView(@NotNull View view) loadOnInit = getDefaultDappUrl(); } + addressBar = view.findViewById(R.id.address_bar_widget); progressBar = view.findViewById(R.id.progressBar); - urlTv = view.findViewById(R.id.url_tv); webFrame = view.findViewById(R.id.frame); swipeRefreshLayout = view.findViewById(R.id.swipe_refresh); swipeRefreshLayout.setRefreshInterface(this); toolbar = view.findViewById(R.id.address_bar); - layoutNavigation = view.findViewById(R.id.layout_navigator); View home = view.findViewById(R.id.home); if (home != null) home.setOnClickListener(v -> homePressed()); @@ -555,17 +561,6 @@ else if (getDefaultDappUrl() != null) refresh.setOnClickListener(v -> reloadPage()); } - back = view.findViewById(R.id.back); - back.setOnClickListener(v -> backPressed()); - - next = view.findViewById(R.id.next); - next.setOnClickListener(v -> goToNextPage()); - - clear = view.findViewById(R.id.clear_url); - clear.setOnClickListener(v -> { - clearAddressBar(); - }); - balance = view.findViewById(R.id.balance); symbol = view.findViewById(R.id.symbol); web3.setWebLoadCallback(this); @@ -597,81 +592,6 @@ private void openNetworkSelection() getNetwork.launch(intent); } - private void clearAddressBar() - { - if (urlTv.getText().toString().isEmpty()) - { - cancelSearchSession(); - } - else - { - urlTv.getText().clear(); - openURLInputView(); - KeyboardUtils.showKeyboard(urlTv); //ensure keyboard shows here so we can listen for it being cancelled - } - } - - private void setupAddressBar() - { - adapter = new DappBrowserSuggestionsAdapter( - requireContext(), - viewModel.getDappsMasterList(getContext()), - this::onItemClick - ); - urlTv.setAdapter(null); - - urlTv.setOnEditorActionListener((v, actionId, event) -> { - boolean handled = false; - if (actionId == EditorInfo.IME_ACTION_GO) - { - String urlText = urlTv.getText().toString(); - handled = loadUrl(urlText); - detachFragments(); - cancelSearchSession(); - } - return handled; - }); - - // Both these are required, the onFocus listener is required to respond to the first click. - urlTv.setOnFocusChangeListener((v, hasFocus) -> { - //see if we have focus flag - loadOnInit = null; - loadUrlAfterReload = null; - if (hasFocus && focusFlag && getActivity() != null) openURLInputView(); - }); - - urlTv.setOnClickListener(v -> { - openURLInputView(); - }); - - urlTv.setShowSoftInputOnFocus(true); - - urlTv.setOnLongClickListener(v -> { - urlTv.dismissDropDown(); - return false; - }); - - urlTv.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) - { - - } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) - { - - } - - @Override - public void afterTextChanged(Editable editable) - { - adapter.setHighlighted(editable.toString()); - } - }); - } - @Override public void comeIntoFocus() { @@ -688,121 +608,21 @@ public void comeIntoFocus() viewModel.updateGasPrice(activeNetwork.chainId); } } - if (urlTv != null) - { - urlTv.clearFocus(); - KeyboardUtils.hideKeyboard(urlTv); - } - focusFlag = true; + addressBar.leaveEditMode(); } @Override public void leaveFocus() { - focusFlag = false; if (web3 != null) web3.requestFocus(); - if (urlTv != null) urlTv.clearFocus(); + addressBar.leaveFocus(); if (viewModel != null) viewModel.stopBalanceUpdate(); stopBalanceListener(); } - // TODO: Move all nav stuff to widget - private void openURLInputView() - { - urlTv.setAdapter(null); - expandCollapseView(layoutNavigation, false); - - disposable = Observable.zip( - Observable.interval(600, TimeUnit.MILLISECONDS).take(1), - Observable.fromArray(clear), (interval, item) -> item) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(AndroidSchedulers.mainThread()) - .subscribe(this::postBeginSearchSession); - } - - private void postBeginSearchSession(@NotNull ImageView item) - { - urlTv.setAdapter(adapter); - urlTv.showDropDown(); - if (item.getVisibility() == View.GONE) - { - expandCollapseView(item, true); - showKeyboard(urlTv); - } - } - /** * Used to expand or collapse the view */ - private synchronized void expandCollapseView(@NotNull View view, boolean expandView) - { - //detect if view is expanded or collapsed - boolean isViewExpanded = view.getVisibility() == View.VISIBLE; - - //Collapse view - if (isViewExpanded && !expandView) - { - int finalWidth = view.getWidth(); - ValueAnimator valueAnimator = slideAnimator(finalWidth, 0, view); - valueAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) - { - - } - - @Override - public void onAnimationEnd(Animator animator) - { - view.setVisibility(View.GONE); - } - - @Override - public void onAnimationCancel(Animator animator) - { - - } - - @Override - public void onAnimationRepeat(Animator animator) - { - - } - }); - valueAnimator.start(); - } - //Expand view - else if (!isViewExpanded && expandView) - { - view.setVisibility(View.VISIBLE); - - int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); - int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); - - view.measure(widthSpec, heightSpec); - int width = view.getMeasuredWidth(); - ValueAnimator valueAnimator = slideAnimator(0, width, view); - valueAnimator.start(); - } - } - - @NotNull - private ValueAnimator slideAnimator(int start, int end, final View view) - { - - final ValueAnimator animator = ValueAnimator.ofInt(start, end); - - animator.addUpdateListener(valueAnimator -> { - // Update Height - int value = (Integer) valueAnimator.getAnimatedValue(); - - ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); - layoutParams.width = value; - view.setLayoutParams(layoutParams); - }); - animator.setDuration(ANIMATION_DURATION); - return animator; - } private void addToBackStack(String nextFragment) { @@ -821,19 +641,7 @@ private void addToForwardStack(String prevFragment) private void cancelSearchSession() { detachFragment(SEARCH); - KeyboardUtils.hideKeyboard(urlTv); - setBackForwardButtons(); - } - - private void shrinkSearchBar() - { - if (toolbar != null) - { - toolbar.getMenu().setGroupVisible(R.id.dapp_browser_menu, true); - expandCollapseView(layoutNavigation, true); - clear.setVisibility(View.GONE); - urlTv.dismissDropDown(); - } + addressBar.updateNavigationButtons(web3.copyBackForwardList()); } private void detachFragment(String tag) @@ -937,7 +745,7 @@ private void onNetworkChanged(NetworkInfo networkInfo) updateNetworkMenuItem(); } - if (networkChanged && isOnHomePage()) + if (networkChanged && addressBar.isOnHomePage()) resetDappBrowser(); //trigger a reset if on homepage updateFilters(networkInfo); @@ -1003,7 +811,8 @@ private void setupWeb3() web3.setRpcUrl(viewModel.getNetworkNodeRPC(activeNetwork.chainId)); web3.setWalletAddress(new Address(wallet.address)); - web3.setWebChromeClient(new WebChromeClient() { + web3.setWebChromeClient(new WebChromeClient() + { @Override public void onProgressChanged(WebView webview, int newProgress) { @@ -1073,7 +882,8 @@ public boolean onShowFileChooser(WebView webView, ValueCallback filePathC } }); - web3.setWebViewClient(new WebViewClient() { + web3.setWebViewClient(new WebViewClient() + { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { @@ -1144,13 +954,8 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) private void setUrlText(String newUrl) { - if (urlTv == null) - { - if (getView() == null) return; //unable to get view at this time - urlTv = getView().findViewById(R.id.url_tv); - } - urlTv.setText(newUrl); - setBackForwardButtons(); + addressBar.setUrl(newUrl); + addressBar.updateNavigationButtons(web3.copyBackForwardList()); } private void loadNewNetwork(long newNetworkId) @@ -1213,13 +1018,13 @@ public void onSignTypedMessage(@NotNull EthereumTypedMessage message) public void onEthCall(Web3Call call) { Single.fromCallable(() -> { - //let's make the call - Web3j web3j = TokenRepository.getWeb3jService(activeNetwork.chainId); - //construct call - org.web3j.protocol.core.methods.request.Transaction transaction - = createFunctionCallTransaction(wallet.address, null, null, call.gasLimit, call.to.toString(), call.value, call.payload); - return web3j.ethCall(transaction, call.blockParam).send(); - }).map(EthCall::getValue) + //let's make the call + Web3j web3j = TokenRepository.getWeb3jService(activeNetwork.chainId); + //construct call + org.web3j.protocol.core.methods.request.Transaction transaction + = createFunctionCallTransaction(wallet.address, null, null, call.gasLimit, call.to.toString(), call.value, call.payload); + return web3j.ethCall(transaction, call.blockParam).send(); + }).map(EthCall::getValue) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> web3.onCallFunctionSuccessful(call.leafPosition, result), @@ -1345,7 +1150,8 @@ private void showChainChangeDialog(long callbackId, NetworkInfo newNetwork) private void handleSignMessage(Signable message) { - dAppFunction = new DAppFunction() { + dAppFunction = new DAppFunction() + { @Override public void DAppError(Throwable error, Signable message) { @@ -1511,15 +1317,12 @@ else if (transaction.payload == null && transaction.value == null) @Override public void backPressed() { - if (web3 == null || back == null || back.getAlpha() == 0.3f) return; if (!currentFragment.equals(DAPP_BROWSER)) { detachFragment(currentFragment); - checkBackClickArrowVisibility(); } else if (web3.canGoBack()) { - checkBackClickArrowVisibility(); //to make arrows function correctly - don't want to wait for web page to load to check back/forwards - this looks clunky loadSessionUrl(-1); web3.goBack(); detachFragments(); @@ -1531,68 +1334,20 @@ else if (!web3.getUrl().equalsIgnoreCase(getDefaultDappUrl())) web3.resetView(); web3.loadUrl(getDefaultDappUrl()); setUrlText(getDefaultDappUrl()); - checkBackClickArrowVisibility(); - } - else - { - checkBackClickArrowVisibility(); } + addressBar.updateNavigationButtons(web3.copyBackForwardList()); } private void goToNextPage() { - if (next.getAlpha() == 0.3f) return; if (web3.canGoForward()) { - checkForwardClickArrowVisibility(); loadSessionUrl(1); web3.goForward(); + addressBar.updateNavigationButtons(web3.copyBackForwardList()); } } - /** - * Check if this is the last web item and the last fragment item. - */ - private void checkBackClickArrowVisibility() - { - //will this be last item? - WebBackForwardList sessionHistory = web3.copyBackForwardList(); - int nextIndex = sessionHistory.getCurrentIndex() - 1; - - String nextUrl; - - if (nextIndex >= 0) - { - WebHistoryItem newItem = sessionHistory.getItemAtIndex(nextIndex); - nextUrl = newItem.getUrl(); - } - else - { - nextUrl = urlTv.getText().toString(); - } - - if (nextUrl.equalsIgnoreCase(getDefaultDappUrl())) - { - back.setAlpha(0.3f); - } - else - { - back.setAlpha(1.0f); - } - } - - /** - * After a forward click while web browser active, check if forward and back arrows should be updated. - * Note that the web item only becomes history after the next page is loaded, so if the next item is new, then - */ - private void checkForwardClickArrowVisibility() - { - WebBackForwardList sessionHistory = web3.copyBackForwardList(); - int nextIndex = sessionHistory.getCurrentIndex() + 1; - if (nextIndex >= sessionHistory.getSize() - 1) next.setAlpha(0.3f); - else next.setAlpha(1.0f); - } - /** * Browse to relative entry with sanity check on value * @@ -1629,19 +1384,19 @@ public void onWebpageLoaded(String url, String title) { DApp dapp = new DApp(title, url); DappBrowserUtils.addToHistory(getContext(), dapp); - adapter.addSuggestion(dapp); + addressBar.addSuggestion(dapp); } onWebpageLoadComplete(); - if (urlTv != null) urlTv.setText(url); + addressBar.setUrl(url); } @Override public void onWebpageLoadComplete() { handler.post(() -> { - setBackForwardButtons(); + addressBar.updateNavigationButtons(web3.copyBackForwardList()); if (loadUrlAfterReload != null) { loadUrl(loadUrlAfterReload); @@ -1655,61 +1410,6 @@ public void onWebpageLoadComplete() } } - private void setBackForwardButtons() - { - WebBackForwardList sessionHistory; - boolean canBrowseBack = false; - boolean canBrowseForward = false; - - if (currentFragment != null && !currentFragment.equals(DAPP_BROWSER)) - { - canBrowseBack = true; - } - else if (web3 != null) - { - sessionHistory = web3.copyBackForwardList(); - canBrowseBack = !isOnHomePage(); - canBrowseForward = (sessionHistory != null && sessionHistory.getCurrentIndex() < sessionHistory.getSize() - 1); - } - - if (back != null) - { - if (canBrowseBack) - { - back.setAlpha(1.0f); - } - else - { - back.setAlpha(0.3f); - } - } - - if (next != null) - { - if (canBrowseForward) - { - next.setAlpha(1.0f); - } - else - { - next.setAlpha(0.3f); - } - } - } - - private boolean isOnHomePage() - { - if (web3 != null) - { - String url = web3.getUrl(); - return DappBrowserUtils.isDefaultDapp(url); - } - else - { - return false; - } - } - private boolean loadUrl(String urlText) { AnalyticsProperties props = new AnalyticsProperties(); @@ -1744,8 +1444,7 @@ public void loadDirect(String urlText) setUrlText(Utils.formatUrl(urlText)); web3.resetView(); web3.loadUrl(Utils.formatUrl(urlText)); - //ensure focus isn't on the keyboard - KeyboardUtils.hideKeyboard(urlTv); + addressBar.leaveEditMode(); web3.requestFocus(); AnalyticsProperties props = new AnalyticsProperties(); @@ -1769,34 +1468,6 @@ public void reloadPage() } } - @Override - public void onItemClick(String url) - { - addToBackStack(DAPP_BROWSER); - loadUrl(url); - } - - public void testRecoverAddressFromSignature(@NotNull String message, String sig) - { - String prefix = PERSONAL_MESSAGE_PREFIX + message.length(); - byte[] msgHash = (prefix + message).getBytes(); - - byte[] signatureBytes = Numeric.hexStringToByteArray(sig); - Sign.SignatureData sd = sigFromByteArray(signatureBytes); - String addressRecovered; - - try - { - BigInteger recoveredKey = Sign.signedMessageToKey(msgHash, sd); - addressRecovered = "0x" + Keys.getAddress(recoveredKey); - Timber.d("Recovered: %s", addressRecovered); - } - catch (SignatureException e) - { - e.printStackTrace(); - } - } - private void resetDappBrowser() { web3.clearHistory(); @@ -2077,9 +1748,7 @@ private ByteArrayOutputStream getSerialisedBundle(Bundle bundle) throws Exceptio oos.writeObject(CURRENT_FRAGMENT); oos.writeObject(currentFragment); oos.writeObject(CURRENT_URL); - String uurl = urlTv.getText().toString(); - String uurl2 = web3.getUrl(); - oos.writeObject(urlTv.getText().toString()); + oos.writeObject(addressBar.getUrl()); } return bos; } @@ -2206,7 +1875,8 @@ public void getAuthorisation(SignAuthenticationCallback callback) @Override public void sendTransaction(Web3Transaction finalTx) { - final SendTransactionInterface callback = new SendTransactionInterface() { + final SendTransactionInterface callback = new SendTransactionInterface() + { @Override public void transactionSuccess(Web3Transaction web3Tx, String hashData) { diff --git a/app/src/main/java/com/alphawallet/app/widget/AddressBar.java b/app/src/main/java/com/alphawallet/app/widget/AddressBar.java new file mode 100644 index 0000000000..3d2b5e84fd --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/widget/AddressBar.java @@ -0,0 +1,338 @@ +package com.alphawallet.app.widget; + +import static com.alphawallet.app.util.KeyboardUtils.showKeyboard; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.webkit.WebBackForwardList; +import android.widget.AutoCompleteTextView; +import android.widget.ImageView; + +import androidx.annotation.Nullable; +import androidx.appcompat.widget.Toolbar; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.DApp; +import com.alphawallet.app.ui.widget.adapter.DappBrowserSuggestionsAdapter; +import com.alphawallet.app.util.DappBrowserUtils; +import com.alphawallet.app.util.KeyboardUtils; +import com.google.android.material.appbar.MaterialToolbar; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; + +public class AddressBar extends MaterialToolbar +{ + private final int ANIMATION_DURATION = 100; + + private AutoCompleteTextView urlTv; + private DappBrowserSuggestionsAdapter adapter; + private AddressBarListener listener; + private ImageView btnClear; + private View layoutNavigation; + private ImageView back; + private ImageView next; + + @Nullable + private Disposable disposable; + private boolean focused; + + public AddressBar(Context context, AttributeSet attributeSet) + { + super(context, attributeSet); + inflate(context, R.layout.layout_url_bar_full, this); + + initView(); + } + + public void setup(List list, AddressBarListener listener) + { + adapter = new DappBrowserSuggestionsAdapter( + getContext(), + list, + this::load + ); + this.listener = listener; + urlTv.setAdapter(null); + + urlTv.setOnEditorActionListener((v, actionId, event) -> { + if (actionId == EditorInfo.IME_ACTION_GO) + { + load(urlTv.getText().toString()); + } + return false; + }); + + // Both these are required, the onFocus listener is required to respond to the first click. + urlTv.setOnFocusChangeListener((v, hasFocus) -> { + //see if we have focus flag + if (hasFocus && focused) openURLInputView(); + }); + + urlTv.setOnClickListener(v -> { + openURLInputView(); + }); + + urlTv.setShowSoftInputOnFocus(true); + + urlTv.setOnLongClickListener(v -> { + urlTv.dismissDropDown(); + return false; + }); + + urlTv.addTextChangedListener(new TextWatcher() + { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) + { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) + { + + } + + @Override + public void afterTextChanged(Editable editable) + { + adapter.setHighlighted(editable.toString()); + } + }); + } + + private void load(String url) + { + listener.onLoad(url); + expandCollapseView(layoutNavigation, true); + leaveEditMode(); + } + + private void initView() + { + urlTv = findViewById(R.id.url_tv); + btnClear = findViewById(R.id.clear_url); + btnClear.setOnClickListener(v -> { + clearAddressBar(); + }); + + layoutNavigation = findViewById(R.id.layout_navigator); + back = findViewById(R.id.back); + back.setOnClickListener(v -> listener.loadPrevious()); + + next = findViewById(R.id.next); + next.setOnClickListener(v -> listener.loadNext()); + } + + private void clearAddressBar() + { + if (urlTv.getText().toString().isEmpty()) + { + KeyboardUtils.hideKeyboard(urlTv); + listener.onClear(); + } + else + { + urlTv.getText().clear(); + openURLInputView(); + showKeyboard(urlTv); //ensure keyboard shows here so we can listen for it being cancelled + } + } + + private void openURLInputView() + { + urlTv.setAdapter(null); + expandCollapseView(layoutNavigation, false); + + disposable = Observable.zip( + Observable.interval(600, TimeUnit.MILLISECONDS).take(1), + Observable.fromArray(btnClear), (interval, item) -> item) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(AndroidSchedulers.mainThread()) + .subscribe(this::postBeginSearchSession); + } + + private void postBeginSearchSession(@NotNull ImageView item) + { + urlTv.setAdapter(adapter); + urlTv.showDropDown(); + if (item.getVisibility() == View.GONE) + { + expandCollapseView(item, true); + showKeyboard(urlTv); + } + } + + private synchronized void expandCollapseView(@NotNull View view, boolean expandView) + { + //detect if view is expanded or collapsed + boolean isViewExpanded = view.getVisibility() == View.VISIBLE; + + //Collapse view + if (isViewExpanded && !expandView) + { + int finalWidth = view.getWidth(); + ValueAnimator valueAnimator = slideAnimator(finalWidth, 0, view); + valueAnimator.addListener(new Animator.AnimatorListener() + { + @Override + public void onAnimationStart(Animator animator) + { + + } + + @Override + public void onAnimationEnd(Animator animator) + { + view.setVisibility(View.GONE); + } + + @Override + public void onAnimationCancel(Animator animator) + { + + } + + @Override + public void onAnimationRepeat(Animator animator) + { + + } + }); + valueAnimator.start(); + } + //Expand view + else if (!isViewExpanded && expandView) + { + view.setVisibility(View.VISIBLE); + + int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + + view.measure(widthSpec, heightSpec); + int width = view.getMeasuredWidth(); + ValueAnimator valueAnimator = slideAnimator(0, width, view); + valueAnimator.start(); + } + } + + @NotNull + private ValueAnimator slideAnimator(int start, int end, final View view) + { + + final ValueAnimator animator = ValueAnimator.ofInt(start, end); + + animator.addUpdateListener(valueAnimator -> { + // Update Height + int value = (Integer) valueAnimator.getAnimatedValue(); + + ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); + layoutParams.width = value; + view.setLayoutParams(layoutParams); + }); + animator.setDuration(ANIMATION_DURATION); + return animator; + } + + public void removeSuggestion(DApp dApp) + { + adapter.removeSuggestion(dApp); + } + + public void addSuggestion(DApp dapp) + { + adapter.addSuggestion(dapp); + } + + public void shrinkSearchBar() + { + expandCollapseView(layoutNavigation, true); + btnClear.setVisibility(View.GONE); + urlTv.dismissDropDown(); + } + + public void destroy() + { + if (disposable != null && !disposable.isDisposed()) disposable.dispose(); + } + + public void clear() + { + if (urlTv != null) + urlTv.getText().clear(); + } + + public void leaveEditMode() + { + if (urlTv != null) + { + urlTv.clearFocus(); + KeyboardUtils.hideKeyboard(urlTv); + btnClear.setVisibility(GONE); + } + focused = true; + } + + public void leaveFocus() + { + if (urlTv != null) urlTv.clearFocus(); + focused = false; + } + + public void setUrl(String newUrl) + { + if (urlTv != null) + urlTv.setText(newUrl); + } + + public void updateNavigationButtons(WebBackForwardList backForwardList) + { + boolean isLast = backForwardList.getCurrentIndex() + 1 > backForwardList.getSize() - 1; + if (isLast) + { + next.setEnabled(false); + next.setAlpha(0.3f); + } + else + { + next.setEnabled(true); + next.setAlpha(1.0f); + } + + + if (!isOnHomePage()) + { + back.setEnabled(true); + back.setAlpha(1.0f); + } + else + { + back.setEnabled(false); + back.setAlpha(0.3f); + } + } + + public boolean isOnHomePage() + { + return DappBrowserUtils.isDefaultDapp(urlTv.getText().toString()); + } + + public String getUrl() + { + return urlTv.getText().toString(); + } +} diff --git a/app/src/main/java/com/alphawallet/app/widget/AddressBarListener.java b/app/src/main/java/com/alphawallet/app/widget/AddressBarListener.java new file mode 100644 index 0000000000..db8a30b09d --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/widget/AddressBarListener.java @@ -0,0 +1,11 @@ +package com.alphawallet.app.widget; + +public interface AddressBarListener +{ + boolean onLoad(String urlText); + void onClear(); + + void loadNext(); + + void loadPrevious(); +} diff --git a/app/src/main/res/layout/fragment_webview.xml b/app/src/main/res/layout/fragment_webview.xml index c10189b77a..bd91508732 100644 --- a/app/src/main/res/layout/fragment_webview.xml +++ b/app/src/main/res/layout/fragment_webview.xml @@ -1,15 +1,18 @@ + android:layout_height="match_parent"> - + + android:layout_below="@id/address_bar_widget" /> Date: Tue, 8 Nov 2022 14:39:27 +0800 Subject: [PATCH 138/183] fix malicious NFT make app crash (#2909) * Catch NumberFormatException when bgColor is invalid --- .../main/java/com/alphawallet/app/widget/NFTImageView.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/widget/NFTImageView.java b/app/src/main/java/com/alphawallet/app/widget/NFTImageView.java index f5985c3926..cd4678b167 100644 --- a/app/src/main/java/com/alphawallet/app/widget/NFTImageView.java +++ b/app/src/main/java/com/alphawallet/app/widget/NFTImageView.java @@ -41,6 +41,8 @@ import java.nio.charset.StandardCharsets; +import timber.log.Timber; + /** * Created by JB on 30/05/2021. */ @@ -145,14 +147,15 @@ private void loadImage(String url, String backgroundColor, int corners) throws I image.setVisibility(View.VISIBLE); webLayout.setVisibility(View.GONE); - if (!TextUtils.isEmpty(backgroundColor)) + try { int color = Color.parseColor("#" + backgroundColor); ColorStateList sl = ColorStateList.valueOf(color); holdingView.setBackgroundTintList(sl); } - else + catch (Exception e) { + Timber.w(e); holdingView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.transparent)); } From bc9bddb4c0ee2b88ce81dd9159e6eb6b4509c0c2 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Tue, 8 Nov 2022 14:42:17 +0800 Subject: [PATCH 139/183] Cancel in progress jobs (#2924) * Cancel in progress jobs --- .github/workflows/ci-ubuntu.yml | 5 ++++- .github/workflows/ci-windows.yml | 5 ++++- .github/workflows/ci.yml | 5 ++++- .github/workflows/codestyle.yml | 3 +++ .github/workflows/e2e.yml | 5 ++++- .github/workflows/lint-pr.yml | 3 +++ .github/workflows/lint.yml | 3 +++ .github/workflows/stats.yml | 4 +--- 8 files changed, 26 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-ubuntu.yml b/.github/workflows/ci-ubuntu.yml index 54be4252b6..e587cd9f28 100644 --- a/.github/workflows/ci-ubuntu.yml +++ b/.github/workflows/ci-ubuntu.yml @@ -7,6 +7,9 @@ on: jobs: test: runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v3 @@ -30,4 +33,4 @@ jobs: run: | curl -Os https://uploader.codecov.io/latest/linux/codecov chmod +x codecov - ./codecov \ No newline at end of file + ./codecov diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index e93ff358ce..4d7e11d4bb 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -7,6 +7,9 @@ on: jobs: test: runs-on: windows-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v3 @@ -30,4 +33,4 @@ jobs: run: | curl -Os https://uploader.codecov.io/latest/windows/codecov chmod +x codecov - ./codecov \ No newline at end of file + ./codecov diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21e6c53f4d..89a1bb9bf3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,9 @@ on: jobs: test: runs-on: self-hosted + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v3 @@ -31,4 +34,4 @@ jobs: run: | curl -Os https://uploader.codecov.io/latest/macos/codecov chmod +x codecov - ./codecov \ No newline at end of file + ./codecov diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index 12adccc228..80338f1aba 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -5,6 +5,9 @@ jobs: lint: name: Check runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index b9d469c92d..2807ef8dad 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,6 +7,9 @@ on: jobs: test: runs-on: self-hosted + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true timeout-minutes: 20 strategy: matrix: @@ -40,4 +43,4 @@ jobs: uses: actions/upload-artifact@v1 with: name: e2e-tests-results - path: output/ \ No newline at end of file + path: output/ diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index 42f08d3b86..756a270b76 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -4,6 +4,9 @@ jobs: lint: name: Comments lint result on PR runs-on: macos-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0d721cb00c..40d9fa2823 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,6 +8,9 @@ jobs: lint: name: Run Lint runs-on: macos-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/stats.yml b/.github/workflows/stats.yml index 459c67e940..af782045db 100644 --- a/.github/workflows/stats.yml +++ b/.github/workflows/stats.yml @@ -1,9 +1,7 @@ name: Pull Request Stats - on: pull_request: types: [opened] - jobs: stats: runs-on: ubuntu-latest @@ -12,4 +10,4 @@ jobs: uses: flowwer-dev/pull-request-stats@master with: charts: true - sort-by: 'COMMENTS' \ No newline at end of file + sort-by: 'COMMENTS' From e9afa4a6d0e5bb704bde4b7e962990ae64f8a0a4 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 10 Nov 2022 11:00:37 +0800 Subject: [PATCH 140/183] Fix SwapProvider NPE (#2919) * Avoid NPE --- .../alphawallet/app/repository/SwapRepositoryType.java | 2 +- .../app/viewmodel/SelectSwapProvidersViewModel.java | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/repository/SwapRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/SwapRepositoryType.java index 978babf52b..2821fc08a2 100644 --- a/app/src/main/java/com/alphawallet/app/repository/SwapRepositoryType.java +++ b/app/src/main/java/com/alphawallet/app/repository/SwapRepositoryType.java @@ -6,5 +6,5 @@ public interface SwapRepositoryType { - public List getProviders(); + List getProviders(); } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java index e162683958..b7449456a8 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java @@ -6,6 +6,7 @@ import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.repository.SwapRepositoryType; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -13,6 +14,7 @@ import javax.inject.Inject; import dagger.hilt.android.lifecycle.HiltViewModel; +import timber.log.Timber; @HiltViewModel public class SelectSwapProvidersViewModel extends BaseViewModel @@ -53,7 +55,7 @@ public List getSwapProviders() if (swapProviders != null) { - Set preferredProviders = preferenceRepository.getSelectedSwapProviders(); + Set preferredProviders = preferenceRepository.getSelectedSwapProviders(); for (SwapProvider provider : swapProviders) { if (preferredProviders.contains(provider.key)) @@ -62,6 +64,11 @@ public List getSwapProviders() } } } + else + { + Timber.w("No Swap Providers found."); + swapProviders = new ArrayList<>(); + } return swapProviders; } From f42a994a4b6c9e819d0a94ff01d7a388a4f4d9b1 Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 10 Nov 2022 00:21:27 -0800 Subject: [PATCH 141/183] Show number of enabled networks in title (#2930) --- .../alphawallet/app/SelectNetworkTest.java | 24 +++++++ .../app/ui/SelectNetworkFilterActivity.java | 70 +++++++++++-------- .../adapter/MultiSelectNetworkAdapter.java | 37 ++++++---- app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-id/strings.xml | 1 + app/src/main/res/values-my/strings.xml | 1 + app/src/main/res/values-vi/strings.xml | 1 + app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 10 files changed, 95 insertions(+), 43 deletions(-) create mode 100644 app/src/androidTest/java/com/alphawallet/app/SelectNetworkTest.java diff --git a/app/src/androidTest/java/com/alphawallet/app/SelectNetworkTest.java b/app/src/androidTest/java/com/alphawallet/app/SelectNetworkTest.java new file mode 100644 index 0000000000..b33740433c --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/SelectNetworkTest.java @@ -0,0 +1,24 @@ +package com.alphawallet.app; + +import static androidx.test.espresso.matcher.ViewMatchers.withSubstring; +import static com.alphawallet.app.assertions.Should.shouldSee; +import static com.alphawallet.app.steps.Steps.createNewWallet; +import static com.alphawallet.app.steps.Steps.gotoSettingsPage; +import static com.alphawallet.app.steps.Steps.selectMenu; +import static com.alphawallet.app.util.Helper.clickListItem; + +import org.junit.Test; + +public class SelectNetworkTest extends BaseE2ETest +{ + @Test + public void title_should_update_count() + { + createNewWallet(); + gotoSettingsPage(); + selectMenu("Select Active Networks"); + shouldSee("Enabled Networks (1)"); + clickListItem(R.id.test_list, withSubstring("Gnosis")); + shouldSee("Enabled Networks (2)"); + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/SelectNetworkFilterActivity.java b/app/src/main/java/com/alphawallet/app/ui/SelectNetworkFilterActivity.java index d85a230609..f1c5a7eb67 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SelectNetworkFilterActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SelectNetworkFilterActivity.java @@ -1,11 +1,9 @@ package com.alphawallet.app.ui; +import static com.alphawallet.app.ui.AddCustomRPCNetworkActivity.CHAIN_ID; + import android.content.Intent; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; import android.os.Bundle; -import android.util.TypedValue; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.CompoundButton; @@ -15,13 +13,10 @@ import androidx.annotation.Nullable; import androidx.lifecycle.ViewModelProvider; -import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.analytics.Analytics; -import com.alphawallet.app.repository.EthereumNetworkRepositoryType; import com.alphawallet.app.ui.widget.adapter.MultiSelectNetworkAdapter; import com.alphawallet.app.ui.widget.entity.NetworkItem; -import com.alphawallet.app.ui.widget.entity.WarningData; import com.alphawallet.app.viewmodel.SelectNetworkFilterViewModel; import com.alphawallet.app.widget.TestNetDialog; import com.alphawallet.ethereum.NetworkInfo; @@ -30,41 +25,30 @@ import java.util.Arrays; import java.util.List; -import javax.inject.Inject; - - -import static com.alphawallet.app.ui.AddCustomRPCNetworkActivity.CHAIN_ID; - import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint -public class SelectNetworkFilterActivity extends SelectNetworkBaseActivity implements TestNetDialog.TestNetDialogCallback { +public class SelectNetworkFilterActivity extends SelectNetworkBaseActivity implements TestNetDialog.TestNetDialogCallback +{ private SelectNetworkFilterViewModel viewModel; - private MultiSelectNetworkAdapter mainNetAdapter; private MultiSelectNetworkAdapter testNetAdapter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setTitle(getString(R.string.select_active_networks)); - viewModel = new ViewModelProvider(this) .get(SelectNetworkFilterViewModel.class); - setupList(); - initTestNetDialog(this); } @Override - protected void onResume() { + protected void onResume() + { super.onResume(); setupFilterList(); - viewModel.track(Analytics.Navigation.SELECT_NETWORKS); } @@ -77,6 +61,10 @@ void setupList() CompoundButton.OnCheckedChangeListener mainnetListener = (compoundButton, checked) -> { testnetSwitch.setChecked(!checked); + if (checked) + { + updateTitle(mainNetAdapter.getSelectedItemCount()); + } }; CompoundButton.OnCheckedChangeListener testnetListener = (compoundButton, checked) -> @@ -90,6 +78,11 @@ void setupList() if (checked) { testnetDialog.show(); + updateTitle(testNetAdapter.getSelectedItemCount()); + } + else + { + updateTitle(mainNetAdapter.getSelectedItemCount()); } }; @@ -106,9 +99,11 @@ private void setupFilterList() List mainNetList = viewModel.getNetworkList(true); List testNetList = viewModel.getNetworkList(false); - MultiSelectNetworkAdapter.EditNetworkListener editNetworkListener = new MultiSelectNetworkAdapter.EditNetworkListener() { + MultiSelectNetworkAdapter.Callback callback = new MultiSelectNetworkAdapter.Callback() + { - private void showPopup(View view, long chainId) { + private void showPopup(View view, long chainId) + { LayoutInflater inflater = LayoutInflater.from(SelectNetworkFilterActivity.this); View popupView = inflater.inflate(R.layout.popup_view_delete_network, null); @@ -124,14 +119,17 @@ private void showPopup(View view, long chainId) { }); NetworkInfo network = viewModel.getNetworkByChain(chainId); - if (network.isCustom) { + if (network.isCustom) + { popupView.findViewById(R.id.popup_delete).setOnClickListener(v -> { // delete network viewModel.removeCustomNetwork(chainId); popupWindow.dismiss(); setupFilterList(); }); - } else { + } + else + { popupView.findViewById(R.id.popup_delete).setVisibility(View.GONE); } @@ -144,16 +142,30 @@ private void showPopup(View view, long chainId) { } @Override - public void onEditNetwork(long chainId, View parent) { + public void onEditSelected(long chainId, View parent) + { showPopup(parent, chainId); } + + @Override + public void onCheckChanged(long chainId, int count) + { + updateTitle(count); + } }; - mainNetAdapter = new MultiSelectNetworkAdapter(mainNetList, editNetworkListener); + mainNetAdapter = new MultiSelectNetworkAdapter(mainNetList, callback); mainnetRecyclerView.setAdapter(mainNetAdapter); - testNetAdapter = new MultiSelectNetworkAdapter(testNetList, editNetworkListener); + testNetAdapter = new MultiSelectNetworkAdapter(testNetList, callback); testnetRecyclerView.setAdapter(testNetAdapter); + + updateTitle(viewModel.mainNetActive() ? mainNetAdapter.getSelectedItemCount() : testNetAdapter.getSelectedItemCount()); + } + + private void updateTitle(int count) + { + setTitle(getString(R.string.title_enabled_networks, String.valueOf(count))); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MultiSelectNetworkAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MultiSelectNetworkAdapter.java index 2e9c761387..c0528e1564 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MultiSelectNetworkAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MultiSelectNetworkAdapter.java @@ -19,21 +19,16 @@ import java.util.ArrayList; import java.util.List; -public class MultiSelectNetworkAdapter extends RecyclerView.Adapter { +public class MultiSelectNetworkAdapter extends RecyclerView.Adapter +{ private final List networkList; + private final Callback callback; private boolean hasClicked = false; - public interface EditNetworkListener { - void onEditNetwork(long chainId, View parent); - } - - private final EditNetworkListener editListener; - - - public MultiSelectNetworkAdapter(List selectedNetworks, EditNetworkListener editNetworkListener) + public MultiSelectNetworkAdapter(List selectedNetworks, Callback callback) { networkList = selectedNetworks; - editListener = editNetworkListener; + this.callback = callback; } public Long[] getSelectedItems() @@ -60,7 +55,7 @@ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) View itemView = LayoutInflater.from(parent.getContext()) .inflate(buttonTypeId, parent, false); - return new MultiSelectNetworkAdapter.ViewHolder(itemView); + return new ViewHolder(itemView); } @Override @@ -74,7 +69,7 @@ public void onBindViewHolder(MultiSelectNetworkAdapter.ViewHolder holder, int po holder.chainId.setText(holder.itemLayout.getContext().getString(R.string.chain_id, item.getChainId())); holder.itemLayout.setOnClickListener(v -> clickListener(holder, position)); holder.manageView.setVisibility(View.VISIBLE); - holder.manageView.setOnClickListener(v -> editListener.onEditNetwork(networkList.get(position).getChainId(), holder.manageView)); + holder.manageView.setOnClickListener(v -> callback.onEditSelected(networkList.get(position).getChainId(), holder.manageView)); holder.checkbox.setChecked(item.isSelected()); holder.tokenIcon.bindData(item.getChainId()); @@ -88,11 +83,17 @@ public void onBindViewHolder(MultiSelectNetworkAdapter.ViewHolder holder, int po } } + public int getSelectedItemCount() + { + return getSelectedItems().length; + } + private void clickListener(final MultiSelectNetworkAdapter.ViewHolder holder, final int position) { networkList.get(position).setSelected(!networkList.get(position).isSelected()); holder.checkbox.setChecked(networkList.get(position).isSelected()); hasClicked = true; + callback.onCheckChanged(networkList.get(position).getChainId(), getSelectedItemCount()); } @Override @@ -101,7 +102,15 @@ public int getItemCount() return networkList.size(); } - class ViewHolder extends RecyclerView.ViewHolder { + public interface Callback + { + void onEditSelected(long chainId, View parent); + + void onCheckChanged(long chainId, int count); + } + + static class ViewHolder extends RecyclerView.ViewHolder + { MaterialCheckBox checkbox; TextView name; View itemLayout; @@ -122,4 +131,4 @@ class ViewHolder extends RecyclerView.ViewHolder { deprecatedIndicator = view.findViewById(R.id.deprecated); } } -} \ No newline at end of file +} diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 62de64b357..4112455791 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -407,6 +407,7 @@ Busca o escribe una dirección web Redes Seleccionar redes activas + Redes habilitadas (%s) Coleccionables Función del token Canal de notificación de AlphaWallet diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 696a65acbc..fb9fa97587 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -416,6 +416,7 @@ Chercher ou taper une adresse web Réseaux Selectionner Réseaux Actifs + Réseaux Activés (%s) Objects de Collections Fonctions du Token Chaine de notifications Alphawallet diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index e352e13fec..64317cc410 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -417,6 +417,7 @@ Cari atau ketik alamat situs jaringan Jaringan Pilih Jaringan Aktif + Jaringan yang Diaktifkan (%s) Barang Koleksi Fungsi Token Saluran pemberitahuan Alphawallet diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 8ad7842002..6bb18cb120 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -424,6 +424,7 @@ ဝက်ဘ်လိပ်စာကိုရိုက်ထည့်ရှာဖွေပါ ကွန်ရက် အသက်ဝင်နေသောကွန်ရက်များကိုရွေးချယ်ပါ + ကွန်ရက်များကို ဖွင့်ထားသည်။ (%s) စုဆောင်ထားသောအရများ တိုကင်လုပ်ငန်းစဥ်များ Alphawallet အသိပေးစာလမ်းကြောင်းများ diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 5f7d3abdf5..8e4a6341d4 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -419,6 +419,7 @@ Tìm kiếm hoặc nhập địa chỉ web Networks Chọn mạng đang hoạt động + Mạng được kích hoạt (%s) Bộ sưu tầm Token Function Kênh thông báo Alphawallet diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 9775395c3b..050fa64e37 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -407,6 +407,7 @@ 搜索或键入网址 网络 设置启用的区块链 + 启用网络 (%s) 收藏品 通证功能 Alphawallet 通知渠道 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 00b4797fe8..bfbe8002b2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -443,6 +443,7 @@ Search or type web address Networks Select Active Networks + Enabled Networks (%s) Collectibles Token Function Alphawallet notification channel From 481e6d4237034b5f005c2572d94a2caacefcdd69 Mon Sep 17 00:00:00 2001 From: justindg Date: Thu, 10 Nov 2022 00:22:49 -0800 Subject: [PATCH 142/183] Change logo uri (#2931) --- app/src/main/java/com/alphawallet/app/C.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 6f79d43399..689116519a 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -302,7 +302,7 @@ public enum TokenStatus { public static final String PREF_UNIQUE_ID = "unique_id"; public static final String APP_NAME = "PACKAGE_NAME"; - public static final String ALPHAWALLET_LOGO_URI = "https://alphawallet.com/wp-content/themes/alphawallet/img/alphawallet-logo.svg"; + public static final String ALPHAWALLET_LOGO_URI = "https://alphawallet.com/wp-content/themes/alphawallet/img/logo-horizontal-new.svg"; // Theme/Dark Mode public static final int THEME_LIGHT = 0; From 50027dbc23163d7dd5f9b8279d0ebc6636061b84 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 10 Nov 2022 23:55:05 +0800 Subject: [PATCH 143/183] Add CheckStyle on CI (#2926) * Add CheckStyle action * Test * Update config * Update config * Test * Test * Remove .editorConfigChecker --- .github/checkstyle-rules.xml | 332 +++ .github/workflows/checkstyle.yml | 23 + .github/workflows/codestyle.yml | 47 - .husky/pre-commit | 4 - .../app/ui/ScammerWarningActivity.java | 25 +- package-lock.json | 2122 ----------------- package.json | 13 +- 7 files changed, 373 insertions(+), 2193 deletions(-) create mode 100644 .github/checkstyle-rules.xml create mode 100644 .github/workflows/checkstyle.yml delete mode 100644 .github/workflows/codestyle.yml delete mode 100755 .husky/pre-commit diff --git a/.github/checkstyle-rules.xml b/.github/checkstyle-rules.xml new file mode 100644 index 0000000000..3f97635791 --- /dev/null +++ b/.github/checkstyle-rules.xml @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.github/workflows/checkstyle.yml b/.github/workflows/checkstyle.yml new file mode 100644 index 0000000000..9be96b02a9 --- /dev/null +++ b/.github/workflows/checkstyle.yml @@ -0,0 +1,23 @@ +name: Run CheckStyle +on: pull_request + +jobs: + checkstyle_job: + runs-on: ubuntu-latest + name: Checkstyle job + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Run check style + uses: nikitasavinov/checkstyle-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + checkstyle_config: '.github/checkstyle-rules.xml' + reporter: 'github-pr-review' + filter_mode: 'file' + fail_on_error: true + level: 'error' + tool_name: 'CheckStyle' diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml deleted file mode 100644 index 80338f1aba..0000000000 --- a/.github/workflows/codestyle.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Check code format -on: - pull_request: -jobs: - lint: - name: Check - runs-on: ubuntu-latest - concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Setup NodeJS - uses: actions/setup-node@v3 - with: - node-version: 16 - - name: Install dependencies - run: npm install - - name: Get changed files - id: changed-files - uses: tj-actions/changed-files@v34 - - name: Check all changed files - run: | - for file in ${{ steps.changed-files.outputs.all_changed_files }}; do - npx ec -no-color "$file" >> format-error.txt || true - done - if [[ -s "format-error.txt" ]]; then - exit 1 - else - exit 0 - fi - - name: Collect results - if: ${{ failure() }} - uses: actions/upload-artifact@v1 - with: - name: format-error - path: format-error.txt - - name: comment PR - if: ${{ failure() }} - uses: machine-learning-apps/pr-comment@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - path: format-error.txt diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index d24fdfc601..0000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -npx lint-staged diff --git a/app/src/main/java/com/alphawallet/app/ui/ScammerWarningActivity.java b/app/src/main/java/com/alphawallet/app/ui/ScammerWarningActivity.java index 0e3aea6db1..80fac01b2d 100644 --- a/app/src/main/java/com/alphawallet/app/ui/ScammerWarningActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/ScammerWarningActivity.java @@ -61,12 +61,14 @@ import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint -public class ScammerWarningActivity extends BaseActivity { +public class ScammerWarningActivity extends BaseActivity +{ private FunctionButtonBar functionButtonBar; private Wallet wallet; @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) + { super.onCreate(savedInstanceState); lockOrientation(); toolbar(); @@ -75,15 +77,20 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { } @SuppressLint("SourceLockedOrientationActivity") - private void lockOrientation() { - if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + private void lockOrientation() + { + if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) + { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - } else { + } + else + { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } } - private void setShowSeedPhraseSplash() { + private void setShowSeedPhraseSplash() + { setContentView(R.layout.activity_show_seed); initViews(); functionButtonBar.setPrimaryButtonText(R.string.show_seed_phrase); @@ -92,14 +99,16 @@ private void setShowSeedPhraseSplash() { }); } - private void openBackupKeyActivity() { + private void openBackupKeyActivity() + { Intent intent = new Intent(this, BackupKeyActivity.class); intent.putExtra(WALLET, wallet); intent.putExtra("STATE", SHOW_SEED_PHRASE_SINGLE); startActivity(intent); } - private void initViews() { + private void initViews() + { functionButtonBar = findViewById(R.id.layoutButtons); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); toolbar(); diff --git a/package-lock.json b/package-lock.json index fc8648e450..62d0316052 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,2141 +10,19 @@ "license": "GPL-3.0", "dependencies": { "normalize.css": "^8.0.0" - }, - "devDependencies": { - "editorconfig-checker": "4.0.0", - "husky": "^8.0.0", - "lint-staged": "^13.0.3" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "node_modules/commander": { - "version": "9.4.1", - "resolved": "https://registry.npmmirror.com/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/editorconfig-checker": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/editorconfig-checker/-/editorconfig-checker-4.0.0.tgz", - "integrity": "sha512-Vd0bfNHFsacoy+4l7TTSXpoCwBD6njW5OTz9ftYSTkKZokC4nPzFMVg1ZBci3BzXqxpT/pt5b+t3raKJ9EYvrg==", - "dev": true, - "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.0", - "rimraf": "^3.0.2", - "tar": "^6.0.0" - }, - "bin": { - "ec": "dist/index.js", - "editorconfig-checker": "dist/index.js" - } - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/execa": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/execa/-/execa-6.1.0.tgz", - "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^3.0.1", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-3.0.1.tgz", - "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", - "dev": true, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/husky": { - "version": "8.0.1", - "resolved": "https://registry.npmmirror.com/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/lilconfig": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.0.5.tgz", - "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lint-staged": { - "version": "13.0.3", - "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-13.0.3.tgz", - "integrity": "sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==", - "dev": true, - "dependencies": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.17", - "commander": "^9.3.0", - "debug": "^4.3.4", - "execa": "^6.1.0", - "lilconfig": "2.0.5", - "listr2": "^4.0.5", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.2", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.1.1" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - } - }, - "node_modules/listr2": { - "version": "4.0.5", - "resolved": "https://registry.npmmirror.com/listr2/-/listr2-4.0.5.tgz", - "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.5", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/listr2/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" } }, "node_modules/normalize.css": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz", "integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A==" - }, - "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/tar": { - "version": "6.1.12", - "resolved": "https://registry.npmmirror.com/tar/-/tar-6.1.12.tgz", - "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", - "dev": true - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.1.3.tgz", - "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", - "dev": true, - "engines": { - "node": ">= 14" - } } }, "dependencies": { - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "commander": { - "version": "9.4.1", - "resolved": "https://registry.npmmirror.com/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "editorconfig-checker": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/editorconfig-checker/-/editorconfig-checker-4.0.0.tgz", - "integrity": "sha512-Vd0bfNHFsacoy+4l7TTSXpoCwBD6njW5OTz9ftYSTkKZokC4nPzFMVg1ZBci3BzXqxpT/pt5b+t3raKJ9EYvrg==", - "dev": true, - "requires": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.0", - "rimraf": "^3.0.2", - "tar": "^6.0.0" - } - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "execa": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/execa/-/execa-6.1.0.tgz", - "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^3.0.1", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-3.0.1.tgz", - "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", - "dev": true - }, - "husky": { - "version": "8.0.1", - "resolved": "https://registry.npmmirror.com/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "lilconfig": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.0.5.tgz", - "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", - "dev": true - }, - "lint-staged": { - "version": "13.0.3", - "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-13.0.3.tgz", - "integrity": "sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==", - "dev": true, - "requires": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.17", - "commander": "^9.3.0", - "debug": "^4.3.4", - "execa": "^6.1.0", - "lilconfig": "2.0.5", - "listr2": "^4.0.5", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.2", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.1.1" - } - }, - "listr2": { - "version": "4.0.5", - "resolved": "https://registry.npmmirror.com/listr2/-/listr2-4.0.5.tgz", - "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.5", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, "normalize.css": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz", "integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A==" - }, - "npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } - } - }, - "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "dependencies": { - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - } - } - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - } - }, - "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, - "tar": { - "version": "6.1.12", - "resolved": "https://registry.npmmirror.com/tar/-/tar-6.1.12.tgz", - "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", - "dev": true - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yaml": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.1.3.tgz", - "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", - "dev": true } } } diff --git a/package.json b/package.json index 7287014736..fea092d23a 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,12 @@ }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "prepare": "husky install" }, "repository": { "type": "git", "url": "git+https://github.com/AlphaWallet/alpha-wallet-android.git" }, - "author": "", + "author": "Smart Token Labs", "license": "GPL-3.0", "bugs": { "url": "https://github.com/AlphaWallet/alpha-wallet-android/issues" @@ -22,15 +21,5 @@ "homepage": "https://github.com/AlphaWallet/alpha-wallet-android#readme", "dependencies": { "normalize.css": "^8.0.0" - }, - "devDependencies": { - "editorconfig-checker": "4.0.0", - "husky": "^8.0.0", - "lint-staged": "^13.0.3" - }, - "lint-staged": { - "**/*": [ - "npx ec" - ] } } From 6ec252baffd1da04d68f2f80065a927d2d326962 Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Fri, 11 Nov 2022 10:31:52 +0800 Subject: [PATCH 144/183] Fix Dapp browser test (#2933) * Avoid NPE * Fix format * Fix Dapp browser test * Fix merge error * Only check added/modified lines other than files --- .github/workflows/checkstyle.yml | 2 +- .../com/alphawallet/app/DappBrowserTest.java | 19 +++++-- .../app/ui/DappBrowserFragment.java | 42 +++++++------- .../SelectSwapProvidersViewModel.java | 4 +- .../alphawallet/app/widget/AddressBar.java | 55 ++++++++++++++----- .../app/widget/AddressBarListener.java | 9 ++- 6 files changed, 85 insertions(+), 46 deletions(-) diff --git a/.github/workflows/checkstyle.yml b/.github/workflows/checkstyle.yml index 9be96b02a9..6d5b0dc734 100644 --- a/.github/workflows/checkstyle.yml +++ b/.github/workflows/checkstyle.yml @@ -17,7 +17,7 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} checkstyle_config: '.github/checkstyle-rules.xml' reporter: 'github-pr-review' - filter_mode: 'file' +# filter_mode: 'file' # https://github.com/nikitasavinov/checkstyle-action fail_on_error: true level: 'error' tool_name: 'CheckStyle' diff --git a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java index 82af16a667..a07d7a709e 100644 --- a/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/DappBrowserTest.java @@ -35,8 +35,8 @@ public class DappBrowserTest extends BaseE2ETest { - private static final String DEFAULT_HOME_PAGE = "https://alphawallet.com/browser/"; - private static final String URL_DAPP = "https://app.1inch.io/"; + private static final String DEFAULT_HOME_PAGE = "https://courses.cs.washington.edu/courses/cse373/99sp/assignments/hw2/test1.html"; + private static final String URL_DAPP = "http://web.simmons.edu/~grovesd/comm244/notes/week3/html-test-page.html"; @Override @Before @@ -51,11 +51,10 @@ public void setUp() public void should_switch_network() { shouldSee("Ethereum"); - waitUntilLoaded(); selectTestNet("Görli"); navigateToBrowser(); - waitUntilLoaded(); pressBack(); + waitUntilLoaded(); shouldSee("Görli"); } @@ -72,6 +71,17 @@ public void should_suggest_websites() assertUrlContains("alphawallet.app.entity.DApp@"); } + @Test + public void should_go_back_when_press_back_button_on_phone() + { + visit(URL_DAPP); + assertUrlContains(URL_DAPP); + Helper.wait(2); + pressBack(); + waitUntilLoaded(); + assertUrlContains(DEFAULT_HOME_PAGE); + } + @Test public void should_navigate_forward_or_backward() { @@ -115,6 +125,7 @@ public void should_set_homepage() visit(URL_DAPP); waitUntilLoaded(); openOptionsMenu(); + Helper.wait(1); click(withText("Set as Home Page")); Helper.wait(2); click(withId(R.id.home)); diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index e0d07b82b4..11d39fba4c 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -341,15 +341,24 @@ public void onClear() } @Override - public void loadNext() + public WebBackForwardList loadNext() { goToNextPage(); + return web3.copyBackForwardList(); } @Override - public void loadPrevious() + public WebBackForwardList loadPrevious() { backPressed(); + return web3.copyBackForwardList(); + } + + @Override + public WebBackForwardList onHomePagePressed() + { + homePressed(); + return web3.copyBackForwardList(); } }); @@ -417,8 +426,6 @@ private void homePressed() { resetDappBrowser(); } - - addressBar.updateNavigationButtons(web3.copyBackForwardList()); } @Override @@ -537,9 +544,6 @@ private void initView(@NotNull View view) toolbar = view.findViewById(R.id.address_bar); - View home = view.findViewById(R.id.home); - if (home != null) home.setOnClickListener(v -> homePressed()); - //If you are wondering about the strange way the menus are inflated - this is required to ensure //that the menu text gets created with the correct localisation under every circumstance MenuInflater inflater = new MenuInflater(LocaleUtils.getActiveLocaleContext(getContext())); @@ -1323,37 +1327,27 @@ public void backPressed() } else if (web3.canGoBack()) { - loadSessionUrl(-1); + setUrlText(getSessionUrl(-1)); web3.goBack(); detachFragments(); } else if (!web3.getUrl().equalsIgnoreCase(getDefaultDappUrl())) { - //load homepage - homePressed = true; - web3.resetView(); - web3.loadUrl(getDefaultDappUrl()); - setUrlText(getDefaultDappUrl()); + homePressed(); + addressBar.updateNavigationButtons(web3.copyBackForwardList()); } - addressBar.updateNavigationButtons(web3.copyBackForwardList()); } private void goToNextPage() { if (web3.canGoForward()) { - loadSessionUrl(1); + setUrlText(getSessionUrl(1)); web3.goForward(); - addressBar.updateNavigationButtons(web3.copyBackForwardList()); } } - /** - * Browse to relative entry with sanity check on value - * - * @param relative relative addition or subtraction of browsing index - */ - private void loadSessionUrl(int relative) + private String getSessionUrl(int relative) { WebBackForwardList sessionHistory = web3.copyBackForwardList(); int newIndex = sessionHistory.getCurrentIndex() + relative; @@ -1362,9 +1356,11 @@ private void loadSessionUrl(int relative) WebHistoryItem newItem = sessionHistory.getItemAtIndex(newIndex); if (newItem != null) { - setUrlText(newItem.getUrl()); + return newItem.getUrl(); } } + + return ""; } @Override diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java index b7449456a8..0c9c27222f 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SelectSwapProvidersViewModel.java @@ -1,7 +1,5 @@ package com.alphawallet.app.viewmodel; -import android.content.Context; - import com.alphawallet.app.entity.lifi.SwapProvider; import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.repository.SwapRepositoryType; @@ -31,7 +29,7 @@ public SelectSwapProvidersViewModel( this.swapRepository = swapRepository; } - public Set getPreferredExchanges(Context context) + public Set getPreferredExchanges() { Set exchanges = preferenceRepository.getSelectedSwapProviders(); if (exchanges.isEmpty()) diff --git a/app/src/main/java/com/alphawallet/app/widget/AddressBar.java b/app/src/main/java/com/alphawallet/app/widget/AddressBar.java index 3d2b5e84fd..74d82b0118 100644 --- a/app/src/main/java/com/alphawallet/app/widget/AddressBar.java +++ b/app/src/main/java/com/alphawallet/app/widget/AddressBar.java @@ -16,7 +16,6 @@ import android.widget.ImageView; import androidx.annotation.Nullable; -import androidx.appcompat.widget.Toolbar; import com.alphawallet.app.R; import com.alphawallet.app.entity.DApp; @@ -45,6 +44,7 @@ public class AddressBar extends MaterialToolbar private View layoutNavigation; private ImageView back; private ImageView next; + private ImageView home; @Nullable private Disposable disposable; @@ -125,6 +125,13 @@ private void load(String url) private void initView() { urlTv = findViewById(R.id.url_tv); + home = findViewById(R.id.home); + if (home != null) home.setOnClickListener(v -> { + disableNavigationButtons(); + WebBackForwardList backForwardList = listener.onHomePagePressed(); + updateNavigationButtons(backForwardList); + }); + btnClear = findViewById(R.id.clear_url); btnClear.setOnClickListener(v -> { clearAddressBar(); @@ -132,10 +139,18 @@ private void initView() layoutNavigation = findViewById(R.id.layout_navigator); back = findViewById(R.id.back); - back.setOnClickListener(v -> listener.loadPrevious()); + back.setOnClickListener(v -> { + disableNavigationButtons(); + WebBackForwardList backForwardList = listener.loadPrevious(); + updateNavigationButtons(backForwardList); + }); next = findViewById(R.id.next); - next.setOnClickListener(v -> listener.loadNext()); + next.setOnClickListener(v -> { + disableNavigationButtons(); + WebBackForwardList backForwardList = listener.loadNext(); + updateNavigationButtons(backForwardList); + }); } private void clearAddressBar() @@ -304,25 +319,21 @@ public void updateNavigationButtons(WebBackForwardList backForwardList) boolean isLast = backForwardList.getCurrentIndex() + 1 > backForwardList.getSize() - 1; if (isLast) { - next.setEnabled(false); - next.setAlpha(0.3f); + disableButton(next); } else { - next.setEnabled(true); - next.setAlpha(1.0f); + enableButton(next); } - - if (!isOnHomePage()) + boolean isFirst = backForwardList.getCurrentIndex() == 0; + if (isFirst) { - back.setEnabled(true); - back.setAlpha(1.0f); + disableButton(back); } else { - back.setEnabled(false); - back.setAlpha(0.3f); + enableButton(back); } } @@ -335,4 +346,22 @@ public String getUrl() { return urlTv.getText().toString(); } + + private void disableNavigationButtons() + { + disableButton(back); + disableButton(next); + } + + private void enableButton(ImageView button) + { + button.setEnabled(true); + button.setAlpha(1.0f); + } + + private void disableButton(ImageView button) + { + button.setEnabled(false); + button.setAlpha(0.3f); + } } diff --git a/app/src/main/java/com/alphawallet/app/widget/AddressBarListener.java b/app/src/main/java/com/alphawallet/app/widget/AddressBarListener.java index db8a30b09d..9777710439 100644 --- a/app/src/main/java/com/alphawallet/app/widget/AddressBarListener.java +++ b/app/src/main/java/com/alphawallet/app/widget/AddressBarListener.java @@ -1,11 +1,16 @@ package com.alphawallet.app.widget; +import android.webkit.WebBackForwardList; + public interface AddressBarListener { boolean onLoad(String urlText); + void onClear(); - void loadNext(); + WebBackForwardList loadNext(); + + WebBackForwardList loadPrevious(); - void loadPrevious(); + WebBackForwardList onHomePagePressed(); } From ce2b7949c966d1eb2401eaaa551b057e65215340 Mon Sep 17 00:00:00 2001 From: justindg Date: Fri, 11 Nov 2022 05:26:57 -0800 Subject: [PATCH 145/183] Fix swap issues (#2936) * Fix NullPointerException * Fix NPE * Fetch quote directly instead of fetching routes again on amount changed * Fix NPE * Show error dialog when making transaction from watch-only wallet * Revise test Co-authored-by: Seaborn Lee --- .../java/com/alphawallet/app/SwapTest.java | 13 +++++-- .../com/alphawallet/app/ui/SwapActivity.java | 33 ++++++++++++++++-- .../app/ui/widget/adapter/RouteAdapter.java | 11 ++++-- .../com/alphawallet/app/util/SwapUtils.java | 34 +++++++++++++------ app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-id/strings.xml | 1 + app/src/main/res/values-my/strings.xml | 1 + app/src/main/res/values-vi/strings.xml | 1 + app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 11 files changed, 82 insertions(+), 16 deletions(-) diff --git a/app/src/androidTest/java/com/alphawallet/app/SwapTest.java b/app/src/androidTest/java/com/alphawallet/app/SwapTest.java index 57aff8466c..bf5fa26e98 100644 --- a/app/src/androidTest/java/com/alphawallet/app/SwapTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/SwapTest.java @@ -2,10 +2,12 @@ import static androidx.test.espresso.Espresso.pressBack; import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withParent; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.alphawallet.app.assertions.Should.shouldSee; import static com.alphawallet.app.steps.Steps.createNewWallet; import static com.alphawallet.app.util.Helper.click; +import static org.hamcrest.CoreMatchers.allOf; import com.alphawallet.app.util.Helper; @@ -22,9 +24,16 @@ public void should_see_swap_window() click(withText("Swap")); shouldSee("Select Exchanges"); click(withText("DODO")); - Helper.wait(3); pressBack(); - Helper.wait(3); + Helper.wait(5); + click(allOf(withId(R.id.chain_name), withParent(withId(R.id.layout_chain_name)))); + click(withText("1%")); + shouldSee("DODO"); + click(withText("Edit")); + click(withText("1inch")); + pressBack(); + shouldSee("1inch"); + pressBack(); click(withId(R.id.action_settings)); shouldSee("Settings"); } diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index 66079ed0c3..cb5d4bb3e3 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -25,6 +25,7 @@ import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.TransactionData; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.analytics.ActionSheetSource; import com.alphawallet.app.entity.lifi.Chain; import com.alphawallet.app.entity.lifi.Connection; @@ -241,7 +242,14 @@ public void onSelectorClicked() @Override public void onAmountChanged(String amount) { - getAvailableRoutes(); + if (TextUtils.isEmpty(selectedRouteProvider)) + { + getAvailableRoutes(); + } + else + { + getQuote(); + } } @Override @@ -333,6 +341,8 @@ private void destTokenChanged(Token token) destTokenDialog.setSelectedToken(token.address); + selectedRouteProvider = ""; + getAvailableRoutes(); } @@ -355,6 +365,8 @@ private void sourceTokenChanged(Token token) sourceToken = token; + selectedRouteProvider = ""; + getAvailableRoutes(); } @@ -543,6 +555,11 @@ private void getQuote() { if (!TextUtils.isEmpty(selectedRouteProvider)) { + if (errorDialog != null && errorDialog.isShowing()) + { + errorDialog.dismiss(); + } + viewModel.getQuote( sourceSelector.getToken(), destSelector.getToken(), @@ -713,7 +730,19 @@ public boolean onOptionsItemSelected(MenuItem item) @Override public void getAuthorisation(SignAuthenticationCallback callback) { - viewModel.getAuthentication(this, wallet, callback); + if (wallet.type != WalletType.WATCH) + { + viewModel.getAuthentication(this, wallet, callback); + } + else + { + confirmationDialog.dismiss(); + errorDialog = new AWalletAlertDialog(this); + errorDialog.setTitle(R.string.title_dialog_error); + errorDialog.setMessage(getString(R.string.error_message_watch_only_wallet)); + errorDialog.setButton(R.string.dialog_ok, v -> errorDialog.dismiss()); + errorDialog.show(); + } } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/RouteAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/RouteAdapter.java index 0dd563796b..65fc34101e 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/RouteAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/RouteAdapter.java @@ -64,8 +64,15 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) holder.icon.bindData(step.action.toToken.logoURI, step.action.toToken.chainId, step.action.toToken.address, step.action.toToken.symbol); // holder.symbol.setText(step.action.toToken.symbol); holder.gas.setText(context.getString(R.string.info_gas_fee, SwapUtils.getTotalGasFees(step.estimate.gasCosts))); - holder.fees.setVisibility(step.estimate.feeCosts.isEmpty() ? View.GONE : View.VISIBLE); - holder.fees.setText(SwapUtils.getOtherFees(step.estimate.feeCosts)); + if (step.estimate.feeCosts != null && step.estimate.feeCosts.isEmpty()) + { + holder.fees.setVisibility(View.VISIBLE); + holder.fees.setText(SwapUtils.getOtherFees(step.estimate.feeCosts)); + } + else + { + holder.fees.setVisibility(View.GONE); + } holder.layout.setOnClickListener(v -> listener.onRouteSelected(step.swapProvider.key)); } } diff --git a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java index b69f0f4a64..724451cbbb 100644 --- a/app/src/main/java/com/alphawallet/app/util/SwapUtils.java +++ b/app/src/main/java/com/alphawallet/app/util/SwapUtils.java @@ -18,12 +18,19 @@ public class SwapUtils public static String getTotalGasFees(ArrayList gasCosts) { - StringBuilder gas = new StringBuilder(); - for (GasCost gc : gasCosts) + if (gasCosts != null) { - gas.append(SwapUtils.getGasFee(gc)).append(System.lineSeparator()); + StringBuilder gas = new StringBuilder(); + for (GasCost gc : gasCosts) + { + gas.append(SwapUtils.getGasFee(gc)).append(System.lineSeparator()); + } + return gas.toString().trim(); + } + else + { + return ""; } - return gas.toString().trim(); } public static String getGasFee(GasCost gasCost) @@ -35,14 +42,21 @@ public static String getGasFee(GasCost gasCost) public static String getOtherFees(ArrayList feeCosts) { - StringBuilder fees = new StringBuilder(); - for (FeeCost fc : feeCosts) + if (feeCosts != null) + { + StringBuilder fees = new StringBuilder(); + for (FeeCost fc : feeCosts) + { + fees.append(fc.name); + fees.append(": "); + fees.append(SwapUtils.getFee(fc)).append(System.lineSeparator()); + } + return fees.toString().trim(); + } + else { - fees.append(fc.name); - fees.append(": "); - fees.append(SwapUtils.getFee(fc)).append(System.lineSeparator()); + return ""; } - return fees.toString().trim(); } public static String getFee(FeeCost feeCost) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 4112455791..2a6e6a0e8e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -930,4 +930,5 @@ No se encontraron rutas para los parámetros dados. Seleccione al menos un intercambio. Obsoleta + No se pudo realizar la acción en esta billetera de solo reloj. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index fb9fa97587..8d9585cd50 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -943,4 +943,5 @@ Aucune route trouvée pour les paramètres donnés. Sélectionnez au moins un échange. Obsolète + Impossible d\'effectuer une action sur ce portefeuille Watch-only. diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 64317cc410..25371f7629 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -943,4 +943,5 @@ Tidak ada rute yang ditemukan untuk parameter yang diberikan. Pilih setidaknya satu bursa. Tidak digunakan lagi + Tidak dapat melakukan tindakan pada dompet khusus jam tangan ini. diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 6bb18cb120..19c793608d 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -964,4 +964,5 @@ ပေးထားသော ကန့်သတ်ဘောင်များအတွက် လမ်းကြောင်းများ ရှာမတွေ့ပါ။ အနည်းဆုံးလဲလှယ်မှုတစ်ခုကို ရွေးပါ။ ကန့်ကွက်ထားသည်။ + ဤ Watch-only ပိုက်ဆံအိတ်တွင် လုပ်ဆောင်ချက်ကို မလုပ်ဆောင်နိုင်ပါ။ diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 8e4a6341d4..4c48f446f6 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -943,4 +943,5 @@ Không tìm thấy các tuyến đường cho các thông số đã cho. Chọn ít nhất một sàn giao dịch. Không được chấp nhận + Không thể thực hiện hành động trên ví Chỉ xem này. diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 050fa64e37..70be1b5cd1 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -930,4 +930,5 @@ 没有找到给定参数的路由。 至少选择一个交易所。 已弃用 + 无法对这个仅限手表的钱包执行操作。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bfbe8002b2..130e5d63e3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1004,4 +1004,5 @@ No routes found for the given parameters. Select at least one exchange. Deprecated + Could not perform action on this Watch-only wallet. From 69ce2f97db641bbc1a9ce2fbd0e71a8f0694322a Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 15 Nov 2022 12:51:23 +1100 Subject: [PATCH 146/183] Fix for video not looping (#2941) --- app/src/main/res/raw/token_anim.data | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/raw/token_anim.data b/app/src/main/res/raw/token_anim.data index 4dce3e0bd9..927ff79c4a 100644 --- a/app/src/main/res/raw/token_anim.data +++ b/app/src/main/res/raw/token_anim.data @@ -20,9 +20,9 @@

-
- \ No newline at end of file + From 7784baa6d0d3d5052accfdf4619443fb2b4b5a6c Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 15 Nov 2022 12:52:54 +1100 Subject: [PATCH 147/183] Fix for deeplink issues reported on Android Developer portal (#2940) --- app/src/main/AndroidManifest.xml | 12 ++--- .../token/web/AppSiteController.java | 50 ++++++++----------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 72f09bd523..ab525be802 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -76,12 +76,12 @@ - - - - - - + + + + + +
diff --git a/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java b/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java index 11d4e5eee4..c6750f3fcb 100644 --- a/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java +++ b/dmz/src/main/java/com/alphawallet/token/web/AppSiteController.java @@ -1,23 +1,34 @@ package com.alphawallet.token.web; +import static com.alphawallet.token.tools.Convert.getEthString; +import static com.alphawallet.token.tools.ParseMagicLink.normal; +import static com.alphawallet.token.web.Ethereum.TokenscriptFunction.ZERO_ADDRESS; + import com.alphawallet.token.entity.Attribute; -import com.github.cliftonlabs.json_simple.JsonObject; +import com.alphawallet.token.entity.AttributeInterface; +import com.alphawallet.token.entity.ContractAddress; +import com.alphawallet.token.entity.ContractInfo; +import com.alphawallet.token.entity.MagicLinkData; +import com.alphawallet.token.entity.MagicLinkInfo; +import com.alphawallet.token.entity.NonFungibleToken; +import com.alphawallet.token.entity.SalesOrderMalformed; +import com.alphawallet.token.entity.TokenScriptResult; +import com.alphawallet.token.entity.TransactionResult; +import com.alphawallet.token.tools.ParseMagicLink; +import com.alphawallet.token.tools.TokenDefinition; +import com.alphawallet.token.web.Ethereum.TokenscriptFunction; +import com.alphawallet.token.web.Ethereum.TransactionHandler; +import com.alphawallet.token.web.Service.CryptoFunctions; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.NoHandlerFoundException; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.view.RedirectView; @@ -31,7 +42,6 @@ import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -44,27 +54,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.servlet.http.HttpServletRequest; -import com.alphawallet.token.entity.AttributeInterface; -import com.alphawallet.token.entity.ContractAddress; -import com.alphawallet.token.entity.ContractInfo; -import com.alphawallet.token.entity.MagicLinkData; -import com.alphawallet.token.entity.MagicLinkInfo; -import com.alphawallet.token.entity.NonFungibleToken; -import com.alphawallet.token.entity.SalesOrderMalformed; -import com.alphawallet.token.entity.XMLDsigVerificationResult; -import com.alphawallet.token.entity.TokenScriptResult; -import com.alphawallet.token.entity.TransactionResult; -import com.alphawallet.token.tools.ParseMagicLink; -import com.alphawallet.token.tools.TokenDefinition; -import com.alphawallet.token.tools.XMLDSigVerifier; -import com.alphawallet.token.web.Ethereum.TokenscriptFunction; -import com.alphawallet.token.web.Ethereum.TransactionHandler; -import com.alphawallet.token.web.Service.CryptoFunctions; -import static com.alphawallet.token.tools.Convert.getEthString; -import static com.alphawallet.token.tools.ParseMagicLink.normal; -import static com.alphawallet.token.web.Ethereum.TokenscriptFunction.ZERO_ADDRESS; +import javax.servlet.http.HttpServletRequest; @Controller @SpringBootApplication @@ -95,6 +86,7 @@ public class AppSiteController implements AttributeInterface " \"package_name\": \"io.stormbird.wallet\",\n" + " \"sha256_cert_fingerprints\": [\n" + " \"8E:1E:C7:92:44:E2:AE:8F:5E:BE:A6:09:E5:CC:05:8F:01:9F:67:F4:A6:FF:E7:60:6E:DA:C8:64:8F:29:AB:C0\"\n" + + " \"54:5B:5D:DE:90:45:11:98:14:5C:90:32:C6:AE:F6:85:C3:7D:F5:72:75:FF:25:07:0E:13:03:11:61:66:6A:E3\"\n" + " ]\n" + " }\n" + " }\n" + @@ -573,4 +565,4 @@ public static String getInfuraKey() { return infuraKey; } -} \ No newline at end of file +} From 015569c8beb9c94720ff6db6996038b8dc4bce35 Mon Sep 17 00:00:00 2001 From: justindg Date: Wed, 16 Nov 2022 17:21:53 -0800 Subject: [PATCH 148/183] Remove PHI network (#2952) --- app/src/main/assets/dapps_list.json | 5 -- app/src/main/java/com/alphawallet/app/C.java | 3 - .../app/repository/EthereumNetworkBase.java | 23 +------- .../app/service/TickerService.java | 53 ------------------ app/src/main/res/drawable/ic_phi_network.png | Bin 88420 -> 0 bytes app/src/main/res/values/colors_misc.xml | 1 - .../ethereum/EthereumNetworkBase.java | 10 +--- 7 files changed, 3 insertions(+), 92 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_phi_network.png diff --git a/app/src/main/assets/dapps_list.json b/app/src/main/assets/dapps_list.json index c640482a17..a6c26d35d2 100644 --- a/app/src/main/assets/dapps_list.json +++ b/app/src/main/assets/dapps_list.json @@ -1,9 +1,6 @@ [ {"name": "Tbull", "description": "A Utility Token on Binance Smart Chain for Payments for Services", "url": "tbull.live", "category": "Utility"}, {"name": "Rare Coin", "description": "Free Crypto Faucet & Yeild Farming", "url": "make.rare.claims", "category": "Tool"}, - {"name": "Phiswap", "description": "Swap On The Largest & Fastest Growing Decentralized Exchange", "url": "https://app.phiswap.com", "category": "Finance"}, - {"name": "Phitoken", "description": "Easily Mint New PHI20 Tokens From Any Device", "url": "https://app.phitoken.com", "category": "Tool"}, - {"name": "PHI.Auction", "description": "Mint, Buy, Sell NFT Marketplace On PHI Network Smart Chain", "url": "https://phi.auction", "category": "Marketplace"}, {"name": "Eporio", "description": "The cheaper marketplace for NFT - Non Fungible Tokens", "url": "https://epor.io", "category": "Marketplace"}, {"name": "DeFiBox", "description": "one-stop DeFi asset, data and protocols aggregation platform", "url": "https://www.defibox.com/index?utm_source=2189969", "category": "Tool"}, {"name": "TokenSets", "description": "Enhance your portfolio with automated asset management strategies.", "url": "https://www.tokensets.com/", "category": "Finance"}, @@ -30,8 +27,6 @@ {"name": "Gravity", "description": "Create your gravatar.", "url": "https://gravity.cool/", "category": "Property"}, {"name": "Mokens", "description": "Create your own collectibles", "url": "https://mokens.io/", "category": "Property"}, {"name": "TENZ-ID", "description": "TENZ-ID is a Decentralized Blockchain naming system", "url": "https://tenzorum.org/tenz_id/", "category": "Property"}, - {"name": "PHI Network", "description": "Decentralized Social Media, Earn, Entertain, Engage & Exchange", "url": "https://phi.network", "category": "Social Media"}, - {"name": "Phiswap", "description": "Swap, earn, and build on PHI Networks leading decentralized crypto trading protocol.", "url": "https://app.phiswap.com", "category": "Exchange"}, {"name": "MonitorChain", "description": "Real-time surveillance", "url": "https://secure.monitorchain.com/", "category": "Security"}, {"name": "Cent", "description": "Earn cryptocurrency sharing your wisdom and creativity.", "url": "https://beta.cent.co/", "category": "Social Media"}, {"name": "Indorse", "description": "Professional Network", "url": "https://indorse.io/", "category": "Social Media"}, diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 689116519a..e71cdd3244 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -57,8 +57,6 @@ public abstract class C { public static final String AURORA_TESTNET_NAME = "Aurora (Test)"; public static final String MILKOMEDA_NAME = "Milkomeda Cardano"; public static final String MILKOMEDA_TESTNET_NAME = "Milkomeda Cardano (Test)"; - public static final String PHI_NETWORK_NAME = "PHI"; - public static final String PHI_V2_NETWORK_NAME = "PHI v2"; public static final String SEPOLIA_TESTNET_NAME = "Sepolia (Test)"; public static final String OPTIMISM_GOERLI_TESTNET_NAME = "Optimism Goerli (Test)"; public static final String ARBITRUM_GOERLI_TESTNET_NAME = "Arbitrum Goerli (Test)"; @@ -94,7 +92,6 @@ public abstract class C { public static final String IOTEX_SYMBOL = "IOTX"; public static final String MILKOMEDA_SYMBOL = "milkADA"; public static final String MILKOMEDA_TEST_SYMBOL = "milktADA"; - public static final String PHI_NETWORK_SYMBOL = "\u03d5"; public static final String SEPOLIA_SYMBOL = "ETH"; public static final String OPTIMISM_GOERLI_TEST_SYMBOL = "ETH"; public static final String ARBITRUM_GOERLI_TEST_SYMBOL = "AGOR"; diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 455d5e352c..5f36af584c 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -55,10 +55,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_RPC_URL; -import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_NETWORK_V2_RPC; -import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; @@ -196,8 +192,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy //Then xDai would appear as the first token at the top of the wallet private static final List hasValue = new ArrayList<>(Arrays.asList( MAINNET_ID, GNOSIS_ID, POLYGON_ID, CLASSIC_ID, POA_ID, ARTIS_SIGMA1_ID, BINANCE_MAIN_ID, HECO_ID, AVALANCHE_ID, - FANTOM_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID, PHI_V2_MAIN_ID, - PHI_MAIN_ID)); + FANTOM_ID, OPTIMISTIC_MAIN_ID, CRONOS_MAIN_ID, ARBITRUM_MAIN_ID, PALM_ID, KLAYTN_ID, IOTEX_MAINNET_ID, AURORA_MAINNET_ID, MILKOMEDA_C1_ID)); private static final List testnetList = new ArrayList<>(Arrays.asList( GOERLI_ID, BINANCE_TEST_ID, HECO_TEST_ID, CRONOS_TEST_ID, OPTIMISM_GOERLI_TEST_ID, ARBITRUM_GOERLI_TEST_ID, KLAYTN_BAOBAB_ID, @@ -334,14 +329,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy MILKOMEDA_C1_TEST_RPC, "https://explorer-devnet-cardano-evm.c1.milkomeda.com/tx/", MILKOMEDA_C1_TEST_ID, "", "https://explorer-devnet-cardano-evm.c1.milkomeda.com/api?")); - put(PHI_MAIN_ID, new NetworkInfo(C.PHI_NETWORK_NAME, C.PHI_NETWORK_SYMBOL, - PHI_MAIN_RPC_URL, - "https://explorer.phi.network/tx/", PHI_MAIN_ID, "https://rpc2.phi.network", - "")); - put(PHI_V2_MAIN_ID, new NetworkInfo(C.PHI_V2_NETWORK_NAME, C.PHI_NETWORK_SYMBOL, - PHI_NETWORK_V2_RPC, - "https://phiscan.com/tx/", PHI_V2_MAIN_ID, "", - "https://phiscan.com/api?")); put(SEPOLIA_TESTNET_ID, new NetworkInfo(C.SEPOLIA_TESTNET_NAME, C.SEPOLIA_SYMBOL, SEPOLIA_TESTNET_RPC_URL, "https://sepolia.etherscan.io/tx/", SEPOLIA_TESTNET_ID, "https://rpc2.sepolia.org", @@ -427,8 +414,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(AURORA_TESTNET_ID, R.drawable.ic_aurora_test); put(MILKOMEDA_C1_ID, R.drawable.ic_milkomeda); put(MILKOMEDA_C1_TEST_ID, R.drawable.ic_milkomeda_test); - put(PHI_MAIN_ID, R.drawable.ic_phi_network); - put(PHI_V2_MAIN_ID, R.drawable.ic_phi_network); put(SEPOLIA_TESTNET_ID, R.drawable.ic_sepolia_test); put(OPTIMISM_GOERLI_TEST_ID, R.drawable.ic_optimism_testnet_logo); put(ARBITRUM_GOERLI_TEST_ID, R.drawable.ic_icons_arbitrum_test); @@ -475,8 +460,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(AURORA_TESTNET_ID, R.drawable.ic_aurora_test); put(MILKOMEDA_C1_ID, R.drawable.ic_milkomeda); put(MILKOMEDA_C1_TEST_ID, R.drawable.ic_milkomeda_test); - put(PHI_MAIN_ID, R.drawable.ic_phi_network); - put(PHI_V2_MAIN_ID, R.drawable.ic_phi_network); put(SEPOLIA_TESTNET_ID, R.drawable.ic_sepolia_test); put(OPTIMISM_GOERLI_TEST_ID, R.drawable.ic_optimism_testnet_logo); put(ARBITRUM_GOERLI_TEST_ID, R.drawable.ic_icons_arbitrum_test); @@ -523,8 +506,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(AURORA_TESTNET_ID, R.color.aurora_testnet); put(MILKOMEDA_C1_ID, R.color.milkomeda); put(MILKOMEDA_C1_TEST_ID, R.color.milkomeda_test); - put(PHI_MAIN_ID, R.color.phi_network); - put(PHI_V2_MAIN_ID, R.color.phi_network); put(SEPOLIA_TESTNET_ID, R.color.sepolia); put(OPTIMISM_GOERLI_TEST_ID, R.color.optimistic_test); put(ARBITRUM_GOERLI_TEST_ID, R.color.arbitrum_test); @@ -1229,4 +1210,4 @@ public static boolean isNetworkDeprecated(long chainId) { return deprecatedNetworkList.contains(chainId); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index e76b083e8f..ccc154086f 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -16,8 +16,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.PHI_V2_MAIN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; @@ -89,7 +87,6 @@ public class TickerService private static final String COINGECKO_API = String.format("https://api.coingecko.com/api/v3/simple/token_price/%s?contract_addresses=%s&vs_currencies=%s&include_24hr_change=true", CHAIN_IDS, CONTRACT_ADDR, CURRENCY_TOKEN); private static final String DEXGURU_API = "https://api.dex.guru/v1/tokens/" + CONTRACT_ADDR + "-" + CHAIN_IDS; - private static final String PHI_TICKER_API = "https://price.phi.network/api/ticker?filter=WPHI"; private static final String CURRENCY_CONV = "currency"; private static final boolean ALLOW_UNVERIFIED_TICKERS = false; //allows verified:false tickers from DEX.GURU. Not recommended public static final long TICKER_TIMEOUT = DateUtils.WEEK_IN_MILLIS; //remove ticker if not seen in one week @@ -144,7 +141,6 @@ private void tickerUpdate() .flatMap(this::updateTickersFromOracle) .flatMap(this::fetchTickersSeparatelyIfRequired) .flatMap(this::addArtisTicker) - .map(this::addPhiTickers) .map(this::checkTickers) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -448,10 +444,6 @@ private void checkPeggedTickers(long chainId, TokenTicker ticker) ethTickers.put(ARBITRUM_MAIN_ID, ticker); ethTickers.put(OPTIMISTIC_MAIN_ID, ticker); } - else if (chainId == PHI_V2_MAIN_ID) - { - ethTickers.put(PHI_MAIN_ID, ticker); - } } private void addToTokenTickers(BigInteger tickerInfo, long tickerTime) @@ -512,51 +504,6 @@ private TokenTicker addArtisTickers(TokenTicker tokenTicker) return tokenTicker; } - private int addPhiTickers(int tickerCount) - { - //fetch phi price - Request request = new Request.Builder() - .url(PHI_TICKER_API) - .get() - .build(); - - try (okhttp3.Response response = httpClient.newCall(request) - .execute()) - { - if ((response.code() / 100) == 2 && response.body() != null) - { - String result = response.body() - .string(); - JSONObject data = new JSONObject(result); - JSONObject tickerData = (JSONObject) data.get("data"); - JSONObject quoteData = (JSONObject) tickerData.get("quotes"); - JSONObject usdQuote = (JSONObject) quoteData.get("USD"); - - double priceChange = usdQuote.getDouble("price_change_24h"); - double price = usdQuote.getDouble("price"); - double percentChange = (priceChange / price) * 100.0; - - String currentPrice = String.valueOf(price * currentConversionRate); - - TokenTicker phiTicker = new TokenTicker(currentPrice, - String.valueOf(percentChange), - currentCurrencySymbolTxt, - "", - System.currentTimeMillis()); - - ethTickers.put(PHI_V2_MAIN_ID, phiTicker); - ethTickers.put(PHI_MAIN_ID, phiTicker); - return tickerCount + 1; - } - } - catch (Exception e) - { - Timber.e(e); - } - - return tickerCount; - } - private TokenTicker decodeCoinGeckoTicker(JSONObject eth) { TokenTicker tTicker; diff --git a/app/src/main/res/drawable/ic_phi_network.png b/app/src/main/res/drawable/ic_phi_network.png deleted file mode 100644 index 931b13fcb5fd8e6dd34dac891c928196e37bbf1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88420 zcmbrlWmp?s)Gi!?1}W|>Qna{3afjmWPK#@CcL`2uaWC!;MT6582<}>1++6~k@Vwu- z-t+&v@?&Q9WM=PKzSg}qSWQI^3!Mxd003ZpkeAi~0D$mQAOH;oez^3WxrZN+tR<8s z0D$^L4464G{F=&AUPBoG@TCU;g2MrTm%jw>0stNy0KmQ(03etS01&%mx2p@oZ=hHx z%1HyBUw-*rr77?cRQC_cGN}L1(NToZGMf4i;SU2oNK0sWFCBJybsp~PuRjEs*jnkV z`W>x7MISELViWxkl>n9%j&Z-KQTmkGM2f_zK%0>pE+<$de-^@xVw5pT7KaGTPy-XwbQ(AXAb==<5uRYOG#-&wso3u&9!6yr2yGDEbd%aCW}*M|Ek z?_6!a!@rCOaXFY0X${dxn~i=I8!i22 z2>H!+-%}|K_USX+$7ig!+eAD;2}EoQ(KujNe;Z#JTn$;*976i42mFeZKOhM~3?%WU ztaB|_ErF9E?jYpd28Lq5TRJw8|88$MLTZ8dF9QlJZY0?ehl-HiV$lq|G$I9{TA|Gf zvOj?MRu|6eClXZI;KZ#8P%2|RBZp!DkWPni4)FYHp>c*mqi_JdpC9pt?drqVwk9>a zU_6;WLLvOD@Jq&eASZ%9@uxZmu#EHvfC51T7R1kW76z9fPOr{a3k@?2>VKvr{<|~3 z0egl^M4NyS!b;o!jw2xYGdpSI!G*=>wXBQVNBBD#8A0OUw{?WxiyC=wd8`EJvR#3` zwz>Z|^#+sK{Qozc^=`URkp&O-B5RdEUEp`c06aQ2Qk%xL|t!)B&U^Kw)9q z$r1&S5LZSGlkA9H7J_(&B#cBkAU6~LF1irN#AHVx^1ZG$X`L_Bk3C8;AX%|05KcX5 z+y#}4Zgu|#&K{gpQ4t$_LVbv#nm!8C4kC@#Z@FzvOi!7^blkZ9V# z86=M>Kemym?O#roj4p|+j@`>>mz~~RSZHC`BT+@dB1?cxsH!E5W1190MTpB3s)bXL zbEZYW%QUA~e^jr=Ps9{yBRqglXe#Xwkt=#TA;>Q*Jy~pe&;%*mO{}yQ?d_ISC{6&GyLQ9 zt;LDPJ%NDpb>%?o+qXxcb3qq=gMvZj!to~Mzo|A#%2jm3;F}}Nw`XUxf`u*DP%`Qu zmL%7DohG#DfW1`KdYk{GMr|Ngl|K-AI-2@09I0jl8flsPAa^=FWkNWOSHz09!DATT zBJ@yaW{_7=Mw|?aM=IF}r#U+LBU=1vBmSyCzNSpFgSDjFK0%?@Msd4onGoTs$>V6I zStbDAV$^YZpzSDk$th)AZ)uIwQ3;BhuujdLVvhe*uhaD4GoI!A*{SyQe1 zXO^*5IlrdqR$~jtu84axkBas7|?d%+i+ zxCtVyrDVq(Rpo2N7b z0?M=Q)d#N|MSr{YM9&-QcJX>n<=-q~f6XI>%hJOGv)LC?@>aw1Z$y{mZtZ0|K3IKN%R%NW`Wt1B#e3B6n{C zb{Y1*^mRRpF5;;^I6zPG=2JaP!eF_9T>~kF1D>`BjQ^KwXb5UM1$ilSo;bZZyYqCn zydQw)LyjlQ9nVxi6YY-sA+Tilh=0x}LL45tQ8zRx>`H|0-b$a5x+pD?(?4>f^u}Qr zo<~1ay-deede#@ZmVKr04t{Q71+EZvP9dvV{QFNC#5swAaZ-x^wM-tYk~MaF9<86` zRCSSW&4pjzl1djC?%K`YS=*g+uJ?S*4jC9nL}^5$t$y{U&s2k0&JM-@!)taY z)(^%JHOvH)5kG9Ex#~_;GB37ViNX??-@Q!4@C)Rui87PZLmk!UOI7U`(N`Q%Z;-*xZn zh1~x`RwM)*qrS|3fPo)9wfxcYzvsL#-uz{T+Er=ldBTGCAH}($Lcf0{6(ck7+*1%C z#BFE`kJd%$9w1#5_wP4Uy>jhcU#ubhnBTfF8ecoowqX|%8CyYMiff7|H_}e=I4Nf4 zs+OoJ#vF1>0G}0ZwPpUZ^&z1w0Pj^!z$&iSDo~~a$(21`1Yc0k&x=Lk*Hw~~QUmPj zjh95Lz|mVopNC;zFj|SlX{0}lnzEdP!|WmY;P0KM{eu1uZ`r5(M%BnNZ5c!vYZkKL z86<8@PBIc96L!h~ojNnIm?_fM9*plj5fU(+&HTInoGsS>$naZ0iQ)3m(eTL*1ywU^ zeNE=7N}?HrMKa0NY0n!lPlWL_?L?i6bDudWi{gXBL0J0lp`W5;KVJuk0Q%Od6X;j!%#}57N^NQ94rEEhts+A)H!GTu4$|LOU`13>b;t8W+~p@(DdU#0aozA;}er`4b;jUnt^3TOx$Up^Vf} z4XmgxjLz+Kw!JqQvrn_wCz|viUG&2W2B5w@#pqa&O zVBKj&`ZG!8;@^YKMBC?<-UZnhE~`>j_AK`F7*gFV=?~5k3cazgW+iJ1eXt8{9qK0^ zSI9WvJM*eBNPVDYr>c9XxO@wGWJP?8Xa__qP~QjXK1qS`Frxmmw#c&xYRoa}dv73V z&RFvHD?U$Q3C_Zz6r`5hSGt0i^EfZ5m3^Y7aRiE(@Y5u?l;`mJG3+ z2h~DV6m>L0A$w3M;$c;U+HyDwb|)ux(25k(B$|Gc40mG66~>=;;MK=-%HSfG6ZQqa zjEBbj!eWg4ff%WmP%R|z*RJ@4xOUZa@K)`v_qgA6!m4Rw;gR3b@_do%tKJExkgQjS ziu2Ub-J}T6n=-7snMkJbTIVmBfd(6LwE33E6Ein9e%+BP(9!koZB8uV$r`p8vFukM zYnB$<6n=RKxoh&Ht5}erC{-Y0gEDMM*AMzzdY5&j**;Ig67(5SwVpr?g#>OmEpXLe z;?4Xr4G7ax?k9e8vJ*+{`QV2y&k9h*v)EE(&lY=>4-*c$5^FwmpJ=+B%Vzx}qXL+C zDYr6OP800!--Of@m69cV`S(^V2q|SDSGZNUm$D~+l{UZ8DN8|s97iQ0+=KWh_L~rN zv&guMi$pXowF#LUS3_L^*D=AoE+8^$JuU6cFE9L2^>pH$AM6MJt6f9L8)$$pbhm!V zAw*Ltdrh9dM~0!$BUMA-$X?oP>+jCBdz#>r=I|%Ah^3^&`3iUIJ+uS)17-B*B5{7w zBU_B%gHq$=)$TVTSt{QSJwc3mblJ^F)6|CfS%BVs5+a@1?I^cv4f2q`znuoITO}dOqx;CW;}kxfX(m1lY=tD5Pv2dI*_Iv+ z|5OUS^;RRjIr|KQ-CZFNXbjMJ5V~;#ryd3l5Zuu+@^@rB#44Z#_dq0Q#IJXpzF#@o z%;F=x-vB29N5XOF4*e^#3JqpK{tUM?*bx=njQVD&Z*g|Q;n@r0e_k~F(zO{IC{)R# z8WF=lT~J}5tvzF)#aiY;mTsWt!EV_c%~W_?%u;zX-(n=Bmz=NKhE}Tw?Nup*{K+rhVvsG1 ziJCM_sM0ztTL`IzE+&~VQKfrm-^;JgTr2Z!B$C0JbF;LQSX|dGBwOacAb5pk-3mP# z^iUJbJ{Ddh@Z4tO2@~KQH(Nj}CdId+I7xSsiEmmL(rsDcA0+TUVSyxITy%ycaHB(2 zkl1e*Nrbv7B2Y1=!tNlYrD!GrZ(&Y{&{`RSW+gvh%50$ToZ0+anA`uGvs}&1*r|4R zxdUe|X`l2*@y4&SEYhh6Aq5rCUA2hG0`z7(g3%qx{(q#Abp;J`!{n|xf6_!%7j}r8-zrW_i|W8K zi{+eegdBNbs193Dma!l-I$@h>U=ZD=07vtGncR!1CkU~n0#sa((xz*0-zjk>%#a{8 zp-%{)2Sd{k)XJl)owz*z`u5ascQe_WsPp#g`gD^LekXEBqt?Nf>@heasn#YTui?4S6kM&uAE|sVw1Pbs=y_b#&COMp-U|%`iE^z7h!t~kF)rL)0u-n5I70IO4 zslt&L4|;C9rUZE$*|my13@yKP6lEKA%)4&NSg*k2k=&m~xGGP|r)UYKx!}F8bZ8C3;cz>n+Tq6JQ6J3_>Dvtf?L^* z`eM;!yfl=~|4F>DR$>o+!AB(Xzd-Lz{Gt)?nMRBn|mhHas$fE@dwg z$6n6kHFlf(Wc>3YdFDNRt-ja#tpMP@u%272Qt*y4i{6`)XSYJjL=@y7UD#j;FFA$% z=jjntZhJh-Rg28zT~xX(^Kz2=^YSK_P}Wt9)Cr+p=iIE9QsxUOQLLVD^(U#Z}dA=)PI}iTCt#J%@0zmbA~5 zJHmf18|x@Qk{VV7fai2MJQgWgnK2UXz3MrlG;AMhmiGduu z*1rZQnHssNiN|MtxK#9xeiUEW)#8g$Ah{8w2;Kp~nKHzuT^|4Aau> zd+hn;)Kg;x0y>qo48yY{N$&HvNNWa7o4Z{VK-){y>Re#A(iar{&h{ zg>0G6x6Rq|s_^K!VqV&lNiH(4j&KZV=3AB=`*Y~4MNFJcpRqk+8H*=3WiIAUA@AW_= zDomE?6y@>U8n{opdr<@JT$f$t*89yDupQk z02vig4gRqYSYF*$3*LmuESg>>2BtVnn$rlS<1_Dld{ZxoGkM7Qa0li;1*Mg%N1HFs`p`4DBr07(oitYk~mj89{^ z6|4Sk&2*z*GCjHLva=jMA6~Kyt3p4UbLErT_z7;Jy$Q+t?&zftSaGf3?Qf6Qo^!0w zAm=j1e`pJ6sJu+J`;GquzR1s7`I|W3_V!{ugo(oQKj)uGcZc&^V#jSc(_;JI`Ud+G`Gmqd3i!(nwv(kd>X|#I=l8 zzf|6lS5{wpc2fQ`$buI(9UyE7gV|4DlShdJw@8Y12G=Xk+yNWf_!R;k_*PN7%>Q2%V#fH_8Z~{#?c5CWm zwIe)2VutJLfJH%MEXW(1P27dK^7gLdFiSSe`8FqhO^KDKl#M4n8w=#%-;h1$E5vKs zfmCAW+m}OvV1tXi)w|FJ&AcM4kfNW2mLPSF5k4(>_;W4sxT35|8vC_)j7Wu-Cn|W~ zt~SzVH(@-!4sQc{QXqDt2qV58%J@hA5#yrjmzNJRibnqEs8a2`;L zU=q^!%At1NykKK_fIVNqXVsjDyXqr3E^zSfPEIy}e(nJ?(bI}S3FGoFa#MgcZqcJHH*&y|!h|F4h`r)e>}lI> zZ!3?-{_n8}o<~(gQ{WT9ElV9XL$=~q#+M=s3#)&&qFKN}W27HF%^34zhRM8WUTCZv zDPqfJ48dv`hEit?^0-==15d9<52w|z^Gzk666oIML&nv^4@7{SRHVm2WnA?cr!2RY zMyzKumJ0e5nLn%wwHd95mH2Eg5Lw_c2%q9Etx@(URQi!W1d7mu;E&!`mvr+(8vHE= zt~_ls8=EYzYLV7nbyDaxs-Z5Q#?Ri*_HY>_XOa+4&pU=D+CP6-_l=?r)+i^TpVLlH zFWb;XBFDe9Jqi*nqN;whHbjEwjO-doP8cR!?I&3Wf)`qKI7`n6g2f(CmYD!nbqn77 zQ6Qshxr8g(CVrcOgK4ie>&h4qCN_huPuewyAzORyUtezLyJW0F{Dt=c!CzIcXWaUs zg_?e@&Hw4x;Boct@sZ~I;z80&(9~qGH!xuOz*?;A`jV1|_|NJE-A0rv{WI5CjWk&F z#Y-!aBCxR@Shf|i@N3rbiX$qysPxA>m&KGPl{v4|!7RhY355~uhXY!itLt5jzs0cs zkQ5GYW3>Xgs`D_qphXKpsRO%L|3QjFInTN)T+bg{N zq}qShX-7x&=zE^KEr5@>Ny3FLPtbY>(HV{f$<;(k#6YAprxz#(;U#0H6Z8h%3cJv_ z_^5~3Mb~3t@pX6G#qBU%e<^qj`FSl6=LNu?f=6OO~I*t6C?gQHHN7xwzzKHnfd z$4woY77obt<~`%kDO3pxqryl|A0SsUm?YV{Co`p)y_tso-)vfhkfHc<@edBGYUb_> zQpG7->4eI8Dx^xKMCe`T4~?3aO?11C7I9Tf!8wOWm1fmh@LG%lNgJKbpSdg?lvEA? zITMr1ld8jnu(>_*>Ua86(bxLSaO_Pc{{?vbxMjYv6TDuMem?m59z(hDK%{xXl(`#V zFB{O}SjEM;O-;{sE41XLHAwg3+OjI(h)*=J zQlIeLbGQUlY0tFm6ESkeOg(YhAPPMME0dsYgL@DIYbS(E3J2&SUxXkzu?Oji;WR}C zldlWvtEn2XIX*wTz^DFcOB#7SjHBdR82*#`TtE~Ot>S~Hym;&NI_qtY45UI)q)7+F zf>c0<_LWL4Q@MB%?_44usQ~{xIrSvm?_7BKV9GX8@pjx3Ex~TVKcUe7c_+klc#KaU zE*!BhDBaf)IY1{RJdQ89du3%k>kTFKJ9wm-5uTp9Wu!&u3i6D2F=zG<_I*w(OEx}gApYN*%_ZEXR2@Qbk5EChZ&r$R z{6IzSIv!y0B;L8>n244nhEC30Ual6J{KD%gP4v=gP?;y__S%LN<#Ct4$-Lm~E0a0( z_A|<9)YphWg|F%SFOiLOkUzn#1bQ7X+q;5VQ?6RYhz+lW=d?sSvjG3^6=VvHXJFa&r1MDrb*wwy1 zKkFM+Si#}(ZSV{CCMi)vdh!84mrePU+JH?-x0IcEtAlZt^`>!JN`rXYqgDF5T}^fA z?DuckW(pcjQ#qhSrvtLb(fh4`4^U8cB0bjW-n>Iw6PX#doL2<6==wB8=c0b)KXGO&Qw!T zAR=d`itXO_Xy$4g6oIKzI8dDMvQSQvTtF`HIBQ3Ms|#9DZ^O(e#))Az#j}3o2Ym`W zlk6%jrkeW+@;>79A38IL6NgsTYeu9$L;oDZ%cgYyRdK(PU|NTuW{4r=2aftKi4QVt z))U9aPC8L`67vqPp*9V!jQ@&Fa_m9@v5yu)V0*rGJpUA?A;#>G)I4~111gLq~7fK?R)R^Vz z^hMbfgRMc&aVL9r{vW{Ezpf~G_Qk%liXKxHw&}SVqd&u``Jeicyv8!}+3=B&nxMCv z`F0wQ!~gFl;R*WdmHZ%@joicy=IL*dpNH-}E8d}1N+CMB$=5ST7c%bye870f|1R*R z`5*bhRc_+%kszRT?_1xnyBfwNZu-&JQ(K(hdYyMX|H#cfln6E<9YCB|(l6qeevEI+ zAk9NH0VW`nx`t#7hLff;x`JN7G=A(U zYi<$1`T&CrARZk8n?Gg{vfLEk#>jG(YfT7-KqbTtVhQ;UnHJD+Ntg;y`-3L~x3xx0 z91yaN&)NAshzystNG)pNR$^2HNR<`_Oo1BHlv-`px3?Y>fZnR}-X)@yS@3G|^NWkqT*lQQCTg@96vyY z<~|djI+>yKA6;xgbc3T@T#<+0fh54%FY%ooD~?g{8lk|^)2C`Ev+Gix{yu(OUgd%g zy4mR0wHB!ztyOZyb5T!DltkQ#wXN+L;BE}}2o*{pE3j^bQT&Geb-zAZ4PrNWI?Ah! z6=YLjcT6mufXp5jW4*#lJ(`)6&RO#**LrQ?l&Tp0Eh?1w)c(X|~{%(RPXNPmMi0l6!M2-wD%G_Dp%l5DZ+A&gyj{ zk@G2$ZdO+34339?puiJ>U>c;vtt!M%KmOn`qrBv)E7Ss}N7ax6mv^S~TZNapHF{tp zKz-)@pUj8Mzw9+!8~Hk+fv95))MrE9YWbY$beKRRG;c`D+FZ$%+zyb+<2ivD_MQ`a5R6L<)A zoheo$|MVI;CxqABSbo%ovC5xZ+&ONOMcoS^7UzcL54siFpmeQA`b1?8{`3NM>9KJL z#P6GA>s;9xiJLl>t5&%%Rv_pQKy5U#5^Jr#9UM9D=UHx;s#HH8B5uFY=hj{B>96ty z;>Z!Ul{EW{soVyU-r8qJYygmz7_|$fabFa(IDA9la18^7ztJpE(DMa$M;xVA&6xWa zZ9V}dhhWW(^U*qf`9RNS8wPVVSS`ZG&L@2!4`UJMg?s~0E=(JA6YF~KVn7&NK5lS) zl9d3{y_iE5iK0(a19cD`LMeOs{NH<8lqjAA>E^ z7v7v@_aVP5vWzjE5sSk*H8=26$n;~%!zJ_%>duY!xP|x~t;eLV$3qxwL9Y9G!m7S( zqWt|SVjE^?Vrwcx@M5uOFTCLS!Zd1Xfu5&>;1dY)g<}Z;(!^T;80@aGeces}q|;<9 z8yx76_g;40>xd&yqWRn21fL#@@zvnJSX`sJ0})6M1R4A3{pq_6oZ{I00pN=D%q4{2|;FmJU%_LdyN)Se&1%-z2))U#R)@sV~sde(9^;6j%Y zHsY9o^r`7}%0sBM4-BpLy5yt-g{!&^L(vI1%k=M$&I0I~MSS~7v{>y}Ey%+?bwDK( z+xiY$m{S5069VOdkBsJ91SS^*;VJ1ZD3gHx;)fc+utszkCtLL?V`W8=B)E8>_+C}J zP(Uk~Jou!~mVMrB&*s5SxJi&jut}%yOgXZ7Ij&}vt=%*0OqL&uUF_u&WEBSDSbg$s$T39OXR>*A!;8=y1gz6pjO7g+adSsD0-l(_5jD%mSOeI z)%Ws{W%tjiia(;6Kh|a5n>V>)P7B9_7;qg;GzRiP!pQzj&B8JnDtZ>VZCX!03IvIq zM(@{J5!b_~pL9 z=gl5Mv7Q{_JUoICDS(Qe9Iqb`xeLJtlKHJa}Y_&G|cmRLU z{7u=uX6wzSgY6-m7ccu}J~ro_o*Xglt}&F~m98SY$FJUh#cY+z1Qf{w_bfkNpA?a| z7^CC9&zHg6w{byO7D%Y36t^~!wlLqtPm;kRsE++gWV2^yd2g1I#Z@c}-ORvG`%(?CCNFlr+Q1>Fod~!@F=IQ76 z%V2^+sHLp1W%4ui>%sA38S7jLYf}i%E6Y9%IBfClTmCCyOc>i~S{qOb9=HtJ-Jvqp zb8xhwJ+&e_Bi2|DO52gEx@X z#CN#Oz_an+o*-#@B)5=wh>)vWf$0!>ppNuJ^MSD6?5uXzMNQ_~O#`)4PqiJ}`qA&( zbP_Od`t1kRLqE)=^HC_$FFA@_tM!b0V;%;mLtYDxyX^xh5z^D4H z>%0YasCC{Z9?t#sQTdTqa+FiUm*X@l;F;szlVlb_S)nJ9V=is>YHW@VFemV}ZD%-f zcE6b}&tx+^-jOr-jX}$<4#tC^2bQPl;oL&T+V(%LgB(ov@!REhPwOU)I|BT6jHT`? zbYHnaMR?5a<1Y8pFi^Lmc&~sA+)x2HO z^c+3%&=1Vei-n=Uz6`ngX;Ueyyk4ZzGo5@7s<*(NC>kL95WC@jmGQPFbC>t9X990# zW~Ea<3eQzp_7%4-=h~jGUxfU(R{eZi+ED{5P4>|bH53xtg^SPvs1ow45JRMM2`x-m`)ZgnQ$`g5Q~c^Qu+rh}BE?U(A7jqgBpXT$CR9 zzjX#)m&#vb9Z}wk%{29tdU4m-L`WvWxTkX1;}dA8KetZQ$*HDcs z^lSVlSLzjdhW8mj_oEc^?!>D-yuOTwp%JM>G6dU#ocWqAq<}+`uB9oR@D>jUVsqi9 zeqVX51v`wF$7BGBfs<@kp$-!X5(aSw28C2I!?TCJhM>DNM$7|O+()s{-&>}0?2OQU zr=MA7AY zlRtQn&p{lDqm)u@8eL+MS^3tBb9=-R409Q$ky(|S#y7Kn+q0Oh9%Z+DMDb+dy+Un6 z5!NWwZAZV%kK29IC7Yi~p02_APxVJABQyZk$#m;C(T^zdxk0(hfG^8LlDF2l*dsWZ zXY23WPu3ZZYAF#$=nx-=ev*CHHB96bl$QK5%r_yhffj5a*o;ar`)+bu!eL9ltfvSs zS2v99!0Y(^%3)YfLRLs!c8vEo%lBe&bla%dZTJkg>!Vz3i$bEuiyg;guTI)J3e!v- zKOU&8S88z-Fikr6yt!y^Sy$kjOQln)?#smO=U){W%2ZGJ@(&pY7_yVVcefkH&C~xC z;AsCKf~MHP$}G+rZI=)b9IAipz6ApPh|{QB4YJ$JZgQ#C5}2o!yU0pLcoe^$>v zWw0SiH%*8$4w=!V5?1|e@qNw{6Q}SxdtoTH@XGq@wmGk-r+x?8D}@spLTfkWm@jf@NYxan{Pjw>4p@WK%q^d znmY$g{`*jg3;A>ZKU)RCR9q}W>mlXF3>wQccCt!kjiKXqJU)}3`^YwCAqT;vMoVUv zFFPmBPItuMI~c-UjVPWIw_vc}M}vI>;nt>SF_Wi$-PWP}o#vy53&%cFnIg`N1bo$% zpLffc>r#^RGilTxMjW+2ofM$x9+h$N;prpXgC06tE0Ye0QAeu2B|zxMx~p>rBqEh&1Wy^J*Nbb?eJA32HHyJnl*>HSoF2(gSa^wloHhb z2NOTDiJtf0TF-Y&nUSfa=^pkU#(Q%KyngF5Eyt+z#hLU&M=j{II+{CF6zR7i9pgg7 zWE@dPKOX6Nlr22Tacx^azF~KIKY=nTyr=Z6uM?RdL+ulp{0|^q6zRRp(R>i6Rm(9q zL))a8fAxu%JtVP`@SIhE{|`6huST90*aDuze@k?Ps3P_NR|dHn_A#+Y0~Wi!Z$e?C zR*%JS^x6OBriM4oScjKT%%p{`SyfpeNOYqwg5zBgo^glrUq_(|`iQJD%`evEziO%p znT&Okj|2aQA^y1Klb~TilZz$wM$f+V797>|^Nxtxo&HZk zQ35`NAGl{)?u4rKhnJTWv|oMTfGoOEqbBgQd8+b$D$EP3g9RwTI^D`0Yn8(L7X{xEV*-pA>sq;ce zzbN4Hwim^np-K61k1=xL!>K+y57bU`p{}5B2#YYG#R37-y?Ek- z6XPg4QtJrD-llT zx^lLU8H@V0Cz3oggS|Ve+~S&xw}65TrYqeDGp1UHA9semx)OS}A*);(5XKYP%_GT0+?MM^1HerTJ$zO@#xhp;0C#b6Mz)c3vU zRRr}4OTaTqn{Bx&ia1i2h3Z)MQT4&)L$`B|kzc^rMW+ry&-Nh3r)ICU-CXv=CGD-h zU=(u_;^Q1qdResgsA$lS1x46pMzEAzmeG%nOeuwPX!%9gvX7(G49_5i?_8v+DADfI zj%30cEw|&Qt4t53kDYanWky}ITdX&b;qIls3-6WFE2nt@Q#+G$jFvq<69S!U5&_6V zM>0UXq(cCjdMpnE=hz21^n^h5S*^NekA+ENo_P~Q`&wC9_I|B-b0y>y4%$JU!!i;n z!Qfiv{KO(1HXlbvdhrKpyVp@en=>97dksj^!$&YRa6EgxCteW%+iso==7<7JBD1>v zXX3Hz1f9!k=>2Po(mQG`DJJ}bB^sUzJpg)|8?EbxNdR{p2{EYVi!w3;Q6`y|U7vuR`5S4YfOzsWu5?;L-bU-A~W?Ogg z{@q0=dOb@YrNS)xM~wHuz@tOBAw0;_5bCFZt-(RXJwo&PJrb20+VViw`viWs*D9jn zG)UxiTYfe*9SCzqQKX9@XR@3YIM#1=1AgKoz{*n&ol-^v4p~OK^Cti|Rf=gSl>G0T zjG0+OPP$8Zg1!{xx6758I0;HsI|3!LRobb)!YBe<5ueHsoDl*OKILD<=KFcx^=7RLSUmqEm+O4!wl)6b5YYU+ zflGCB-R^?9ujaR1w&>)c9s-`RZ>vZ6$0<9PeJx0`C6?z&#m8aHq8>RX18otHsr~PX z$k*I?w!1r`^GOVO4!<&{3!INuOd;lFj*S=N@qLEJS9g`QNQYv!mVX$w?xkvE#U>uJ zq}Gq0mfWg3>#^MbJwyKyIN&>PGp>!Q3p{}@wps%IY5n)|aIX(OWY zj@kbY?eg|hdPyy3ivN-`CFuM<5N$lE4s(F_)|*8}i&Vp4sE!d24jAAVSC$#~uD_e9 z;fw~~%l9Emphe4Hk(Fx&ewLT(=|@QkT69o)_Au-F?pY3oV6}bi)!p1rJT&Zcd&dc{ z$kuh%W55ko7G2F>hS1~1J=FE5A>4>y_@*{b;#v{Vv_QoNYem z6|GN?zIph=^_5#* zhQGuWIyTJfjR!yv=A|A~2VV_r0h-c+ z=VwISAKEXdVia7dEAW&ybNq--RvLGE6D^}!D~$aR+@yU1PkyLZ4-CkiujohJjty!pWy{?#0QJh9<%r&z zs2d}tGq0Sfv)eL;?mMK1Y6mNo1o%Uk-?6TWsSEbCF^lGVtSyCS5ciJ%wRwCu9psm^ zOD4aBC*Fr=HV2tdMsaSNWytMMkCDM~)JHD*M~0L9i?D?248LFSeA|HIsx*G+l7T!| zr1_(?xC`A#5V5z|sXe5eP9PBv5e|O;#y$uRN?_h?bOk}BS{=_rTRQ^>y8p$~tc_Qz zoGwq;#!O}n0!p#RIXZ_dr*k(iasFaFuZ093S2no1MR*)AWecu3bYZ99KQGJ$oYiseoBO#ot zRqsCfM3Dz$628+oAoJMSYewp_GFt7$gn>62Z<~M75W(jRE5SA|!S0<@ zEq}8nQTL=0dgT=xXZ)_4wD%(l_E3V>E;O6bCU8rxQ3sOafDSIgPk+HED^e~=|RM%V#k62L-_Uep$1S0-m1 z&dsr~S+Vrjw5i>+lueRoqvG-=TG!pMbux-O*JXQhzXR= zcHiG!J3o~;iQP}yQh4WY=7^BX#@vMVEmf8A@?T6Yac;t`)+v^73%`;}@#t6a_Ev`F zFVf~oO^_crv4I~YY>>xT-#XxPHz)4Th+dvD%p{m9yKVh8|MTiBvPFrilcQAc-ze+Qdt&nLaW)X{sY|m$&EOBDr|{1zAuoH}S+KR>z(WSC*0>^tVrtGgY71TuGg);y18| zXsIfX=Hyaly<+RB>P#g+2lw~uJ$S1PC9IbvQ5Y}1%P)(VaD<=Ih8RIU_hupbbnM1g zOZZ>%4vWqOvR61utTD}Avi&r>XEPi)GYJHhtjhtWv@-uOmNfL2#yVnK5}SyhiB z8Mz5K&XlH`6s|OQPyTyaN&X)|Yych9uOz@t#{vxToCZ>ZEdrqovVzQ_uO zgsjp+j##QWzdKHW2pr}qZ2}^xWR;HA?3#TQXU7A(C$nLzdv#|v{R~E5Ld|u7&u`kW zbn7n%ri9Vyru1IT7PEOcK>oqEXPFIaWCx#s0~VE=x1p;&IwwIFHlKEg*5&YjiPqy3 z9jE`8o64?7QvNiy9mDJ__xZUOYvgBO?um&*X#$@`;HhX|&y}`|l_!FTpH4q2g$>{H zX`=O!>63PU(B))F&~}_hBQ_gXP1pFAUr(t;+|M4qZ!ryiu?364Gz^5zXGqP*eo3n( zT@SXNhMhrcgQRV%g%3TUT`ulF315Lq&*=XTM_1v{x1IHHv0bH+%3hGiD}Jt2V^_!SVjjCh&}U?pT=F< zOMQ)d%^i{VOnqAq`*zGp`k5=NZ7$+%p(!mtDSM+oFEs=d8UKzl>KikA4LOnb^-NE* z<0B%p0+uU)o5#LT3B`%}Eh@V6J)4M=3?CZ?T>tVsX8!n8L`$RUlK%di?B9t^6Sib0 z!o53jPhR&SBH=lUveJ(7p^EkaBh8f60_|@oA5XY>g#1aM#$CR+K%w#Wp9sulqeri2 zO{3stLFCPThfM_?7oj4K`fE*o0Wf6zsui_tiVnP4+(_EOa3b{M;uj^Xrp@>3z{B!K zhxNzbd{LDPXWF0g0B<6U;Mq!Xur1Zm?D$!dZE|6T;*WkQK?z=nKaeLuyy{{@wILg% zL&UGE^g2{Of7fJb`>FnI71aH3WwWgQQ?{qxZ>^y96D!C^gl%+$GdExFOm5lU4U1`1opT3dMY6=V2S{ zQEge7P+!s7VIBFI)r+o5%3tAN(tFI&0ZCNqWqn7kNc4XD2Sxj@M0j`;bfb; zmb4qK-S7_)JvOrFzb78sTo}7wbM~hixxY!Ka=gD0T<1|~Z~W+ub-nC8_@+_1mY z{Bun0rr9l#z*y+{>RgEJ8+^1c?nEjKd4F0lKJZAg17c@t1$|~{A;R{|(fLjQ{pn^D z^hIUnv$WQxqM4uMFdsFRwt>EsH`3^Lh<87pxEB##nM4109#pDCRR~lQi)pF8f7`_x za`oP<&Fg-ni*#K)Q6FD>w{OoF5+2&x^^BFd?xlGI{(U7kf9ribp5nmbAex4THGHO0 zD;JN;-@I0;<*ay?!a8C3V5xXKK#9F;Xg2`K6~nWA`VtH>)D8gql~s?~!@N zwefc9UvLWKEEJ@g5WaO)bQKSiWsktXCUR<_T*hC@Gc^}y!8M(8o1w@(rypPKWXb=f zeD|+3yg;Fh?opkQTYkB${i*&Z`<4M)UM-x%Ce-!txV3tMh^DVi{g+Gcx2hM^|ND`8 z6mDPr&hFIe{AL6L`!&!BM6)a{$>{cQMxkud@VBF#Lk!NMznxX|E;T_O(NSMXOYAOaK609=nS{I^3 zGOuP3O9P5^06C;Q2QCxeF@rmp@V*Fq_Z68(H8VF-6aIZ!y6-%f%F$!oGAd*kGe;o^ z;o_mrof0Y|H&Zcr6yD0p;J62d!Nd33imtHuP{Etw!toFTC1%t8i!zxrbgzjSw&S9j zu_H!jv;_`eiR8?U{VdF(_yw#gG8ice%zO2D%3Ael+U;k&=7Hv8jdY?k9v2$1iO_Uq zFRP(ZE)&Q_F?|8UK2356KOc)5E2cd*!coTIdtm1CZ@t5*aU;$QdP=T=H=oT?D@edSYjKm-#w~Etl{+g*4dDO$fXM{jswkH? zAc7%CL2M5;B~d@ufulRV;f>$ARx65`3LxfK6Lwts(4u4 zhQYTfOLC`A0j&Ah=0_L)uKm83<|^SM%; zv)$caUfWBa$I)mHc(3+y(;BdJ4H_>0#kle%h_6A1j*;XC$=PQ! z5%{1JyAUN+5`7Q5O(w?CA4wIRuUCv~*zfcarA~6uFlES7`Vx<`ohY7c@Nu?)2{lx- z;|_-Q;vM(1R7@``=&-G<%O5V~(1Zl%o=K&j0&$jUs<2T&4fMj?kay6rWy137d1h0S3R0l>Z5#{{TF?lg-ayIwk89MjWbtN z5VGX1KLh;0Dodq^1lYiPv(Q7!0XbDnuc)Q(#V_TBlw6aOyJC8Xai3QDXhKsf>U^+wO%3?0dVUCrzwcS7ZR>H7#F8b)uj_-r&)zk7*o-Jj!xX!Sy8jnvEtuxNK z5}{)DZ~Td2_ivSdLV`00b*_R_!J!X{L0xTOVS!6whd+y+`&4yo2cf;~kht(J<8Q)5 zCYt&-5TL9N?OZk89Zn->7k<|F1n7G46D@8DR`_+_dIdz<^-if1rr8R3?T|ZsVC3O^ z>EM=BUB#&Xkdb@x6W+V*$C$+H{CJGtyy~ZD%*SJ&^3&&n*RA>-Yd z3OtKlew}rGYVu+F+1YMa7)X-LU;3zy;wSyOTvuX5V+%@$B!D|%`6siuk4~R=iLJ~a z{=*{&5wk2#x8$lfL0oVv;eBc+xsa^S!;Asd@=X%1a zPUf)wuTU{Q5>;X!eU|pcK5j_<^GvF&4 zLYIYnh<p*xgw@v>rl2?CuOzI+5@Bnfb|px2U&B=PWNLyK`=URG&q7 zUt`ewvIw#G1E$K)0g)+Z$r5nS3@%!DAzi5zY7>fKJ7hFiOL-8-Pw$!k9k6xpJ$w zilIwOG`O_0o-`ar_v+lG{8mfdEEbhk=T+%~ym)317dHduNwuvv{OQr+%n{(p_>R+T z+>QrA`aN^eE`$cTD`#)A9YlqV6j}n?o2(9zvGH9v&5d@HHaF`=omz$Kk7Zr{QDWV~ z3-Ioo?~Y@I80}ev$c)+(vvC<9yXQDOZu$936=I031NNv~g5C!X zffXRR*IH>5+0zu-{xNI?qPxo(|EGDp{&79fQSr2v8(oR6X}EM%B12Dzn!-`uD6W_0g?DuAK+dV*{s=w! zb%?m*_g4)r$XjoNIBkh&QjI&`skO8}+AOb+vdV|YrG%D8lV2EP2L_1~$Vdx{gF9G2 z1jDs%0FEgWazwOGAPT>;;t+if^}O}BBR9?ktG9=r#-&a*BYbSCTiu|^;P-P|FM#2P zk{cJqADnTQ&CA}R!A7`xHTFaPqfaZWmh%ogF#+xRt3x4W@DhO1_8n}Cr zm*oEw&|~ZgH*q$IH6Bumn+r8hjyQreTo&TFhc3{{ug42>EE^LxRVM)j;0R{9@~d*+ z7jpAkkex57gI(K7T`4JFA3VosFUQBPf9LFN^Y`7mn>dnqS`$s+gumyCKTKku9A~1F z$4I9-g;q$xKqthgW8WMUb7UH*aL^>3eJDNh6`hB@i)2O`@!C1W!Ekvm_V-iUQcJW1 zeyAFpE^$QmHqocAKSA9(VF+8whi9kCvaaq*!hAW4+m?l)d_}1e4AIFP!*fGk>a{OQNvp0n0#vpTaG`aI5_!fok&@y}Y&>Rw(Pm+bT2+XpWJdkb{Z1rD zDuGp>W}JP?mb0{Go5nY@J_(UdV^RlnCGb1Yv9)6VxpA-t(V}O)`(L3%56?<PidA{8!RwJ%We$&d_1O%X*aq%T2)tnH zem$Y(K{F0sk96~)vj(yI37{T~e2YBO(glcd`Sf4iFn1u*=+1N3S_g4+@d3jgYw{bc zFJ7uxH-o?GV_b`7(_|RB@QsfixhX$mh^CTK*?-Hw(`O)^i{HzfSfarnQ{w*oo4n3# z6@H25#5~Hg+LpAJnsZS&xgDMP)8PA%r6N<&zO4pD;Eq|0@(r(hZ?~ z_82KUk^K_BNmfFazRyYBRZviBN5k6?ZM7_?$GOjkh5r*(k3U=BeM?@1T43R z0K3>KYvG8S@A{rrzn!@bpvjL-X24C=@bizb+mUwBq=iwd=?N9(WeI72NBabhE(u!f ze{f}92^S}erX3J`*Qyl9@8{ER@+XXO{Ar!QB(48Zq?XrKSzX&wSubUVVm7ZDqv3!2;wi=sI^krx#KSN_O?Hm1`92O(P6htJ0Y!Ke= zX?!8Zy=2-vFKokBK62(Rj0QvhEc$>{5BPSZ`kTNiC$q;TH_F(Ul`U?*n?zVS>_U}H zbn5QKYB{Y!C0KQM`IAaZDRXSq^I7J^Hurx+aGFhPdGz{<9FodYcqeQtWpJwQHELe4 zZ`UPyYpW&g8W%D#)7(@B=`Lyfa{PNZhUS^!5V*UsS;2vT7BpfT8!^wgGx#VtU(;se zn>0auA5h~DglX@Vv9rBdqF0pDtqY{c5nGyR_b7oj)-cUNBUJiIUQl|yZ3DSfV|h^x zdT*g-Qcsu>D<_Zh7V#so%9GUdRI%KcvBQoF>^vrd(V?fxz4IZ3^8zX@be2YTN=xLv zM04jMMS^y8;1~@`V;HKu>WOPd7EVt<*Q(+Ibbs}74H946ida((`BT{jhEbk~*}qg4 zs`Jj@xkZOcDRU*Rx6J|IJydl0$^|s-0Y5?mFtp~&{A7ltD|3vP`TXDaLGgA1^57nS1f-UnnIKskZBUg6vluXy4NiagG#lqMb$xqto30CW z)}+9hl`3rZdC$>?AAIe56S(aZ7Tl7Xls)riY&0qG_ouaFZp2<`xLE0zr+wAaA zzXwqwZ+=vi5qy_OhD7{&9ecuYwV@a0m~Q1po1@UN_w&J4Ut%@ZLf;rddf>mU0kBk6 zs#zKtqvb^zoBQ`G)rwRrNEe_t@rzrq>rJ=gvP}m%HI$aljix(-)zD^c z_O%|QT&ej@3?N%R3Hm-tmJig9@qN-sNi(mRE3I8qquU;3zkDuEuF5`-VaNd9lg5-% z@<4t-KVJk6!(V;?L@Sw=Uo|zvkUH}S1aMXOCtK617X+ErFz^q?#S1b&miHC$Wf%Lj z{l^j6_diwj`OujBI&4{u>t(6)`4Ij}3tNb6`RTc|$C$Mt$NY!eSn>1ssq$bx9z~Dk zdhOFFsFxnVUL$zRcj2ZDnneLUHFT=b$Cdkm@a1r1Pv^;Y=qtGmGDL^|(7s>{cPr9q zY^ka`+V%2wvOSG%p_x-l8#M`ZmCeZMd`X?THm7~&gJzch!5zN4sJ14ThAO^Ej@sA& z$Burgupq|!XQrRW?T3LoUeJ_?=iW}cC<*Ho zj-{XFjVXCScIj1r@Oc<5KmCI-Xdk`G0E7RPrKI}DNv>8nNdT`d;@Qdyu&|HuP; z9&jgB#7`NIW%|eCF&}i98R0+)J@c8*P4`Rh5})gpkh5_8ruHg-+Zx!=thW>Ryw@0t zH*UD9g)07>za(kW#PGW56LI&s-EbqWNRo?<_x-^3wt|~)J*d##%T8k&A-`6}u9@eD zI!jtSV^2?+$Xy$c9MV?XS3#^f-2vR&JHQ3BKCi%u$6Y-DpLw1Ks@4xOS=~3LWo7|) zdZnJe82;2}D_cvxqugDDU8LYLm3&x)Xyx>;5Vo}Orhqsy=0qc7Ykr)LBP-I-Nq|=! zvz-p$cMPbe^I0WZ$N7J|@a094hFYQz8>pCOLv;x*fmaK6ZUn{t`t;N}y)c1YgfE{L z;)dC3pYJp8+V$hdtpD17)0xcbVQ1RI<|gu~R%_g=(j?IRF9s*@KmQ9v{b$pWS+1TC z8jNR0bps}(0=Z$(Dx$S9MRG)ct1rGiY_29vX0Y$jzua>Y_~mWFMWWC{=j=0LS+B@M za&3^a%g%o;<5Jt@%UJWbn)yxZ3#y}QE);FJG!V>aSZ9$evQz%Usi>H;J$tgYV_7iY z`4_J0<-O)7hRa45kAD+wZed%4p|-;ECM5DsuZx=Dndi7_ufd|XWmhW#V?zY>?tRc* z$b}vWxemjpx$?TV`ZrIV=D6f*AJ16pB%|K8;%6o{qLlRh5Qa*N=A<`BM48yNYUR2f9EuCS`CBuPXbq?rwrXVC=$Np${;*n9Fi)_EQcY7zT7s<{8)JK z1q-+9A;;HB1R3M4B_sI(9@~)NCCR?q@IHn3@RnKu{Q z&vz~79YxJ)8pC2^Z^s!6kQcTNt7rk3SpSN%7TUL^63Nj^dlqXXiP*A|}s{)3u^WL}f zREsp>zU)4jPYxM&v9Ba0<3Z{q!t6@D4ZLF+yjrN0l(_Dj`dyTIVRpr+Eb~QM4hTn! zF+xq~m>yb@RS~a6^MjaEWl9RVu$)}`vfpSoV%mRueqIwKy(Lqj*$3Rt&)3F}<)Vgp zvkIQ1!!;hce8_jPxfv9w*4wTn>^9?bUJ`7C}AMf*7WWZ(EAwD8~GFQ$UQaAKXa9Fy-3`l z*T1Csx#u5mNp#OdD3tP=!_hBFK_8!Ttxvt@kB>ra<2@hWY}U>)LlzADfDU+ij7c6o zK(da+1!yi;s5+=cb&ONCoA>!HNvSgEVpWHR+`63qgy6TEEV9f=ty&QE{1U;R)j=O3 zVg8}A#On(Vp2>hwbWa4x>ZV@F6r7||V32}6hVQGu#*ZHjz z!WDVh*jbSRU*YKv5>+X^D0H6=I^Y<~{K8wLNiiLz^x&o}{+@~ynM(2K>CxNg!F|8y zy50yj4hb?pxnttTYCQoOSSU1QC7iq;4a8>?>l6QYTZzOV0#kQ8(Q{$4=C=*2Fch3NqBF!O7Xd&T}!_y<0n}C5~}70XaniF|Xsvbb1>L zN3VPsz;un|W6b4Wp?+MUV#DXVfgaaCs)lHvFXxo3fvD zowoShQ_q(UcU{PX-~%t{O{oaU-?I-#ZwhxlBs*GJmxE&RonB+LYS|8a_?$=@UKyGN zTe|)N+=?~J!Y`3_sH^gvbttwX<8sC>-==CqIqB>eFE6IBIm*WYNtNUPnnMd!wc=8` z_Px5i*F01Gfs@s3cKVZcOpoA?GT`-o3-z4OxZ?d?N^+N>8{N@!dUkFM@a-gC0D)DV zTgD5Z8%Md5Dn|1IDKE!e)zh=LT{^c;izGv4?mNq83obArvR@FDN8MO1_s*#5?H8)% zF5R1L?-Gg$`MzOafbekv1#vlJEpL_sHx3u!v%>bo4Z$mzz=OGy#FEcSArYT-5G2<2 zsPYFhL=5-I;e8kKk*^QcI8g=p5oggptec-6+TJrR`n-d)e<#56&enZx!2XUT0Av8G zc0gj+Hp7neAezR3>|kbJ^v;l9s0bCdQm%jZ7ZZr6p$ zCk8DRES$0V3Iu+QeCU@~Oh>VoCHy~8s*w!ZZp!;)h%g(C2@tGznjYXA`O08pk2GZ+ zJgPQCq7#m+nwOt;eYd74wwBdNwYnvnk#E*k#}$);URq076uJBdw#MF%qE$_>8fUX-}%6g#P z8G?JbESWoK1yLJVp|58pd$rkm>fNs2H*_a9#Ir{SK`p?~fik={#2I$?R^v-`kyd zhQ@KX-aq(zGMz@~@tiX%O;Wq|+m%+keusE5t3-kSkX^X5N=zV#;5C%KYjGAK-Ux z3E>0yG&*kV!u`fN^GR4#Hp|?c3tQp;b4W%ir*CurB5~zZ{^;;t3XSDjt0BKx4nWy7 zb5$7U4RR-I^Kh0FMJ;yBVOp%6`?N2ul!6_2*ThL$Inh)~ZE&>90P49A;FuWqkn-*+ z?993L^s`)=-@a)#+u+k;H`WzI8_`^lq@GGl8wn8;9T6>e`56;zZynKv?i9id)ru#b zK#6bc5EGk%hZbTiJ#>S?nvwIuTHW~el%s_j+dwAxouXS0*ayIEEL7T%kRtFna?e0 zsiN~Kbu6xkP|!e-n-RdQ%b%3em(LWQJdAe3z9a z1m`+;%ku;lW`?>~y=OivtR!};?0eb7+0TN=S{b$H-ie`ZE$CYRBPR$V@PmrcZU1}^ zNor4feAxficttchT^|22zGs`MmI7uO6|9XPJ-#=&EpkwDF)I(6P-a^|ccEJ&cGETK za0URp&y# zHQh=`qR;jh=Va0eO_85{9H9g-6p$DFl6qhGg_(xufD9j`;$Xc`3bE|#b|&D;Ee^6N zyn`=YZ+90-Ak7v%o>s@f^PV(Oqy=W3bv(zp)U6b0u=yW$nWADQpgPh_t$RgT7BRgwRAQ63Jhx}3 zdcS`*j7Tj=`Q_!VE?a2%RNUa`mCAA&QYfigiP2Z8p=i|rh#XpOdN=Y=;Uu6&{f2^$ zoR{z}RKE9$e20&SWwhpLSDWVxmatumEH_aNuXGVVyb&I8kAued0X^KvIv?X>lhD(W zl7o_4lm3RRD}UbP_rjBnEo1Xk`NA{+VM)_4^$V7+y`x7$GO{=lhv>=dJ&BLlDZQPA z>WjZ=#8bWd?^gQRFRL0BP#3qHS-)l3W8nKvC zHG0UIP_s)vxUt!-4>UMQriMLmAnPrz%}1?BPrN1{BC<{bqqO0LF=|_a2KHW0qwK=_ zbTFLrrj_4VkNZ{s`mE5?ro+D`xfg&6nP}Y(BWjAR{(}rv;V@9>EBr=A2Ia#WgY~dm zf;=iP{1HDNKw%4#aGcn+ITrUT(0=I)UJ>;E5{n+Aa^(~dM~Hh^ndJ%;wi$CzMCUIP zPaxL$)mTj4rKZiZX@j2?ezBkh%ES2qlrr<`Q}W4rN(|PjIk8U||GTEl5LEn4rJ5pZ z$*jycEc9?4S(%U~kf1hV0vI+=9cjv~SgB)d@NQ)6&z#$ceFH46LO}_Pce0R>9MnFR zyih^-d&G)P6a7->5LNR@MT|%5D0~7S#Jtlb>LGd=^H495-jE8Xpae>K%_9&3baJU235QVN?}m%^3~N=gJjyKuo@ zWS^wr|3wY;Qs6t~tML;StY75I0Qd%B$LKj72fe!TwCUfIwFZ=(1w^}3vcnkSzOJqn4HreXW~2%YVu#$(z3N==29 zQ95bdAne2412%r(QpiN(lE$h)+4GB&0DZ%@*F@g~S|Q#7qrZ!cZXzGAA6@sybPHme zms3bD;J(M?2WQ&#kf}a_jaC2ZiP*)WQ<}7^1+}e=giS3J5(w?@o#6j|;QN3M?u8JS zGMMpVQtZJcE4Zg}cQu(ZrY8Qy=t)rIzRQUGZ_+?TWuip~{tjg`!v{QM_7fcvc0!I` z$TnJ?4B4LaNMCmm0N9(!<9u|L*w+&nST1pbndyW@lV7TFB9w)_*%?G7W0$2JZ_Met z!a~BhWwX!eB_0U%EB{Nr^0pEcda@`^SUbZ>c*yyAG!I9-iXjRFc8`ui<4Ys?81 z?9DCXTDb*xAAMd#xaFjuwPOsz+5uc&?b8Z`!mepA`(sT}U;VbD;X)goTTHdDy&tNrNNCRms=*)lH9kmMUqkWOml#+#zKS^}w&74-nczB>CXSM10>xSYq$fWS z^K9Qg{0Nl6lljx#WFJmR`v!KE%VWm-kJrSH>-=?ANTbZ!YT-OuF63!z%A$6!mE9~1X1-Ay)OGpp_sPv!cUX_%jazP0KO zZ~?l0(4t?qZ9Go|22qZK<&4h}wcVpWH%t549n|U@ZYwZ0UJ()>!&hS0F8L-0J%H>J ziG9aKU~q)vPNA@tRxUzF`LPG=9GNHOB1B2^BhfClyMMq@v0Y`zT*o-Fg(!2vg?2){ z>-Z_3*%AGZEs)Mj@Of)|wK<@P=P+U#8=-y)nY2yQ3_>U0n;ch;stYcWkh~M0hVbmX z5Hl0Hn6Odd4!2BgIuitH!;wVJldBHW}W zU&g7LI`{gHWqGmJho*gfHo ziP!-~zbna4W`2cjh#@+-(iv+%E8} zzmF8;9B=G!>#TEl$nls0(jec%_YidQUyd&hjJkh<745#J^&fD^Tf7ov8s?;ZCNoe# z)7TtJ{rps*qS_^l&z=hR$rV$Z10|F}6e{25E{19A}bcTglO%eI9eL~&V za!;9g9%t?swunVvq`?YJ4n7al+dn>nE2l(xIf;^lp}bl%2Q>R2Czo;<>ox`cZ^)&!(ucp1WO-0($O{Q6wH8J=mlGZSfb+^= z&A;FYvvv2gg~mJYIHGsmddRG^Vrrq)^l^k9W5|~Y{_z<_Y{0QYG}GRfb4&EbnY`Z2x1lE&Wz

o6nmmG{^dID@y9?a!3C} z9BM19Lu)(+KkQ{lR#z6(OXCCBuwkg?cvihepReBaa}TG`h76kqg{t^lm|}V1)yTP; z5)JPOuXQ87g81>E*TBU$@p#c=gf0hovLRwbeY!&B=o4%$}VJaYOF~cm!vRIpBhn%<07AiV1fSUd` z_dNE89VSszA)7MxUhUH&vv;OG;k%wvIrW6mNlrfNerDy_*|g9Ak>*~~K3fmpXUjcrO(4ta;Mq8|!yGD@aDs5K{Iq;UZ`Cj(!W=a}}Y?=@E6yMA^=X~lkmgi5%< zwkO0yXRTM#Pw;Z0xB3y9MTF0wLPVg{?cma%?oFe`m&$)1u`bk8UMdj{UCyWvZ#U^a zN4QkSzs!JFMF0<$+%a?WY|TC?eB+dDILeDWv3s_Nf&QCSH7ai+5oRuV(ViZ+kEWJ| z4L7X9Rzs{^PNYryvQAp=&nB025{8Pef0rG-tx}SFUR00sqlb&^Fet-PwlWL(S70NZ z8Pi6k?!^>D=R&}0|61ez(9O=lcF%payD=e5Y+t92|F}& z`#too=8cOx<^hl^J*op|A-J|8Rd=L#uCH_EQ%;VSRTy&fz`XQu-aWn#JDa~a$%LI% zNkA00B8 zw+~{F=M<8gC7Saz6+mdD2y@4`dP^t38rcnfjd!TSf|7R*chFd!HAK>N(vGsN3-@2Q zN$7!gAa}me!8&cjT3?mq>MMJOh~@wAcK+&us! zk+njtss`rB?E3PDh}ujI(PT15K+~)Cl)=FwWg-Kpa7tR=f_&#sXW{p?F5JTrrZZT< zrI>W1&l@G&R~~wul0JvGcTd`@#)}`8`&GCGZU|OBxV!#RT|i~X?(L&KId3}H?frhi z!}K?AV538YCd<%6eCB=rA})GGLdY3N>s`t-B5=kP>j4+tHLN5r>Pb)aqZjV>R#|zZ zY{y>45>rFiATgJD${j+5aju4E?4ZQ_inD*-7m*eztC%aTqe1=8v0ba zY&SJ(4sRrm^mG91xan;kJCmV_A3T-Z!l$hOz2t!U`I<1C+4%l^LACf@@*CHE<*GM@ zFt%88fbo>GN=vdc?F{Uz64oYIrpkthCOnH%*(sVQGH+-0`zz z=vD5|*dKUUGUPL-RnciC{QxbXh_y(G*u9%)A`jk~L@Kvd#S$6c1s=L{$?DT37A2;} zS8veb?a4|cK^jJlVMd&3(o{vtl;d|KeYO%Ap7!fe+%y+2uL;@+ zcRGS+XjkESVG0xLFM8Bgur9uT!wYTU^_i3uzd)`et~FbQ5A0%@M z70=TM9X6B~xetM;7nPj~#VC{W*^h|AlY53DVZT75?;qXntdA^q2PyJs!n@|HUs(tucis zzh1KL)0m27yV2hq4~JiZS&F1IN|Vvx^9Hd$VhcqGvp zsWb(b#d!DuxzF`}eD3sXVhy&Ym)AE=z@W(Kuw8+R+Aftk{N0#OHEcvv0vZ;FIsB-0 z=^HMw$f|(N??)b8krM6At}vJt_JiH^O{nFNmk&M@~`q(*t zdH`JH_8h+<#Z93Z^!bPYp+?7)yQs;D*sc6QdXcM8Uye#&)E<_cE&vZ=Eq)M7y~#dl zk5RVy1ovDom=Q8!xi53nZ@Jlh$tc{UW&;G>yx7XVYT&51Btx`-kmi5j?Q_^mWT#V# zj1w6!pV`l2b$Rne@LyWzjLg}+(BFU^p+7Udw~m`cfY9k_%&6#PU51HJS}}eXW{v7^ z>)m&WZ_OUVb&pS($x!$K0bm=G+u^B`ruI%B0p-K(w|yb4mux4g{6Lx^U4-=pa9WRN zF$&7hGWj*(feTTGx&8*(C6Za`WRxLZ#082Af-@e1v2V@JXX47Pdi|Wa!_rYF7U&Kg zt@m~YJ%tqDgQn`tt-=~kS{mU-M3Y%4u3C=Ki@22n12kp5vZluCg--T>L*EzY&urlF-AjBx|5Q>P zSKNoEYJ5o83USfhU68qn_&U&!#jLn_fmNFE5&BfSbFn;4R&zrTZyM1}vHnxnnR`up zbGL6tzhN`lfbv@LX;UN}io3JW0{PkgGP#Fcaa=Q39`ET@Hyw0~%$P0RQm zG5))vF_44Zrit4xpD{AW#YYytddqmt3MTF_|4+hrx7KZcB~eu?q)6O%wMn9$M8mDY2=^}OJ-o5kbSuNcjA1z{Kd_dK4>R^=8YRp(2r}?N!W8?=c=~DVBjn%Z1=Fg z4P^Qh*!dBc)<_g2PWw)7g zeY&bhw7tiM`{&|vunvjUCcxO5_n9lxtElc4TPzfD11EbP0y{yZR;K_be&4>ghG$lv z;JQIOyz;MI?`*nU-`@LjIyBB7aHJI*Wes@t*yaZYf||d-!^4C*2w&T6Z zq-IbUv#(W;lNhV%V<5&hsgw13Z9a9uY-J}q2H7og_+aw|TBl)x#Kd`Nx3+Q>h^!%27<|&#Ir{_ZVXPo-IHWU1_!)E6m z4@loaa;XkL| zM-wol#cV(l*@g5zT9jdB(b;%0aGc~A*1`MK3KNcFKt)@#slqJoM*$L=vOF`o1(U7? zHVn61uMJ?#v6Yvtvno~C?d*b>cy88N`uAnGGxttrN)azk^a*=7$;$myBPSRixo(y* z;M&r{dZcY1?~3L|m#(|f0M`il`hjGDzeZ(4v2Opyx9~H;^Fi^rd08zf+$>zkS1)}& zqN45tIRXukW0Wx;W4=xFVV$zcl>k2}&O73XHFE5UlyW>d{S{Y#RiW4)_0%@m>8WCU5BZi&KJ_ zCY<_C`6@8c9d;_|--u7?)hhTF^jv3mcbb50a|5{_yhhl+)^g@v-L^K2&bpm31%1Tz za{k~)w|~2#rj=iiNjD?`)+4S{3j)zfPbAB}@`o{37KtIA+ynRky~W(?F8Bv={kd_k z-mv_fJ%KbujM?_G=o;>CfQ~Bo_Q6l*iCLuY6xq=_jPy#d+r!Q(;<$3B)V4JM5u}*2 zs3Ggb`&zkVWmfygChYb#ZP$so)w$UGWz_e>cK{s`L3?KkF5HhVIx51$6QIvOdB{G5 ziWQi2IIeXQA`xvtpckbvJ>H?zCZj1dP0vz!M*jD!%|CFEtpF@U7EvW1sj8#m9H$~Y z$TLD_C?O6jlQgqty&IG*HZ)LF?ON3jD}CDfJta0DYjw=_y|!bnQ6DcsOU}}NZ!+XG zCpB(QNv4C-cG?Unf`s;M*9Knz9FxmOnBS4~*d5X&GvR1}-6Lfmj|<}+zXLYZ8Z&jf znIEwT+?R04CAIb^uCm)-;vhHF2636(;g0h>w38Yf{Z9Mln%yKRo4Qp1@PGjBO4YEr z@RIElU<%LL>AL>pBb`s5xZVCeItAJ^;m!!G^r7Kw`TK{*6R#hbBZ7wGo@V9x^kKJr zE^Y!>eNH?0h(O(>nQX0&_4N4kHSmhjEMfCY7?!`5n||V}{KE(TZfBO~ksd#T$bWq` zY%58Ey&bT*s50(R^ib(ez<e6G;U(G^G8N?|ED{O^^}f_(S>qdw4g zCvZ9W@Z!aHRJPCnt#7`!A0@04EkJFYV}!&IhEb=cY=Zlt59qjrdrV5#d`(C z`jG{Hx6??$?m}=8eY)5hfa;QC-}0eRXG4;O$hjy{o*U=zyKClH%D2?ebL))kIz#GR zRumq%M;Yv7#zMgh_^fGg6c34KwZ=~PQ!a4bUcV$xh*eUsUnXgJ=s=$3W&wKV+EQm= zMf7hPuqtW%p3k=96|KE&0b=Z@QC8ft{2S}2+aVKyCoRztyTQ7LisjJo%j5QkY|ID( z^Ksn<23h-M7ah2qKm6sPz3@*Jbs2lcV;P_GF|R;r%8ny6>d$mi{}Vm{BkHg<8=nO4 z!mjalIx^TUqYGWeCw^aU_P{D8YMRY`?Z0NFs$J9wugTVG(-tk;F+||ayIK4s?iVVv zk>Gth3=g{#Ln{=Ud|TdX7H6>ll9xzA{sd{! zSK-j)*G9L|U85W61|=j10+Q0*C|v`kYak%f4N7*hbNB9$+A&Qt&)pd9 zSy`HrJU)#j{`|IC%^W)k@9^1|(W1%V=(z!$X#-c*h(^o3G;&t$+1O!7x2%2DCCa!< zN-@uJSY(?c^a8rF9g8bBZn8wnk3t}sM-!a{TfPOfjq7tO3fLR40DlhJXEq+2Xrc(? z)26MTVjYS9GiSwOkfvrhZcvYh=_M668E4jOQ}-UW(VQHoZLIxsAKBJtdh?Go{@nagXaB$>lF)>b%jQ28AwQp?5>Xa0PPPU2*v+QZvNrnE0QYnV@ukvZ=gXF9`+FsA=bh#ZKxBU zT}^qAy=Bhz^5qMBNf1`EYv{_76&Z{ID?Lk-E^rE|A!8N&i3T!7%Ahv`ehW}0he$oq z-Aw1BH;h8|)lb4~O0lX;e<`6I!ke|xU&t4kX90H2;;v|^2iy0>9{kL|dfl(2^N1sA z2H=mGEVR*fGOWVhtH!Iv>Aiv=PtaNi;@U%|RtpnBMgwF=)vvlfS~@OObdd|_UCT*1 z$l3UE@|MuIvljR)n6rOGIznYnj;*Ce+st)DV6xi1xVA#QtD~_Sbyk2VA^+=H?TwU7 zw*ryjl;HP#dvS5Kef?4U5-w$LE@%O+UgdC#E<$Hj0<17Ih#cg;0WpVyun@{Vt~_W| zNCwp}kyN#T>!tHswu0p-O=5Q8O)D(R#(!_jm>IexmA8zWiB1NL&&;nlJE&cHRGk1F zq2Ib6zoi7nuNLzj5BXh+`2O8Lh=hau#rf-C|3A|MSxrwX0O@8&P32~FdE57Kf7#>u zQ{jvg`PF4jGEFK^=}7J{zr`i6YXO6oj-Av3vqY-QJD~uYev+Ggduso?7M^o6x`9r) zAw;(mIRAC1069L)xp%UY{}t+st&6L4TjwO;9EKfrIpVTC>=%c1F_E8%aooiSx5P!V zd=-)}V()M%aJ6Wq+q6`zC#mxD7$q_*OVgoC;XbGmeO~Z2-5)=i-l)nTB(hDBGrE3# zkTmzGZhtLXX+A@^M9`e0Q}J^^EuA*aQrJ0sk)P@$$-8#yppHe%Y*T)@9^|yV@3Z!h z6&&yvi{-xCvbqJY1;;knP{067wGG?)hk}L?za{e zdXaf(ApRG!m#NrK+g*O#|FoWs265h85Dv)I#f5PC&I_>1a+R#(v;i z56ee)IuvL3_0&q5KD+w5sXmBWxCLTLlTH5hN+Qzhmh{GJ?d|rJ-)YlH$dJZC02@b) zbkR{s9Lb4_uPH>n<9AR6+ma`#H5vs6>b575 zUf}DOdAR?4JiTMh)1}clSK@1mRyJT(%t34cBWD%5xk;EPDCKsXkMi>YZ_^vcun(az z$gy6{S%F!{5oc*eXMjhh2fv$t)AB*+?mRyhJzaxosaJgDnIUb8kX=Q{^7R^B#lOQy zG<9rCKoOb+zXaZcndWD-B<-nXKL$M#ShB|W*+E6F;a*TekU4I>4d`T%x^(%U`vbLW zU*#I=!1(pad%>TuJ>koe`yZw#dI_fbH-ClJz*?%F*ewzfVI$!0Q=SS zQp)?-B~B}d@7-fx@?7@z!O11@@mtVcLde{Uy_56ORg<1*m3s4$PY-7=EWLB*zdzHX zXLCRBR`Y^oV_&gqyg-JR;pw;QBLcp*Xt;?fg5-HQ4%cYaD=d|??+iJonAa(Xp9+Yu z6w#mMdtg@b$~cJptv;}*HT1DR&B9kW1C@E|PA~+pCA$X7j$3F68yaoaYQ2|wsHlFU z@Vn{!a*u4Y5H0XsZqC(DJ;gy33iA%v2mHQyZ_S}GT|__>)EuYJ{rN2w#*>of=T4hu z*OO&lv!LMR7jfN^)E3d~pNP=^DuCMVJO<8%F=vefMp$KZSEjHrB@BO`suO%kK&iy+ zh!|$!oum%4!>c;SOC+r3akqUV+C*PGKIvm`hD($_EJb-AGrQh499sU14fwL*^z>!k z3!wdxv@!}V+8X#gGZo49EukK4-!ZCf%Pi_{!omto5_MTc z)lFn|Y&c;Ns#^DpN-80Z{#2<4C7Xw1e8f6g?YBLH>5 zXAa6|;p>YyXv(wlg@PL|ti?yNi6U$Omu7)H3WMUup>(M(1C4)W6-jS4Pa@&N zr0)gy*xW|mj;xuOgVH-PX6K4<^EN;#C@A9N!6-FV_>}h<3nn)f7r-8<%5?NjH-1v! zfvdXM_jjj`OByN2E2(MoY4x{{*UQ;+PcH>gz!Y>ZSE<)P17K@3Z&EJ1klgKT zw9^2$S8 z336!4TNm?amfqQQ%?u2DaIqU23ZIC&{f)j8H_>n04w zcwre(UYO7Ot@t|Eu7Lya)7O%zM(zD6dmoN}0X9Soqi%TdM`D*pOmF>`>te(SXN_VajSZ!{P@|;7$jd#pt`csnqwyITcOJm^6~3#^ zNr?256N6Ev!X@Q;UdTWjSVNI8HzXldTsQH^xdH-T%?vBRu=u^LQT9V@KtMlA*H`l7 z8+h^WgDG_;m&F>^j#QGt+al6#2927&H{%!Sx1`@AuC+;Q z{n=7mBX?H(TaKr~uKi2(c$Bm#TV5j%OadP@jo!yqv5nladKpiR#&6>@yl;0TVK&rY zHzMG1f6U5m-E5nXx>O_@pGy(lzT6F2nGC5l!9uW~E;6AD=B@>%sE=whGXI6EW<2aY z*N-rx?{$5DnQ9Zaz=|&U!^a`VHqNTMLz;cx!)Ooy{jC5h#JCK`OkdTq?i%26 z2H4rSv7GN(X;lzM>Gvvbj;H@1$#avZ29S7R(l82j;rw%6tqqrja7XH}^`~LH2bQYOyG(6#8>DsdD~c?jteU z>fCVm+VpjfItcC<{Z87jee&mU7vp-_+sIN}(GVQ;hjz5Kv@pxoHb8YT!@uWhxA*4F z!|BJF&p#{GyY?giIc#Q>7aKwI^mZ`yxKPVubn=s!t*pJ3Bnwk-txcD^pXWp>a~ybqEw`i3jpSuJrR zn-uW&jU3L$ugH{eEQ;|!iFR9*!S-%`Kf6LUXz5*{82IJCaqC|{*Wv;k-idR@+Wl$6 zKzEL6ML+$~aY!AuQJ24*TaycL9F~3GN(@T_W<*l#&MpP`-FiFDb@R$(4xPl6>~9wz zOd8kj5TO>Rlv_qiJN`KJ&qnaG(VGFOkKx&`4eRX%9eKY6J~@AB9F5 zTbul691rCO$!5K-a8LV>PZt5-qRV4q%?ci@3iG_0$dQ* zsL0{Ox1jZn5w?G1(5{HUe=Y>?DlsNSvH3DJ z?k6^KOYc2VZ*D-V!?Th3m@q3%claY*p26t5hp6X|fGd{xPHe4F7JyJ4Qd-Kkz;c)> z2@Zn8pKpAqLw(=0@*5jO+auTO@yE9|1ODQPzkF|#<8MNO{m$wa@zCp~1b^b(&rUCu z1R>H)Q!DDa7XF}S24xr=Ude~y{0>9B9l-KY|cxn3VV@=KLr<%{mXAFm$Gs$uNs zA03Ee=~0$G@NcZTOtxSPj_Hf7IcH#kw^5Kr-_MBp6lt{?Q26wt zApd29u+<3k@!BAf@h^)}sDBc^be*9H$gIj!8R>1K*Jrj7@=*ph z{OHPk`e+iv&WR2oS?sdOm{>Xx2w}jsRc|jUA+_MGhQYg~UGBzxyHE_onN6Dey@;O5 z;E2+p3^-;m2YWzbB47l=yg2t3_#MMsu;*-xF+II@oa~R1V7yT!^W)q##-@Ph@f z9Agcc-$2)waZ7p$ErW|^6~qqtAN=Y-@D>O#%Z|zab}0_$=|UK9@n1 z;dHzaRc?u;?m4zGeC43ykIz!NZo#zKOjIK?fIRL6q9lrfy#u=X%FG+7ui{>KyMwvF zZovQYU3v3(7Z(}en~1zR)8usg+-87;iuh_wv30{{=;$`b#@Y z$1%L3h8}t=NFW#vIycd$`1a^rfCbP?);PQu#gCOXSs!f=I*@|Aw;Lz01)sQlhy8I0 zpiHUc&~44E+!Z4;uy#etVP=arHixC%f6ZyFUiiQ$^~R!mB)H@2m-9+2L%m=?7Zfp78}>&Fqh-iK{@VvWA+Y;O z_3NI4*3E|nS|b=DK^33ob-YBe!?qBlL>BO1g8EjYsII z(uGREq;s+_N-p4BME+k5X)w}M3EsK^5&smRo9W~%ya{~W7`az|Ol#pRic$>K^iW>;nwh+(jqEXQ*n!z zAHm5~MP3Baw{|GfmJ{sa@zq&ck{*k2uo;GsBSGNQzy%RVH&1_Ws-Wbv@Hj~g*p$VMr<8}g64I(c9B(%6BOQ4@?{@Jc zn(S;d>ghH^-sC_9jGTShwY$Q6Y)}enE&(g-Ac|u5 zj`5H+C(^mwWjV5msRWBLQ?eAY6TH8PF zIUDK$1Q)>rT;T^IdfvOxq~e&sXz-q^iA(ixO2i{#3%NBmANV!juSw97(hJawamSAgOeA6=#+rzZY6ZgNMRWBpw9bQB{0rgz`nSXIt zN#oOvZ!d`9R<=8ekbOx(vN~NOTaq-l<=Z^A&XNia;z0oA;l(LZ7aE)`X45;(RwXUA zVLzOC5+5jP6hVU8(+^~B`+JCywHLUg2TWoj`-NeaB);SD^ffS#DZ`6;0Y1I|XW`b2 zE{~z#ld(1v6QPS}yT#WcJ>=6DI3V^%r2TR-{8EQy;%LoEouvwFr?_#EiG@z;r#OdI-To@9t>onIC}R4Zsi-p(DJXA@{L` zlrc8uzP>iTYvmQ?jx}u_*U=IGZsJH1+^mK(ngv~EtI8i{*|^@nc4Kmp`{R?nbItws z>lASGLmlcjS^gwWR9e2&T&0cEZ|Y~^`-!Pbe|SZkBfC0gz9U(bmVYp4n@BEN0m20U zjelD7^fN-cy46U>%srJ6Cf&se-DbtMMKTkPWk>8}5Y!i^h%WrJx#X9Q!XJTfkLMC> zi1-bNmlm4OAk^MuwK>g}e>(Q1Lli~~|J%u7e6ZKF!5Fqx##!7*Ww+-a##=aJ-bY`E z{n0OG`B5>yCa5#!{(*49nw-pZNevtE0%AM$4nKSzqm9D&W$s)|oyQ5p(n5{rm1B>B zatC&XXe#0ZcaQ46*lvme$X>K=91Ko%tR6rdsLVGURQ-8oL+lvu?&!Vc!i8z+0O|$G z5}rzAb{#JzW8aH@Bs!MBG=0`Lvq9Yty@3YcRs@9#PLOX*qR^&_U^p=oI#qp+iz)+6 z;Aao^18Fi!$sJk5&f2cls=lijQg(G15iMH(;Zw7Y*3*!-fa2Iq4@{l4ss!KB>&^?f zAG&QfKW($?TAD0>uE6wm=?yd*bkPK$mHcjp9n z_9$aVH*(tQW#cu_q5byYx5=9#zV0BjV;@!iU@Nw< zt~R_hEPh=86+gl9Z-uvU7Za44)2}XDYWs2IvvA*C%9lw)fOTbBgfjJioABRbwc&9G zQ*Ql<2;54nTKP!o{n?Z%#`kkxRitOWebX`&cX~4&U8w7sNVeOln!5@j4MX|&WY~EU z$?xipq1eF0Kg0rqI_33Eg-5;?u~Px2qXU~hd#pPmyi^x8{g1((0V`-Ay+BG9`P@wW z^q#+JIAm>J26^Lc^s3HH!8)Yj=YrrBbh1A`AHx^qt+%HNn{A0&P;UMf(l*Adq3! zmm*8V%i8F6qx@6oH6b_VCW=WiZI93r=+t~K(x(pUr5Z0zhq+MDW(!LS!CZNEtJ*v6h~mf)jJ z;G0B(u9N^Bj5P;yqZk&0k4~W!@r0^1yJGybY2n`XD3V=^R33LUM+Vi+Vn&t#t9T(C zR)<A7&K(p}QJW^}$}z@CKEMm81cbnaSs;bJ55i#WdI-LzKO%Zxg4d*?|~(OWtV> z>=}FQ60gkw)$3EWHB@a~Ouvf$QPH%Dqzvg4JmOH0;;ehA?$Hi|(Vo9Btr84!06A~n zH8_BTQTTe|@dxgPdT>R|?1B7AWLY#A1{# zWOo|G?2rs9l%i3>R&+M4Auy^L(T#0{1e5b;<;XS;Cxh@*;UVsz3za_~PHjQ!) z)DVlpWjOV5UQ>Y!YoU!X2E!n{Aj(VvQgBLN=c?kFJK!9z5PTT}{{>Jbg?U1WMTZNq zA+O^9JS<^x(#}rdEPt51_wT;Ow;%N@Zj6-q_EeIK`r)L&Mi~+D3evq~*@Q;1!jDaW7`8|U88md!LievQ zXW^MoZ6;s(&gDpjGC{|?83~enWhu?tb=qX1tC?`O-WeiSV{kQkG~6qFAFRXkTrRkN zlC->8<3^zK;WJS}-yk<$d7rQwSY+wwPXm8b#7ZGD{D{B#@NV%V5cm4F=XMoy2^^|B zujku3gf078xOn+*3{WXQspKuF1p566oK%p-00GK;>M!@V1UNEEfJOJ_cF`%m02RrH z3Q~1NyRidM{zI$TB7GupL{oZAOPaE7ou zaY~58E(z&yOlRYm%5oV)W^Anf_Q`xG(trD+^rPA2gWCNv|m_u$T+k%KN zY0P;)X2wIT$$>(obXF}uHB)PX)$=om|MPS#Ygi|jTy)#s;9D6EhwuXbCyh%pQnapD zPS?#Tk_P>BMKV|v?7mD)1HV2iorw{uFAsw!^jIKMmLsFuVQ6L%7Nfn|j3X-5);D?q zO{=@;?37YrB-oX2p`K_i=8D6$DrGNREoiuSa~UpFK+;QJ7&ueWHEY#WO#w%nY9{52S^n*l|bZuqq02llF|aQ z<2-6r!g@wqvt5LbZnP|i0PvV3QGLV%bJp%(BRi2f%)i%Zo_6Ir`@0m0nmr+nlXZB? zkh$O*!Vlkodjk8kHEMeyWFI`^rgEZM+`B|JB(p8c0W($tkE)@(^L@eT+yD=*S21)2 z$-zf9Sh&s3L?Zl7ISzaa?JcQ<=8CLdQX38$Id*wD95joZXqDd=4pz0v)+@u-zGf0b z{qR)w>9r{SDWGEAnWX4$JbaJBF!*^>BsOgB*d)Wd-q4;P08B;ihhP$t63zayZOr6E z-nj%XDU=Bf;ZkYT-js=|yxtC&NveACqILf`6flFFN6V$l0vX^w6i^{Ut`NV3G@*0v zU8JJx7@Qx|3-(BIJtc^|@>+~RkZP#U=VP_c5`&X~A+;vgTagnkr+=Goo2;;g0xFr) zxtdZY$~;UK#yJ*c{CHs_{O3)G~NuiS@^`Br8ceipaspT)4tzaL&=D7pTU+I?NNU^8{PLxT9OTA<($R1J!0JnM3(ZJJ|r%~ODb9>Ps8dI^)F4ak8yHi|{Q$B$( zSjM?I0(AB`$_%GIHRf_VZ4A@@!gQ+RS;~$n7{-z*tit`I4{Id5`_?Ptra4XGWhFUK zZt*8MSq;rh#RR(E4w`?_57}#DkSVR!Uc|4?`ADs7{v!&b^p+PVux#N3&vjoSy^SO zz?c2QOcYp=HeK$R*v!!emJ@&J-06xV{_m!mu3ZK={|0CAA)hPDwS1O#;IpsFrL1Yk z^T9Y&NVeNP12mjE(e!fOv=P z0?m@*M;aF(Y&YNpBk}%8KHP9pO%p_W7C#W+dnxshU(u8xU?DDR{c&V)O&_Ek^k{D&(P+*&O&&yO5 zfGF=JCnhI9%`HR=$ZgU&)k~}=B;eP$%cnX1zQ|DRD*|a-=fdr)gdKuHHRKCvdn7%8 z@VHrFvB{W5gQ_D2g{Ii!YlC3RKV8qxng@7?PhS1!>V1Wqz&2m3PH*DQPuQmBAKv{F z>%`?MnK{wCrv##SirnBZzC=+7>nXC)+-zJvFaj<_n`>!=SL+NHRIrnP2J)b|;BpI= z^qp8fRe1EaTihnyKTm&}S+tN=8s(!dI2hjDZk|+On@CZy69ix}VCISAsaf z_G@r4w?*H(T7IhCN)Bd#{wDo25%6}2>Wery->O>rzoWPoBpK#?c2N@-l2WSTjpaM! zGL63IaUlhyTjo|7ifNch&za12;`^lK! zNi~|)BS=?Q;h$J?>1SveXRW)@Aq#ivUph2C7F)^w2N4RgDDp%TEk7J+$jp2v0Ecz* zogQ4JJUo=!2}1Pw+Tfj+T)bH|;&C*R(VuKTa&;wP{YQ@daw8l4QE5m6FX6HFN4{0h zr$yg2Pt(JpOFclS=l-(epk%#8MN4<_$`CJYp~v zt+0z?$jC!{?Z4=4Sqy|7<+GqO(6WEwi`U2lI_Mo#D!!$uomcqPQ7N|3OFyEqzwzrV7&~^@=u#tvT_sF}=ZNDtojn+TgYZo}EL`)~ zjyF8yCF89xqo(*jHA#f84gY~kNf3VEmcT0YKxah9CBzM(BIQYERo(ufGrc+@5+Np&N;8g8Dy*9P*F<_ zhIwk#7CLykzPMXEao5Q(8kSxWh-K0+ByUO(f7$OL=V%CMI_|8}G{b3IkN8CPxq{@B zG|VITE%ReSTFQHl>yy->>M*$!?Tl2qKnch+pKJ#c1pFQds0;g%uJr$3FMa_p))SQ) zJ(;|V$62ozht1H&V_hM~C60o0eAe>N_*$ppb#X(>W!D3KzeL4$n@I)EerKH|bD={6 zRBz73mSd*ZkfH{lDE-B7oHd=&OAcZ@W|98=C)s2rN2tHhE(&Oo&bzq2R+BmFxV@-b zpwH6T;%a0->a8`UlM!hv6OQtyR`vvXn)E7G#h`hpOr}?|bE1M^J;+~}!E`*dTS=r` zl(jkQUiv>f6|YB7?3n!iq@&$WYI_~(+0%Ai51{%C_;+$A3rXhob)bNmFixNs^$_rL z^W&W%KH8~hE0-!ANv$tvB1I0mKyls_2RGM3l8z8 z&H?XU>G!ArB_rzlVqD0*-3top1jrX|2rIN|5ENf@R-|`(YF+V>0HRBj>u{_6{>Zl1 z-+)!rS>F=B{z^?bxYwefid@7ht@XVZGFBnp!j$R`ur-#~?Y;mBH4-{lUEO}O7fW|zpJ0lZ>CT|64z!}JqS1`u(+(iT zkkA}C*4Q`=f?vAzMq|yB-*m>^;M(G-rZq#Sol%g1F95Dx#Jh`YZc@c@V9Yk3v4XOC z9e;2haC4m8N5yNsk#%%Yf=?H9#n+FDE4*lxDQpzvK(gt}1yB~>VR_F`$A;@QPTV zSvTyRUGMgR=DUjf;a_8Dj5P&ePqp;H->$-2kflgoWbFn#2uUQ$Gsb*s6Arrtak9nt z)>RniY(B)=P0LW1!U#XS@1BIxOudh#zDU+ZYfMdDD zSAM>CSU=4abBG8N{I$5_h(u`zN4~=zEyYwEgd<|L0E8)?KdzFI6$QrH?yx|e-fzK1 zN21c5JNMTipy7+a1zHVHl0UK%qZAD9$=D5!Q}%*8xAPoxD+$5LU)-f(Y8FTC#zTKo zXai%H23#}%MtSmjJeHR0OT}3m#zy)(2Q_OVT0eguU5`lH0s+})$KyTbs$+Y+dM9Wrq;8R;% z)I0to0RYm+Brl*!Oi41RdpxKfoMazDYf%p>$_3OTjj8gBOM zk;BHz+_gHlbR^!WVXp~3gnKx?ro)Tif&HqPe%7Nz7pIU@69*$^&?b0oU?@qROswGP zj1!BLwm2hKDA$R4bH&v;vz6B?a+loHhA$RS6h<(OT%dELbI* zn2q2RQe$0oT=ePKX=F492sge8LChjQ@qxrGH-1a*`T62!|$s! zEN{ms>>iC@2yKefWWvaMuHLow)EH9BM`h}hML=5ge>vC$kmmMzPwv$@_smF?YFhhMR!kN=%s&u!r+2@twpx&qQpTYa~q)7odFJNlS3C_^w%& z&WE7|b-Sjlo^|LA#g2NC6*UiSn(1JfsFj{9zB1oh8X7wO4hZl$BEg<;o%e@~(N9qP zSaia%zZfmQS-iR4es9jgc)`6kUc)Y3E&JY#=C_lz>+$wC9ZXW-Yuh_Vj&}^=W2VqR zjwjz9>ssGmf(Fj-yS@u~=HXa~ume;?*DmA&Q*~KPW(8;s#a55o@*I+Dui12eQKg}E z8vlNk-l&ZC?M+EnYVsaIC(u${=<&~DnA8;R=e16S4WF3m4zh9LgBQI(K|{PBZlZCdYOD@gzjd0g{Z7bw$`To1I2XLP{{b(?yJj#v`r z;i|;TK~G)?xkE2N!N|C>@2jUrod%=M16!xz#f2+_#~L>-Wbhw=8^=JiX=GDH^W0U= z4_TKt(l0?ZLGLQX8l0`^dsoND_ftJM>5O$JF+$=lhmnM^lu(&V3SfCYGtWWei+FVY z1RkN);g^r<{t)b#b-5OgrLkgjP<3x9-P9|F8#j7&{|&7#I43{)XV=!e`-Ym`+Xaa* z676>Eb{U3B;EvJm+jkr?J_-m+@IT>oE?|Kbb~811dX=(Il%hvYyGyGnGx`z#t%^4R z|2VIze5(u+)WJ+v3RVUL)Re2PS4rqqXh%i|)BY73$>|p}~GUY`OrKK{a$QpWeV?sNEYNp{{D3pw7`B znEsc6Ya@s6iq_^$WI#TW{;Kk&SsgymIFzFIWki$CDP)5`F zbDD@N+e?cj0l@Y(wJ0Y)+iuD)Nlgr>8-P!3c^W)nMhja`9NoPnZhGA1atR|k!sat8 zbJlyN?*Y}6S>t)D%KpV})k~%TZiK{mzg%5^f(B9$5V9A!XX(cvfeIa6VHg!)>RX-7 zUkI;+q`80H(?{J1f`I3}y8TGy7T1hiVPMQka}2}R=}Vp33X;w8ueQI^{3})~#5(Xf zf>gSA(GA<9U78X>En_-BimzKUUp_eDxN^D6PxeJi+v(Zpa~)RNoBtkLW5XkpR8xj1 z_xTQ5Zyq30|aNc7mO6yHocMzM>&Yp^lv z9b>pxpI-c>F%jjz2cs;xcYRE(YKiOSM?Ojs5-3&W7uvZw`aqPfVJ`AN_VUAdfa_*p zc9 zPOD$5k^l-qry)Aj+Kq$JPp)I=@%hv^-7$VAHjv|_In=B7@RvtBU>*)YRD1`0pVYF2 zKJP(BOj}bQ*uGH%)qGz~yQ5vqWH21<;8<=73riA4<^eq>LmHH^F-X;1exvSB9d{_5 z&(2)V@TSgD46mSE{V-9j>P#07iZ8zx!h`@8*X)2Ds81qEPe{ihdOESWoP4f+=pET& z@2o1}EBET)$nII`8r*S8_H(ETvjCJ2s*m%iI++L}43>=8z5h}BrHZ~jwyt2lxK#B+ zuZd&j{ifILjg`0z1z>F^l-yZXZh)Xr*?9;Pvp4KR((f%Hk%T3^u(*Lfq(Na2Ov(oH z6KTF|ATYOHaEPU5`>D~1#&fBu0S;d(g1$qe z6K3l4bSgm+6+s}In51Y73YGFLczyTG7Qq#{enWFQGP|~R<@E8cjyl-z);Lse-S^oI zM2>&Bj%4i%lPqz$0Ta7+s1NS+*1B>d++NTT~+-1&YjvRfaKnm=u>{Xxm}Ofz=@ zw1&UE2F-jvc2;`cIvLisJ{a5J!qeMu;m0UMekx$~_dq~)J`Wm0&~_|C2SJ~I!Fu(r zU6w|Tc$0niJ#U*BvVr{6G}7*?#be$`q_WFjJL`q^qr8Kduc26p`s6Gbm`-E5j?7&j z+Wskvvb7>Ec|0Ae4)eG1`+6pQQEYf#AR?R%U4rb}FUPdmuZ@4}-?g4MIdm+9H~FG@ z-x^8II7_!51OVx>OVGaG!}~Mg1{~ey*6<=+r?e+Na$5Ag3+TH~J z;df-5i5DFw{YKb@()SW|gsIFmfaVnk=Ie8Phfm_t9C;IFQOZgQJW%Jc_qUNTq7|tj z?ul(6;n{t_QYr}Pt*m{T>siQjdvP7SHv~nD?(c6Iu4lva)hYDZ{gqSh!UMcfsxITK zQCCiK+NsDjV%QXGhFOQUwC(x?#4uk)a zZN9AT;^5(FpCG@iR=*0rwpF$^W!C)tqo1-IZ3e^S_x%)Y=i6s<5U)vrZQG-*S0^8$ zFQett*RRjTw$q8@F-#2#K<*Q2E()mJb>RJjKVERq;)GJ$3an!~BK>L;Q0xNxHHnWB z-x{hM@6Ei;}@dmQ!W{pGxziR1kpwzVAjysgS;*$6LtLmy}NhZ3eb6tW2 zvKdYqay2xZ*Gd& zzV;R3LM@*dL0_)}XmtmrPanZ&x2VoCUF!46KELWbTIxso8?O44)>HSl1%hI>gk3Q42x&H}4J>j?vVmVMxRBXLKhi^Sg_wkMaU@JucfPWYn z`Wy@YxV;Ncnn9V(Zp3U=IL~Dlm$OPwz-qgwM8`Vk&$wUJer5tEiAY(67f^B@dB9q) zU06(6*WoPtGltMQmTd3$hex+CKf@k7sp7Fga|eAaOm05%xYrd}=F@7t<^6VCjertd z#D^PCi@ccFkcFj8&;iYKbC7;2 zV61j2P;Mv4{fLtT8~F1+CgGhpHU!h3 zO`FSs7%oH^&+d^d-p9s+ctJtO#z0|t#8uA|2H^@>8^5pl2#mHsAHohT`GE~JBIMz+52QcPY`N_=7u?Q6NpjkA>n2KO$qtm$-6y$clWig4D zU6n3+C1pO57ADH#1?zX*nZABCgOPh$6{9EJe^m6Ue*@rDwO{lb;!KT;0NfnLN{?dI z8MC4c)uJMm3)c&2vvfvql>Ox}9n~70jV_h#MV%$Oo>nwH`n-j0<*%?{5C+w-KnzAg zk(|2V-aoq679%f#zbcft26iNo1YR|blM6f%dM1EsOh}z@=!x2SH%jOrrXpcBTUjg2 zx2Y^P)iu1NWyr24yJk2w;Dd6s{a~}0HK3ZVn>rnN2#YIW9Wh>I!`vIY+52vA3`-)8 z8BuuB6(+Ct5MF9OqwoO}b;K9bHZ&3Y_}?WCXC1QTaEGqS{j4>H$w>Fxn5NxlZ8&(k zDQP~&=)%@M*lY#$AEhz&q3db4ey*|8{{Rm`@V?%{>i3O)H&O{*gc)E_VIRUl5e^&o zIV6VtVptTzj0j!a=qAI?1gsEPm2VS4q!mAE0DK=UqypWdXoUf=VDdq7^ha@u;u8cs zlsW^(i}K$h|G%b>Tz~HfcrvPZ@x##GSw=+UUrbP|eH{$*KN~ey_Lg zYjge!F#+EG>{wfDUvxE;Vg$zh;GHYGcAG9QpR&4ku`LDQS>WUjKhKG=+ZX_FX%pvw zBNO%`pHs|b#qNPx-rVVk^?uh{C$=3InRb zheYHy5k1|`G?gC&9>oP;PO&|-q5$Z~m!RIF4}m8MNf2I6b>(_Xzqt=>*yr|V7Q9bR z)D;7g5;Zm=CLmvHYk-|H0Ncm6;U)l@7(s6j(%tKV|44utT8mw`{W)Ypz;H_~XUv~=^;n!9 z92K}d{XQ(Ntlpx+j6&B!piRO*6Y2#XV0aCA)k97FhT*(TR)+Zth+DgfKXyMS+L zqa!gLYxX>v5H5nG?_MR%j$+_np+cYgE~N0GHSO#2{4N)tZCi;}eG>Q>@Gn~E>sCTrE&ww+3cu3c z`*upe)40le$1BqZjbawIb`@-G`8V}Z(a6@M7%*cWYWv9<1W97$ z!i%U)+IlxXiDLnFJ$9=C@HJdI;KXy+zpMmbSK^PQ3P32ifbXR1Ax_8_)W0$%P(~pH zyFtKb>0C{$Y2$HtKD6ro2Nm;yAWZ(X9kijbc7Z<#{0y+(LVvdk+6n@cQT}+g*rz}r z!@KE_5OZ>5a>BTZMox{o1@RQw>ajXj8_Af0sRD5A@c@qLYXchYebh=g-%$h!=P;cG zw0|3-7PXsbyoQZdAYMU}4ba#r1QjMqD9+pFN9|W5`E}?{DEjX!5&xcYQ5yrGLSB!` zAR8B~F1^{-d$|VudP{xnICiT7a2EI-T2KHsAovWD{6T{TAj9bTCTvx#v{o?~Mfp=S z+oW!wY&f=@PLM8i5&1p|`DuyNwi68a5#Sk|<~qfAXe$Olo!vezJ6^Tw6_~~F9y%mM zygh;mC@TS4+otB&Qb1s}%{T#pAUg3a%P>^{#>Wo;_qEZH1by4t`FaBd zU=G50g8pGtEouj7yo$yv5U--~I%t$r`za?>2^92#2z_h4kiJ*(``57ug{v>c7o@oS zit6T-w%(@~+2!^Bee6~RKyg~skJ7@VHNUBtb0YRmZKy&v6tr7V^;@w5Lp1dxxq?yK zWW@Qks8D>&7;~Qq>?=v!#*4cT_z_&}MO*U?-0WzD0f@mWB7#VkjZ~!h>%QwE`-M4# z_t52YM4T-!0b4}-m(EdSB(`!D$QEr%83R)V;9BE$;D_7lESS3|HZym0)TTn;H?9Q~ zn_Af7%&lM+3FkmEhQKKV#4BjD0?9hqi2ThTQ0o7 z_B(CFZ{Q5r8v?sA2r$Fva2Wv;;}xsHzg2G*vg}>6cy`<<;mer9zbS~XW_xyi9d(?4 zd~x61ihRO^t&OI@_u}FKrWg;c%?4;2-z;hPGennWo@C;oJ5{!}eKhF6|t^mrc zL32Q0T`hrW5a2b(@1dp2e}L`mdlE4{gW9zIzYDq>=Iwji++;o0eOn6{rx5fH!~Ffo zz9*3VPr=^Dkhy!Hw;xQ8Atm6~6&Tj+hhpS*DHxENZG{Sh-gX69Ibn6>bX#(875L?A z^jurPZdL$J;DP}sMgsCLt+JtFheEe7o7;cm5Ih$h&>H`9W zR*G1`Q~?+Vhk<{emhP459Z15(M*_8;P%RYe@uTqTmOW)aEg%rgApJwg!hJ)9K=wTj z^T*KM0SNl8omx-1z{?JxDDVpz0C_t%1wctju(5LC8>o%il7rs>zI3e~ZY$69dSAc@ zSm2j%HI*mEZ(B8ArEV_rIxB|p1pk<+d(GRu7=gn1#_RLFD&{>wt1Q3|0gtuV-_4A+ z<^s@as$R3zuMOMFpKkgo3v1tvFt*ZBcvYKS13ptw4QzCsNJ}M@nJNI|;QN7hx73%0 zi;pIzvoENvzUK-0Y+t4vsLv8)%z;h!TMITx+ZqUFpmzx7Q-$EbyO4cPz`}jdKj`*n zfq$7IQKcN_S}NU7fn#`N=3ZdN^R!K(bhprfB`FBtG{oW<~`w{a(KRkWr6SkEdh`}wP{ zWu5;&-!8xs$`^?^lLiCUA3NIrua#46CnkVl&|p~+5T}H}ns+PYO_v(dzPlTxgFdDxfH}hXB z2dozv=@Du`~Wr(govu$=j+W+Be#Khz(_pj7b+-2H*9c}E z)z;Lv*CydVM)03{*EtMY%wq@cwqkxD=(a_xf}1d;HOt{9M#~I9GxcAt3Rp+|3vdR@ z=Z3<+cuY?D`zZBScujpDe;wT~HT{&@R^EHTv@?+vOcj7pI0pR3v~`apOgej?MxccO%39KLNH=-Y_DdnHV5jcf_-T_#+7xp~~hu#ARo`yXS!|YM$%)4v^ z$m0l5v+ zl74zMZi1R?QswtcDF46&_KZ#1dZB+m@Xv7*T1-)ow(0sJaSQ{J>FthM1>b=#Vii?WAossQXT1eZSDR^&h7%$-R%cYmnX4$qL~(~nG9 z&8+%t!|)YJT>w5jil`QiZiZA57%~Js==EIyA?g@{BxMK&OAxIhn->zj_>EC#+b&)K zezmRpeJyb#FaVc;pKYtNuc{4x!N_QfIji8;mhi9iZ9tm_%%(KLYJV2kz;b62n{QEx z+PX);A>cn}@>0wt+g6<;0A45I^PceE);lSHh^G`ZGX?b-1yw7* zIiQd!1F-XW3iuD&>(1EDo~Ko0CcxUQE%g!XKpqT8F-Wk^(jS*yDDU&L3=}Y3=*x2~3dMaD=D~|5Y{T*IVX6RB(F6WCa93L$2K^&(XYP?e{b>6J zfm{~o#pr)8Mb8)dLt4K{pjZ3fzGC3H3;Dq)ued>jrf(Dl;00Q&ulzgK znqLvI)l|Rj2>($&{W@%+6jb61stQJga)pEo#4M38NQpQLJc9|pl^|~G9szT}pTJES zJVg~PF#w7V>q8fXt3!QkKn#4Hh-Vp8@?^_OL&b70l%w8S>1<{s>e`oS|9rhiz^n#S z24Ls#UBC~v*PYnz;?q`w`Opc_nsh!-&^P-0YrgY#siod%_1iH7e5udIeZa}zOt|t| zo38KQ0=|4rpK^=1Q51j}_3oO7m!hd@deeswv`zo;z3T$GzOw0u$ zmPv?9%BBJ{i1`r-nQfN^_yF)9w%FgzgjN&)rC6LoYlUf%_8$Px67fwUl3}aySR|FA z`yjmrMol|h4)CjU160cj=jSj8x6$J%S>On*1*}dLfFf=K{wv(<<*gv-9f>=0kA|7` zuf8D7EcsCaz9fh%^#L-aLQDDlC97YpO%(;ZrSNBz@LxX@^VTn>KG;^UiHnuGVJA_$ zQ4|1h0cl@otFup9Ykt{?-8vE<#uNN<6~{E6$Evc13w)5E^O1I0 z00aCH+AAhnyfES6=*nv8s4VCw-VP?sucd?i?(CpK%1`8J3 z?vaqkWu7Nwo_%x(+H(R-6@VN9{3pN%TkO(y7oJuL7Q&(Lzs7%G@8ho*`1x{1$u}tq zcKE5r23U%j0L67J>?K3c!st zcI`Ai0Q_gPcu&IKeuB>4j*XY|fVu|izb-JamKhid|C(clmVO>5FftHuEX&^u23$E2 zbMlwBvh=nC3;Z)~u*!dB+-N_dpU1@mw1VHZN$@kKZV(^ON*{mwXu+=t1C%9V&Jl6h z^Y2%sfAhed03RUed^mkBj^m(@|aKFsblj5XA!PwItZ;2@b;II$)Z*a5z zwE_{No&GUwv~1$lSBTf%z(z}`O^VdNZ7%y;OZ|_UGoZ4M@q_(F#3H!;iE{FnENgGK z>HB{k_~~o=sN2VlrT`oV{$*R84OHdFuySsg7C25s^tgf_#u5A*SS}KCo`@?X^|qbD zD8cWq&miVUrDOIYZMp*bI2NFlii|f2viQqMJ28F`U>)s$7RzVYLi005>M2atbGk?>hIxqw9~!oDil9j=bz&-;=_!Jqe& zpLd>+M`ez8nRyON7ok{J!2cMetud!fI`>A!hk*Zr77Mx=6KdGM7bPs*Th#=OE|aXi zPO|ngcJmCHY*qyBNJgMx=D>nGz>Xj6r)mEq>j=b~mbZRJ8C-7D`hNxIj=te>BPsyT z1OK|M&JtDmF`LM1jm3fLg!y&@{9OAOxI)6&G_Y?2J0>lgqLvA$o~r}qN2MFwfoYQk z0Qh~tA8NVJ8x<|a0Epnx_u1!7Vm`+vSBBO7Mk}Y2Q2fPx&F``ATIgc9PiA;V7Pv?H zbO@*~TbwHcExQ12Wd-0i;Lp<{^$*bL9aS+0q&UkSLk&~aqR}$R`f-xAm#`Zr(PTXp z!i)?G9H|hD8O@&wd>!XF6}a%Fhzp-M;3TQ=9o?W z{90<8y9f#~0Bu?Bx3UYM1N=$gV{LXC1T!}59YfVfF#t*PFCA(EXuO8qIEh_-5xemw z8ZW1j_>83cEA;|KQTwIO*h+%}o0k$!{2L+JZ1Y`t4L4cZO@SLx0RT5Qz`tp+Klz6? zGM_Wp(F5VA;J@NFi?EJzo|v;lEDiJbwjtZ)F$258$HyTmAdH{kv6IFnQEJ9s`iS1w-o_*G7{~bn`TJ?IrB` zYiM-25HPrPfu16DKbFAXvLvu7r++Qx%1dpg{ectytp%cAZ``N~Kmz6&-2& z$8{s2t+@a+0V@a*@HO4!YdRo;)aUQuYZ~>!9?I`bb6mhUj6l);nNmnMpOE~uVrooM>004Xm_^CEK{P`pb z{-x2k3>{oY7u zO#x6uH-Im($@4NGsk|0-Lc2)`7i zg#g@=3cz9Df5HXiwgzKD?e^~lx>6MKC4x)K!a8k}9^+O8Y>Y-1(e+o+wHMLN)75~% zQJDZ%uPQ!ZcwD@0Ir(oagNtqY{uTHMZW7;rh8tM{NPxc&oNBAXO;!0{HRAQ4sX}0J zn*tjs7f5)Ugo|nZezAQS)qz+l`)KH6dy0S}%p&HG(>J$c+ExMvAr z3S2?$=h@&D1}W*E1_U;JMktQjs3=t1juQNWaGP{_k1X(n%(F;Xy8`!NAwk1PRDpIiG#l`R%0=x zLCO!ZgVmJgKTXUMmbehCRUKHx`@f2DScdH?1`Y}E1Yzetrk9wOswjH67x>G#xPV&? zN(=Wh5#&o|VBSng|0W-P0mI!*%E1=aes%64vO+>C!lHC|(#-Q7S>QJ5Vk*9UXcqXT zHmTr`fpa?GjBd6$7r?E;00{7-xN^U({>?$KH=dpSpmaL-h%t**x_*eFOJKOm6Xv<_ zAJPFsf`DWV-FORKeF0s61EMSV6$ZBo1{@vm=TZM_CnDbdS%b!H%C;EzyW9kM|7G0h z3V;RvFI;41YxoH}Fuxr5t^hZv#VA)&n*R(5D`<@bxEeqIsBPm}{dIhT*H(UnUgule zcLe}^3-CVxdv>7j-HcXT0Er-1L`^e|pP?#bYl8#RMJ);U{8Q~Sv+VmA9%7dF%L2#f z)4^bC&oe^cr{9vEZv*8m-QcTwg=h5&=ZG|A0Vc(*qyYRb;J*cC+U!&a?Ci{YZ4eyj z2pz)C9Ry}yHTcgL{KKQQBIt{3fzJqdeIy&Oc?#BEfVEd)a0$u*gWGWd_=-xhVR`$f zEt{v?PW$^buKvtThqiCj^}siQe~1f=X=OlIvR3}040u=2x3?#l0m>=~D_AduukK_` zLVlcWb=$YY05tcb2>X%XzhWl&21$Gl+xBz+VVrjS7oajb?ahi-6aaGDr4)hhHSo5L zlAQUzY7k$(EZ#OJ_ydF^bhuw;*o&*+XQ{iEt(ILm0~ZLJ@V0JpMhC2rq!lj&(~j_m zTSozS5AauLe_C$s^&W`&y?1mn0V;%q;q53PNpc=1xU)AiyVb>Iw_BVGK*VDW(&PMX zS^S3z*a!w^A-af$d!Ta&I(tDn#i#0@Zi~N%3!jd-^!d)%M~sJ6;BRn)*Zgn7&5}#| zI`D14k+wQKfi+f4@{}T%NhF(%Z+w$;PjtP)byRG-t_n%%@Y7yQcfr*9a z(?oTt4wJy(W(+)s3(mY1&2W6Hy ziuwFaZiVVBf$kHDa!w;&WsO&KjdKjx#FGCOgv%1!S6OM}{d*lZ8B5#6u67gd$5GEu zx7~3N?2Q*^zg>)(FB$`4FlG)2u)6MOdhr803yst52+}^p+m^Bexfx&Dma+pP z;#>vE6h~$aUL^Q4GMl`hadZOPcBJef z+@N&{_>GqP-fd7?sIQ=?W`l6O0B$~cQ`@GJ!3uOR+$lZolRgWC1@}M`t)HJyhQ?b0 zENRT!Y;t-?^Ji_!?g~%k74cMuiEuM30DFP|8Th^(=v!yIk47`yhr3#)<{|gri(rC% z1QMe0DO5Mz%~o~qSNYCsNeMs@OnD&pYAP!FW~S ztGM#LN2JI5WPzt-o;|6rf1FR2nkcwwtKZfEU)5#4pi8`>>#U@+6v`Oyx`?z@3E*a} z1UQe2XZk}s@%MFuBhh^Cy`gAehELcJ_A8|T8nZwc-i634g}2HJ49qXGoH9uLa-Kpk zJf{=_3Dezn(*+E!J`ZazLv#sjoVP<@`MHSmzY?IfZCUn3;QyorO?5ZpW>NsaS)Kp1 z!__8i@ zQa9P88oyHPv$QUPX{`|8O%uQ5V+NP&|DWx|-xtViyl3V^gk~Wu2y68sNi-Yfaz#L7 zjv%}XF$)YgrjTs4Ea=m|r7l}wm>XE^P723*`|ZH70jn>->Wi>>7Bq&<(=lg%3X;{f zne0{IuL399eg?Y@HILpwzEqea>LG zNBZ1L-%Z$~S@k0EszytBI8T>c?*3(sImsrcb(2*s(){DOEV6i%JPt+5KHaOs&E^8= z1AiL$6SNh_7u?xZb%B}b4hN6=2ZoUvnl6a+34*(Tw@K{fQs2%RcSiZ} zz})RGdH1!H|IkI?T~NWLkoHFm(FKT?kj)uo`Eyn`PV7WE^8W|;nH}hN*WqSk003UZ z1#YyOj&=?W|1uG$(AaFt>fi4Ac7^}dxezSEodn^3FN@qE;Z8-kei-;Wz(YIK|Mf&G zE&x#M(5aeR?xST}J?&3=K_SB3(&vL_50A?nbCOo^8&NRG&n6fECw0J=^$MTUC0^Ba zRt2LhTPD_=--<+-*~{=k*`{j0#n z4m^ilhnrCW0GA&03vGA$6>R6P5hv@zcz_I7L+@|BUZwn-mbbSrvn)kIzTF(?{H4zA zESO-Yd|e;Gr83=YN5DOmmX`<53Df;-mk)bvQfWkIWMKmA?j$(q_0OR%J@l}P{0*h`2yi-)qlWr)N9`@H2 zOms5Qm2Vi-wk`ZOaY4-A*oo(`8*#I_05V(w{uf*z+8r(SD?d%#c?c8zVZtuyC^(wb zzgnukp{B+P7Whc zy*Q&FI1CbE<1;96?(Y{V$nLU>K_o32q*8Pj_yyJ^tvIMsIv$L@l<4wTMD1WFp8Zeb zru)5RaHIc#M&Yx#cz{+T-6Jr6n<)6VBvF9WSVp7QN5u*>uUD64%Qp4vUFoqXdzhDb zf;195RFOZWhs_TJdv~(f#kb6N(Nc~It*+hAZO+K$z_^dAR3hS&$k~8+%aof12t=qWmEx7@<@{{a#EaIa5 z|1>)!`~&I72f81!J#)BIRs}0lGLAESOD z>Jkg!=kvQ~UJVk&?8Ss3Ha>~!dP-1AUf`pw3-HaRc2Q)4&;wGv&*>=aTVLSf=1N(Mi+NrX2vz1jp{<>^K;1~ZFW@Lsv zvX@zAQ{nGhWqB;sG21hLUGCyR)8C2u02$teo4er?J9v(3g;wrUHq15q>WA%6V4sA% zM;7^j?BNJqq~zz%*a7$S4GD0Lh_C7jzipRzPFJ}|>}Bug=P70c)OJAuE6o7rzigg=Pg+j(NJCw!vo2mPh{vX?Cly7S`zsOIQu9|ZTR%PS)#BRK?Q-PoVg7(wLZwTCsxwK`xg?ni}*7o0f z0u3&p@rMbei%W2>x998W|Lv^ju74TTqOjJH4hv?1S(zgsfP(P%e@odq+(F+Q3wp_~ z>Jn?TUR)!?K^!ylHZCUMMl7}w06#psYIdjk~%ttB*HB$^%T?oP&iM(i+h$kmc&IA95 z8;i1i2k>LK3V%EG+tS7G!RT=JgB>HCAbYM^tVyCPfI%cEI|YX0%aCyzrfyc-NU06d zL1Z3?KsQSLR*$cYhf-b6S_IMSs_Wm}iJ(7lR{tLZ&g{_h*wwfd6aa8D20j8j+H$}0 zGS(IA<3V{*#@0dq3Pf-KNUEyN~&Y(*&$ct~c< zLDR9nsaM!!M}h*uO&|PixH{X$mJyqG7uTCOMht+OwiI+6jf}GOq5z@9fa?*!8$o6o5@! zF`AF#{BNy6L7pQqdoa;cgoWZHRja%?Helqs2+acDC;NpyeHLYbzVwk{t(3B$uM_+N zMzV9slQJj95P!-pr=ejxf*D+z;5@GM=8cqlYjATs(7)3-j{1MzyQoS3PcB6JD^b zC;%663c&KD9qlkOMe%Pl;k&XGX3TAa+q)k%9a-$CHwsx|Hj>jsdKmz#n^-n6GJ{Cy z#e0;E1M=*El7diV1$;%oI3+*?)pd$x{(LroYCrgk2BYUJYhMwy>pLO*EiUEnrZ4w9 z3b%>^0FL6h415PISK5j}zCyyCnD`NbKvO>S>coAC9+RSw&)XLjf({`I%rkH12qc6; zpx+3=KO`-R?F5x~Xe3uO8hn|}wxRwb3AG0*>AcoeX3B%$344sl(%$~uj^_`^Sjyj%I{Yu%(oWk<0uE?D+EQi zhOj}BG5{01050JafGd-Bw1b!f{=c{Yv!gqCqQ2~p?(BX{dgee!v&wvcWx#rJnpl?$ z!q@5ms~Z?*5XnLjWauEOvH+PfQ0ERPt~(dQ97q7VMjm)ravNl*Q8Gj?C9Hp0Y_hUb zu9Ba}rC_e^+V*0 zq4@$NtYMQAbhsTOb5!#5De3|0l?xWHhJcnc1JZ3`4q^zg$tje`dk-^(fb_U*hC!F# zVszQ+##gaBlkNwO4gPaDH_|PQTZsVxH()=Di$uS#?ao)he3`^PL73b{P$;c8Is~v3 z3m`JakwT9yi!3lFvl!#k{Y}E(v;IYJaf?MZz>=_{mx*)}fIddvCw)0ZJb0dHr|YlZ z34A-Sgp1qQ$!vs4A;1p+k5ANz2#<#I_HON&qtfGPv%vjkhJNOsC5zKHL^zuNo4Up~ zbd{6%G=FwUHJ?g=p2sBAu2a)z-Jd@`Q=sYJxLraP4=}xqV*oBs*w0Sj{kUMi z?`MaNtgb9XcXd8u=gjRrzmQaAOrooZbP?&1k1kafAdf@JE%`Dt zSz!gt3?egWOh8<{mclsV=)NC#a>73J1L5A}cbWacqh^l9?0I_8 z{A(!3b%W=0g%@;<3q(YfX#VZ^>BkV-Wrd)kC`ff~fMIvl?V7&Vn_}$?_A)If09SAd zz;1FG^>G&e-^3NX+EIq0EA!FaosZfDb63x&{Ug1?nmvOZPKT0@D2h}rN=dMG4UrH- zze35^QU7%TfrW8P{NsBdbEt0Mrf8`uBq9c3U1jjBCW9Tx^#`Yc{3Tp4=5A*guL*8N z1pr)KfQz_X^j_PYUqFMelh}9D(L)$hrbqoBNlPo6WG774^BS2`}q9&*=)U=?2Rr!)X5I%#IA>3H);XfUD`F(pIY5GDUa;t1s$h zjWn5bkY5IVg59G4+yVRr+;qN&cKT#pnUC%cztt`VcYDHL+0@Id*|V-Z?+|78UlH!T zvshilS>ZEO0*{B5{RnHn!Wj5%yNHPkt zxK$MZaQWx6zz5lZoZK^L@J*8V89I6pV-#Psmq>l@htd@7-=)hQ=9y!TK!R;p{i!u( z{2yqseJ=br3g;~UsOQO)faqE%0fKYWdh|Lb;zQ#xRy*4p?ivbzi)GE8XG1TdKC@jA#BMoP45(~(a7ut;(^>(BdY6FT zcV@+V+X_Za`Yix~S21wiS^m*;J1zWQ#Z5%^^&LFN4T)P>0RX3legzk_)8?#!8RR6^ zJWrgwhmIcb-2t_}e*b@AhCX{(V3t0nk-n$2?xp_?Ctj^r7%W<#{fj^FdL|-s2YlGf zaE>JYrfvp1m?D@V#97+khEo7uW_JV#{w`cr$was(n2i;>j^?*RVOh1;wqc!Dlmfqb zlj2bBs(OwsO9j^`2EM`&iRz1biA}$P_SInxrvRLv^!{H33@&x`e+T{}+{8XRjv3h( z-5-8b_n13|!apHq)t+G^&G9b^_oDEx|CQGNbXC_;VvNj^iHVBfuM`3*8Vt2<0K_1& z2)br9`i$-{?SB!cr2Wbcp5unat*!uodqG~n375S)(7&9(ns1UM&k*VX35?eLC_MVV zL&zfYEHFn%=vj4JQU2bK&Sb~bGXy#9zg9f1Mls1*ft=2rBQW1$W@QB%eN8vb4yFkD zIE8|vdU2itvdvH@uPlUUIndAt)PLZk|{V7H;)#dk>F`lr_6~_kFVcYJ3;t&d zxVcBBL4P%vDgX}0alWCCUsCVV$clh#Rf@rZy!dvR0^Y#hf?Slt9A2oAwpp)I#NHoiK(ix@*X77KWE_<10jv36*>Ziu)qO@Ml?H{q9+~>cU2Kz`sF!-8% zk=CnY1pvBYbh*A*J_5gLpTBa4&V*oG}m6s|4y9yXd>Jf%qI8ATv%T` zimR~hs~G}?>3z#Wf23kD=6O8@rKrew%QzRnOL|GxC$H_kfpY;|i=eJ!z@G*FM_k>9 zYxR!nL38imq3|QYjO^)T1$q=%(+h0qa-$F*H7luO1oG{5Eqx)cL|E3+(!qJvz_IE8 zkQ)zzLG9@%-uyY$0YuB+H<^n;@Jn#zFwl@4HfDcUC$$e(d-fw2ZaVOkqrs3;S`Ra}tudgi? zgvNe~@8D422*d_nvX^L40XRMB{U3ov;74#)|M%lc`(6_W#@-RUWAH%up-z|CP`x5Q z07iPmxtm3!ub7h`}arMbYNZsoFC;E&P88 z_~TqVcIbx1Q~@X=2EKsvF;80Hr4i?`!Doq*C(N9Entef!9>Zu`19cVpCZYTt?Vk#N zRz0h}+}>vd^6drd-`iiDy-?&y=?9OQe)47ANG_6G%Xe!5$J~4r=No<`#K~Dnb{LezEmPzrSdbyfTP3f5E6;?69-=EH2{z^&LLXO@XNbP{juDdEE5D z5AM`SE~CNcB;uiPmIt+${(drn4O>$Fjk*0**1(FgN-F$o{c;Qk?>ef#m=@@5E4LMq z2c#Fg-^?X1>Sp|w?s%;LAA%dGzZ+NT`8=-R(@tg!d>d|h*NJe<%<`a_Go$kPM+x(- zT?9?-#!(Em+V3lYS*!G1Wu*W}1YWWiS+j#S6o7wByG5c5uCUX8mwuk)8qb%~lezez z@B_)6!DC%B%o-{R@l5G6bTD)nuu4&Fl*<1_jB*gvZOw#yS~XBt5duVJO5*^9F(l=F zG)}%AMT1`nRF`-9UOor>r|I_;V_>QP)MFXP1U!wKpk_yKSrhZ?tm^)tlRPOiV)E&- zs2BboEmxb{UsV!RlvTatX#XKR2B4z3m#KbVyDwP$wb!G-QRxI9GxMA$iC(;R83GwX z;2~U&{)0FR@eE8p{ag(`hGQNkfj9+VUYdgdX{O;TvbgSeGiHC4OWWep)VB7|1Q8OW zyksxR>f{Q*0Qe`siHV=0yXc32{}T9La7@xp1OtzPF37>?(ePXKu(@{_9OwJ$tIH5b zA2(0LYEAlRlW5;c)_k5TlF5CgpLy{U%^@apWWf} z+*Ft<0L{1vd>I$yb!4YbvZ_}8t*+1sjD0tA(ixidzHo0U?34X4OGCYW2C&@s&O#o6gpJELe~ZCVE!aWN__*12gn-wFABnr^KDYrHr*1DEN`| zGZBuNS$Qa!FU_i#!KeC*gTKH3>KTJlUt47lG@g6BYqB6O+6%O(0K7Fp9|GKqOY8e9 zIHmELnAbqS_BHbv3X5_zU^}g%4f#Soc zd!D5pMbpy3ipXp#@YBBrLD@()qfftGC<{1x+>>Q9DhLOWrol*$NWir{K42)5}-JE8&oVS_A={fj&LE}PpUe8fe{!h zC9sB}@b;xs+nNuW#o)>Q9ro+G%6YqaEt!A}bGV?+@59YDc$)SUfp5jJ02ASEGs{C+ zb+nSe+)g||dEl;hDQu^|ack-$5w5oT@vAsiaAl_dC@xLx z2XXoR*Zlnq=_L0BPezY~@9*?wE)Dh@-f)U>Atm9j`ERfzGb9X1v@`)wEvqw%r>XJ> zRmLFi+p-2E7@5PxF&R`Z#~abFCUNpym&qr6+6t#|aT-6j!{@mvF;xJz#tB@C;J2^? zvj=8KQ2CNwGcTHfeMaVWKOIv?vDbb|6tAMJ*rj^mU)WNz_Dj}$-cs^`zI<#!X{cru z%ybURlbw6bN4iJ#I4jAk@rqo7%7JxQz_B^M2WRzNz$pTg#0Y#C7Y8sA?g?he7=ZGv z-LmAb*S5Y+Ky!aun9*-UTbi;9%I{%QKY3dh18{*B6@WLlaZG@V?fGN4S>b*Vmri;; z-bZF-F?y`?q2yTbc+W`3X|WPx(d!=&$PAILV~J@D{wrw&RTiMx`p>r% zjR(s*N`%N9i9H>yN57U%I9$p7t!YKiJcj_bx@`Bwk zpOsa8%*@!k=$Y!&y-=I`KOCqvwfvWdZR+WMPp~si@LyTLd*`RLKNSSsa3B57?Fa#f znUnAA+=T?1JeypSf!gab=;9QCXK-mtgY{yCZs= zxohxL=Oc2++||u)Vy0wODStt=ybZ6dTQ>v*(kDu5`4`Vwtp->p+M)PJ>mv&4xPc8~ zeLdQUKP6Vrcdo&`Jq!Fv;9oGU@^{skDgfi-mGtv1xCv@@3@3G9evK=7B=3qEw{kN*6=3z)a^(jC6*=V%BuzBjFw9 z9i2V)>-LhKvm4hsF2KhuF5>(9$&2}%#Z59ZEv<_|C!O;Ric&vM0<4|Ex|z9`#>({!$+VSY`qY-C<^cRvZWQf40A08u$3CWd_k| z!kcz8{<=|JyB0F#Ebu3A4A4~gPk?Kh;&Kz<=WrwH-^A4l*fAWpo56n?y=GqwH{w4j zw+D;bal*1D@UCL{dq335w=`_8>}yz-t@{n6&rIhIj7f8az3c5@!567&>NG8ibPFa%!gl09Y$YL_t(+ zajcA7-%ekdFwu$oDq5%=0`>>995su~&|zlqf-<=f7U~U{0O#WQ9^m)kEdSXF&(#KW zuN;UT>%3QQGk5n;BX)SFi?j3<1NIow`PmK2_vd2Rmx5hcWR{3kJ?qU5SXBe+0s}|2 z$s!Y7h+;M#Y}iO&(I`1(^xCj`XK=#*pEDKy6Jx3XY#%>^d-47jJFEmOYhwOlbV8mF z*W>@m9Mk({HXZPaRJ{T#y2KjGrJCHHPG95S&ndsEKrajzQr+65G>CNQckd(!=4#HB zy9^%GZtyod_wXKiga0FXJ3OP&^?nySxcUK4;ex|{1E&mpisqofR#FSCl&$;*)K=dc zh3yFNbbaKIDr0TWl!&f`9FjSXngtfqbhQm)6?fkzwG_(=z&>2C=kEo+1GtB4SF(2` z0>b2;;KBGE;k$!bSq!abn->LrSqaFk{c#k6Y%CCkKKn_CS?5Bf|E8N+JlBYKN5RFA zTuwIaOT@{gYsDm=!ukCFB~#(w3aSCZI-X5JSInJDnh7SxZWSSnYx9%Il}>Vf*?{a1Itu(dxFE4_;!2DDJT4=|FE!jA10Ygk6<3Ay z=uvMw3c*%{Lrr{uj_xblJtHB9%p6C}A`8+(5Nx(z1rcdO0RWfb@lISR=--Vi+;h#! z^^O5ulzs8z;k)gf!TlW}Fg6vfWozHvKdIR^zCwWdZ4EPWh(sechhsy{ImJ7^gvM(S zt1%~%jpS8hubmt3IIg^JW`Ir60;VwlSC5x*!r}e6fTA76X&snfvX?Xvk|$+Bx)O?t zvdR*x>SR*2Dwpra_gfTw_>~xe%A`VBtD+TO6!JnpJVL*7TVb1vQ*h})nbDTmRW{?( z&JGfhyG=j%&TzjhN*KLh*I6aG-bz4*5T^`$3r-pMD6S^N2Chy-CVVEs?ctn#hgry? z>ZteKkK^y(YX5|NHDn@W*$1-W+q-CfC z1TsUc8(1RhpDV-djj;e81E{iL2l|TLu&)QI6VK-`E?xot2u=x~qD4#^)u$RrNvL3(F%;~JIn^l`z{)L}$?L~v*&T16DX*aHQ1;MS*$N82&j`J;l z1UD1m{gZZlG@MNyHG4`5Kp9&J@v=fzuKwqBEnD?f?r*d*GA~_@1$%ioILHyRKuh57 z$_Bp+SBri}VL`rbSA$=-7n8k2$$io>0U}B{ZLiD-NJ%O1+IYtl6$$USf-GHSSkv#< zA2GT^kd}~?{2|@aASD6{j7CN2u92cNf^>>BlG3q_Mv(3t-E4FW*famv^I|V|U*B`? zQ}>C_sa~x|suKKVuU~FE`vNwiddLtK#ro=8Lz$y9nWE*4t#m9Z2J`uhzv(?018O|* z*R<_EW`G0fUR?s75r9KDV3k3`hlA*stM;O=rQn%*NA>|-0k6Q~892sXDyAv&SCJ@R z9@&94tK4{8zfYmjUFjl#-4Z+u51yI;yqRw&5?D#|zN{?XxVjE79ck^)&gVkYo?RO4 zJMu>YICI3F+pQxSTGzl6UtTQXc1FJy63vW|7%VG{u+&V3NQ) zvJv+7t2f!m>^@laqIl}~uEAs)kTCZ3ZZMdw%8e3Ed`ZQ@wzUyWr1aDdJHx&zKtf5_ z2vjyU%BW7?gLxeei3e@rSm|M(c{bAr$}TzDez9ygsB1Z+?X6;TCU#8j59rbeiYB&YS=Z@mhdsr|F3AyXoFr`-do4cYNOFw*E;>)JO z*^NnWzuB>i=*_CJCmNiz0Qm)_JeIQS4gJN zt{T#Q`Ab5EvwNCntnao>3qXHfRe$FxMRY$+JU^imhlN9%4>cZf?$)l^J=as{hv7ar zuGT9j=G#Bf?C$!luznfT-?p&c>)&MGj4m_v1Uz+JC9^ei2`=$ks*J0~W_xfIRZCso z-Mtb$61%AQnic_gl%1+-QaOfo+ED`{X?ZU?<-0;>Id>z#Gv@Ozl4LPjdc^RDJPT7 zL>x3Yl7md{uQ5w!kE*N*kw9(#6x?A?#7{<+(usRBI0$y-^5t6$$@|lIRq8VG**5PnDr|rCB4Yjob?~MNap+Jdo+;0!aFYQC^LwoM!Gq5coDCv?@wMYEh@t% z3KRb?^z$LJnn6=-ZZ}&p@#0f~Z)X3_dUD7=l?zb+N*Yq`Duj=w{T>#p%0uh`P=N&e z7k4d`#+ADN+*V(JF}$g!)$G&i=5r*j0qCE6bKi}OJh4a-_Ft|#I6aObZ{}knxgAV~ zb+Umi<;$^uIIm9g;$Ixm?ozpOrtc&n*)WPcXX_x`*#P1ruC%>4q7PYp+|H6$r!Dal zdraISAi#G@o?e~@e@mZYLd3&?rR2^*i>w=!j%led@rYDF(+kD_usI^9Et?RrL|e9g zYSDe}sQBZ+^v4sNUG}?Q&VLpM>*PnFmhGvb!I*(hg@mklKfkWdVtQ&Lpp|0{VIYIV z+HgRN+V=sPP13k7&@?Tx;$6+&pls;4+E8woJ&59APZ4BKh-uNbVmM))cyUE1hK0Ru z_f^SL`lxuACnW;h-HIJhWGlZk&l>o4C!aKNSGR41K{Mxfo3$(S{3vZ^=$|QLI zUGT5CQz6#Q@2bZQTtX`z0X0w=Y5W$6rT!m#Piz{CZ#sO#1sw8ou@n`kJCd?B1XuMj zxDy2|drJ7Qet}e5?6oq73rQD@X2XwktmMD>%08jxcH7ZLzM{= zsNmH|-`5v}7s!wh(L}sRO{NVRtlH0-UD(H`)41mj0RwboHG60_Fmc}@6BS&$*&hpm zK`*Z&d|kUe=`DU;=iK9y{?a||{Bs62nfx-s4CNaJTiyPIzzs;>W9ioL`3(dS5Jbem zG^s2;Jz}@VGCH0el~UiV*#oj7m`FMs>J>D{HlMY@`bZggniY1r^}NV%)qc{rNLAU7 ze(~<4C~X{#P*M212LA2w#dghdTZfKPle)i7FL}bCpGtEJGfXr!O1AQ4RZDQ0;(r_< zBcG3wCf~Q%eks-+i}iW@{t;J7qLdiuq>b*^bse<&>uFl1?T4U;^$SE^a(S15^2~?^ zxk{8q>R~36Uez3(eSTVX!!)^I_`U*8FxCf+Dqe4zf7f5ooOznp|5vuDuqa%cJGJRQ zqTpV^1J!TWN_+Jt%E_eveK$wHi45t2v!qKo1oRUO>y$zD2G@mzv9M|_?8T&&ER8BT zH`Pt=8xHp1Pubn0GDzje+Eg)??Xx zOfBMX_AtYLj z-XJyGz6qqWb&j6vkaKK7f0ZkF9ou?l#bC5jZeQ~Ef2-GJei1@qv38MyTPLLi^ zlIlY9-=%64EmQv`wS~{aWu%*ctj8=Gt!sgSpF;%}|1v65&bj!@PD}9^1KGNHD&%Pi zXfr^KV<(j_tzqZQ7!~-(jmHAp#;AxN02i85@vh*XqN1{v3JSg)eqt@n{IntQo`*>z z)+mh~tazYLhLi)TnLL~mt`Sh9RjhHjo}+!m-69l66TUW@hpxvnw5{(9-aG{mMo zWU;Xk59K{HE;f%aHf6Ga|0f7Q>$_Mb&AxyMUh zH`vX$mu8JyOiULRJH>7~WATzQ%)bUCCC;xbdv-D+8>UXKXbMqX}dh~)lBNI!ypUGb~eCl9r9dFdH^uq^=jz%1J?&$SxmI+6hjJca#Ir0+t}uZID9ei zGmz*4HER0<8CPAh-zo+^;opL-3Qu-$Y6AmGri?Z?iBaqa9%e+$=TMlMDiUI@2WchXv@ z#pPEU5fDwa4XuGoJwnuFqMD!mT99a@U^N*K>r*EIF}1%3#f*ZkYSk&0T`qgbz2mva zy^qCxvI@Ca!3$N#2G`Xdf3Sx${G=y-OnJaan)tS zRJSgN|5qTvlMES;WQz)uGHG}GSyNp>B3YbY-C?O`rqdMk9{IGoZ>K6N;3=oZF-bxX z>#KLX21W=E0Bd`yJX44zgx7=6bUF z+79dPI`qy$(d6P|U{|oTl)VC@vwN8bbJ!i!UiF>>p0L)}$?Hv6Oa#5?CWM=~C1=R? ziI>yCl}6q(-My)^>$Ef3z?rD^$?Wv()p)+^85T5ro?xw$wm<~-dJkqHrs$=6Ofn)I z4;L!twPYq{n&4!^zpf!5G(MsQ=Of&OEkI{CyBK~&o*nlVuRJO z#o(F==WE14g`(l?TX}h<@hd{@)P{lFr%tpK#}U1n#{5`2EW(W`%?=|3j|g zpgF4E?9;RnU<}5s&0{(yUj{n58sA?+(6IJ`tTmyhX@0%VJ?grnEJ;;+Kw{BJ$gJue z9o~a<0f-dWNPscR#l~y79@|<{zi6h?7wgMQ*@47crbb2golDVkY|idIe>I$OijRvz_*h3M~9Cw7^nVZmDnqW@S1 zErmQ191tFx-u#4W*!4nXxf_6vOn)4R_wmP{qR{|_!T%s&6Pt2?Ik*R!=BAK}Y9SNE zay=so?5>JbU*8|sDl2sA{~{#OzUm#M3J+z4zojKu*QGpsdnj17 zI;xD^MM#GxJ0Dyg|D1&6C`+vubbTWlKV-78bE$c^B8RdHvq~|9B^*bd}IP^gfhJ27;-&+VIC(G1ZrZlFivW52~$lspc+ie^wuE^bsV zWfHx@gsYm`Wn?$eDP7F34hz)(gzUJN*$P@#ISJe2-9YuAUS0Wkyg;eSLLh{6C^B3XlGDED)%J4XLM!N0_;w)}zD_P)UD>QFRk zvoCYCZL~;Dg`rz9{L|74`aGNm8S|6;11vudOEUD`_t66dGw|TU?$XA1!mzCMG0_$9 zWliyO{a*kH&cV8@(IgEqPZHmRROxy8rJE8sT93;l2J(uQsN7J)?%h^uwd(IV@XDvZH@_DI-%=#~Jh!SM!Uz??qhyqf z&zyQ&f3t)v!=VVVg$f&Cv}$d6H>BcJqNM4?q|>tFrRz&Uk+D)&a$Lu_9WZz=H3|Qg zi?edh-XZMfuK7G$-XrlM?OEYg(3?+DsQWJr&*wEp=4X?ezB!uJl}KOS{ye|=5|YleF?xRi)0;V&Zv3~LD|(`*V>A64^Pbpura1Z`1?HF~OWx(InvRIjdK${SNnf0%ms zJQ5Ywf(*Fz*^_F^2z=H`5B}i#MnOi>$ud4|xGpa2IX1y3zHr*!E6l;!H+Qc+l^{b0|7yh|ipK6D8amuy zd$Rn*x_VybfFC=|=>GFiZ}8n&bgML3)<;gqql1%^O|zDddXa64$Z+C!538=f(cce( zM2un+%CKt!POy=A*m+&X!>tH^i!Z8Mk-Ij?RrA}QHz(6OhY$($i}UV!y-eFRB@P=| zp;D_OJOfWG&=U$5^v^IzszG96jZZ{@x_0KRU@cCr@w-pF#*}H*?WUuK$t{pK3RIZ(b%0=Y)DWz^^o* zWa$wmfl}n6*z==%C&lcv(~jlMDbQ)PL*n6r(CWn;>*3Zn3-;GCcTO?#SLYQyc-LAm zMG3QM+RIFwZnek*(i5SVw;wC_pcEi7m^^?8HKFOjXx=kS2`pUJ%D#?YCAfhE4(v* zp1JM-0hx4NgO%`ZktS{kp)unUv9L^E#=Soko+ddrD=( zcVj(|9;{YYC|Sk=WTGfV)Do@K{P#9B;%5>xC2fV=p10_*J*l5?93QTw9~R*k!^H)H z0>>Aw1Z(pJHf5H|si^7{=KAX_dL3@C-%vfw8&U8HsC&=Oc*T)gII3+MjHf)zmKWt& zShYH5zg17WuyL0Se&WaPw^BJ5W3enpD}WCb!bVd&KZTS{gK=z|+FxNbn%mW&Q2{V) zj))no!6YSE50*3T^lMBMmgX6clbqoWTDHU$OQ=o;RYm3P%g%%vaKL!Wn~j~((KUpJ zQjCe<9o};@{zIWRTQ`2j-{&LyGgi->5t(xE!n_M~;bbd+#+axKUum-Am3$|L&`G=1kOLL+h_& z*{%EXDHfCY?F%6SNd3daAL4MMHMyK__kd;)8D0!5`^a_Vf2&UYjh26ZdllC+`klM8loHsaKZsc@sh`N|I^G zGT_QiJvW0fZL=X74O3i;sbK5?Zst zVR57*p`uHUgM)r`P~EksZ!TlnuA^F;`d7zgn3k*^u)~Q_cvfKoA+4X3nia?7La1AP z`_q8I;n?hWaU2q6Nvw0G%~hujkGqcLg|S*@4CJF0oqu+-h&ko%9*QLZ#Z1RS-*njE z`;SyDHmz@6XImuX?J<)gh#nDemA*LBe!mPUHu$JGy>O*F(;iih!E{OE;}Gt$*Z(Up zaAg*G^;h=4tA~szH~BkR*HLW4V7wyd)3&1#m)go*X}PvP24pRAz)Z-sqsbD^ru>Zn z!Ef!TAeiNhSNFY?{nLWO+0j&DK>~Z@w69+Y_WWDRev}=s#i*DzISuY@`kwmVk;)}A zk>j_zbr{|JF~xfT3XUOe{yB@^QJ6%EtqtjQKeWW{q5&-jhhB8@gpfACN(y6Oj)mHn zD{-^Qh$EKyyN8t{SmBz@SlZZ}0Be9bMrTn-Q?6YW<*?sxteKbdo@sZBJ|zVVJMdRZ zf%lf!nZrgb`FNA&n{H=6Y8>L#s{M?2A>>NDhmqiS&BK$9l|r1A$A46^qSaBi6|f+~ zW$wa-64Kuei?91{amy7c8nEYLZQ&T`>m zJ!bk6obQ9bIw42HA}Ys0`x?;b0QgfCl2`+#;Y2Qc54u}%FVLNF4B2-mARvyL-ReWK zrE}4bNWkBs#g9n|H4dc(&GgzoxEjA{d%ec6A@* zU*yP9B!4e;FtkIhm(Ewko=20b6zu)$fpSm$`}zsL1LR8l8`c2r=g0qohD~$#&gYHL zrt6`y(0z;9It!ce!*2LC{@mEbrcNNApIoq#UQab%g?G`=@d*MY8BeVEfZuGmWwaE5 z39KaKZI%MDL0G}`{RFbZ#|0EyKbRvF>TkTSW3n6%Io6c#+WgfE5y#Bp2!gAKdMbLM zWkDHEwDT+6DOI!&`Q}s*^)docVL(v1EWoVS?FA^u%~9=_p2}(3cG37Io}E%!(B!mC za&tO8j<%<6*ZPZTXXectJD>M&yci@no!df{48s#uTK+ho$NK^rOOewE>W0v2Mam zZR!$58bLvhZ~Cr^`(I%-`?(TcFE+O?VZ6~3_!vg2St(~^>4d!UV$#kLRglznhzHwk z=L2(~)0L~Mx-cW|dy%vcund0_#j!S0LdUW-q%Bp@&tSxKPuE(kv$|ji9tbnrOop;3Ud-%`ZRA$#seA%RRLRy!cR6 z=s$DUn4){HgVb)!%&Xg$t{@4a-td4idB9|~2Mv#c&S*o|Z7KDwp~V(;X-7lhF8eo| zv4=KJtma%0y)|5PH8$fcDy(?U4 zG9nvS@!j&G}c5XGB3?vj6oE5N5Fg`lO&`HA@73R!g`d=VJGmZ^mcuTRT*` zY%!N5`R!Si@jL8Tg0Ch_Et-#c#*S3*RPK!0Ak&WWKYf{jK8k}s$i=k@&HH{t!XXoR z8pVpLnAe+SE#0?ze|dTC3U8^J4?Y!RqYtqz05GvhsOK99`VppN+bl)7@%u(-gC<0Q zEHK34x}AEeJ-0G_cJ}pk$$`sL@~D`>rmJ|hyj^DT1fNS_K#@!=9r6=5wIGEj`M1#* z__X}(pO1xztiwMS>)>rE13O`kGP5eg!%KDB#ITN9XJkH_YN zU)m2CNVGO3d9=qZRylvM1QdCNYtBvhwQ9FcE-!oX?8MCMWh&>4Z2OLU=3aeIN61iN+EGR4V`=elzxliMLm@*g@<_SWB`TYd@TyUY@Il7#ltc>q& z+!tc{lsaH6{%W|I`durZ(p^&nXB2qetcgFMyXt;oFSPQ7c%28vC5pjFitA1H`(1YO zhOERH{tD~M^V)R{GnWUZ*+U~tO%9_w63xfX2F+5xaZ%4J9Z;(t zQH-or-a~K##X9DVmclTGr3r6jgQqhORz&g;)!YK~KCt4dV892_XOnjdOICxOwty%N zN4?W=3}J;B!cLB1@ONnM@I6g=?`i#$w>M}md%%Cir5Y)>jLIT8syf0(lRjVFC_*sv zkIptf7w#_o%OS^0Zzs`)pSZn_h`?mJkFg8?4TO7Q`saMV{CCLzNl!>35x`NrVr)sZ zV$2%&-ZH|y7)vw^E1&H;>Xx(X!AgN{J*INE+@hA>U%n-OC)vYXGj$l=M|q3c-DnG4 zg&Cj3R9^vg-GVS>M(1bkk^E~nXt)+JS_Wz{i~7+RBH*;ii!-_yB^{9LqAke9x{9*& zn_cSOZah}9)#+~{AqJ4N`hmL}#kD@;at=zDH-5Gb@mGRe z^vFy7Qpn`xS&1vpXT2RzXTsM9J(`noG4cfO&9!d)xqnP(9tZwfUQ4*;alPleB9^$$ z%U}!mT>$y`XJ3QbqH$<&aQ72R`5c?O(8z(y?0J%!#J4egx_PuVGyx0J{a+q98k3-b z&xB(OVWCN@(#I0kmvEXu2x3N@x?(rvH0%amQ36hacwL$t)vj2h9wOD(6OR0%9UrlX zU0oh0W>~FkKJrn?w{$32RLWGhEa%(>2TbtqvH%D>f}LzgKktS10Rax4myMNZgQ1(o zlV`zYm9!CHhe#(~Sw+nThD&kLQ-zLB!^yCzUj=6#bc!dJv$qci8ey4c51BTA&w5fh zxv=Q{&(8ai*Y57J($*lx_K~kJO^{Mc{c>&d5chdAzU zuM!D$^@tpD5rs{R&RH(H5~gSyY24*|5*&aNHv^w2j$7USg;cyNYXSXrtIl7MPEmb| zxw!v2QeHN6)IlS=oyGp`iA*5~p`+^-6pU@s2HxMuvk_P#5kk|*;NUC~-^pi-B6%bdx=O{0E7Su} zMPkPfc9LApw6d0c_}wm@#+EObGmWo%7OE_u_Fr`;YQhCUJhmKwhJtNXX`w97RVYs zw2bD3=dGn&?fQeJXe1svr?Pg_$iys$u9DsnAW4KhI)qB?--YbjjMe+#o?XI@gM-?A zG+6go5^Zxjwi{hXhO?>;rOpi|SFc#0GcS_An*mgQ`=t_dqZ@3o8mZ3f^Eo=E(ZD#2?YvmX% z;5K!3Ge@5d&Oh5$^(jVRzLl<-fwfxn??&D_AI8KM&yihXvtm71EDeXFFoySt?Kg)S zovx4+!^lBUPSEXfI3ij7s^jf(R!2Y65vw)G5wZsq`(nrYh2_PZc~DMFNpN2gR@XbA zRgX8lcnq8ekF8|k0QVf}`-}47yEhkX`6pAX9YJ=3d^xLdd!yesljkq7tqkHc=B7d| zbe}hWtK7G5t4!OlZ~0a^P`;d~E0btp>D)vruwi)p@EAEHxd7tccZ+_@B7sV9h|W=B z^`#RuMFzN4g)tVK@AVM$%tg9>?q0t4-x)SQK@a6lp-UniK9}iCSsg}XSMfE~^|Qkf z#4k*8)3(GQFQ57{PycG@YJ5qVU!d!JVloeS_h`G2=F9je(Y58D^iv2-MX}C9Yrm|i zoU@edW95OjRrQ=WhRM0@H75==DV1~lgXLyguT2{m>#QZX>S~vu<2Q?u*xYW^f%hJ8 zG3cL*&Qe}ymL)!gpS<39c+L1bEEq)9w$K(#xH!9|_GMRDvLZkx#{Z{}M*Jl?w>no! z$9NxnWF&W_z*SzJe%R|#c;`q~?w%G;0WPi$iDH;dlx1W^KAOKO#2xjC2>lJx5&w7~ zvMu(>xyLOSQ#lg))J~h1kQyd-QiQ>@=aOZ#&=Tw&f*IDaJ9!(i$NhcAxjQrmy*URH znY1A6i;Ypmb688|3N^e7{Vec%NmV#?^M74g^dooyVHvyn z!a`A9ejbw9t9QA*>H+Fqy;Zs@>-O6o~z(!VCQ$6%7@Lrq%{cR|J{+Yfp zO)Pz9`|asMp2E!r>@)LE4?eyACri)#8Lvsh|muVaCDg^tH4t>5R5Oy z<}PdJ&Ai_zSBA9i8##R7-4^R7moW61Qlm4>mbqxdL&!9r5Go;Qsb)=)v2mTNg_qz3uwH%1Upf z8yg4oR`jeb^OV(#fa=c8gTc<9=2_Q%T!Cq?&6av()2gpjb=?jy&QYf}*|cw(4NZeI z2_@eM!-LS8xL>CdFf9=YD(c${gd)r)8!m2~;-9_h5APxgu9|!K-eN!Dui$eCu8@3z z)lphin` z9QRhrQjt;ul#g{tzZJx&bvZL}^Y@;FpD-F?`O)k(nS0-A{rg0Ez}1KfkoyP!;2Fg9ai>I zu!sH+boZhz(Iu8^jA3oHlxg5mm_h{v!MtHFNiX6~y@<{jLt_gDA(~tfw|y6#HN3?< zm}VgzH@RBEK#u#nAdEeK25s8lBV*Zm=SbRaEqq^o}Y%_ z+#fidIHo;#ECD@3<!DdtxIbu)#whmRyaz_ho+52-Z`7fb=Feg3 zq2vJajXzYYyULv5bJn}Te*?uu`FdSQZduzaLkt@g7pmXA?|5ZT0sUd>l}E2#nQBVS zu1h}`p<#=cS@Yf&kAZSNBDC)X1ND35%11FVFe*|a z{*HU*qC`=-A{>fvlB{?bk}N<2vlY-7ONP0^cbFYER?&=v(L-qufwwmz=GmAL%Sa6T z!}}N)9O+q@`w=zHz;BC+x&-%@1O-0@e*SzetURes`7{UGe%l-3cj+TwN_hZ zZe$*QXGA>`63Rc==GP(Q9L?*^@Q?B=!h=m?0<`$cC(Ss%_|BJIK1D-KIA@3KVxC5} zuaBM%>TA$F`-onAMki$9)JR)G<9)D&RQ&b+Eg6vj9$D(k0 zi?@=YXj-NQH2X+b9?>1Iv(&#>)Y+kOW1`j))=Tag8s6MO#DbHn13~movo;I5;S!lD zQF8n!)Y-TNKmt3IG!t8Me_9Ukf0tLch?_A(ZJjwD)k_ig9C~so_D;_!;Ix0P--i$d zQq#47zwRCS8|nPhmgXX1s6l6m>(*DGM9>Lkwjq+>02azO!`Q!@zfC&2Vg(4T2VReEMBGc6|5-V9 zmDUmI75vxkz5e<$HvgsoOemQj7!}gy77goe9uBvaw6`XYfA-EG+TIM!tM>Z1V*Z$p ztn|>Ob2v#$DT6fe*(J)UNI`Y76#%beeq#s_#KFMIGn?n!$LK`fV^lEip9<2b+G)Xv zs+>_SMT;`c@8ihVCdd-j_~;%iv)zR$1GBz4 zcW}wj+;+w8)mPU?aePQl)XxaKGvmrr_KD^#o_qRFzKmj{2$~avEs>1~M|Ys2af6z3 z0)J0aF}eu?{w-=qbJr{A*{qT-9(3vbNNR4rzjK7W-r=)Yc+7L?Z|fpP=UP9G;`AT7 z|1PpPo#fZ61~(D_t+w>riWp>dJ{*sp>%3`KJ7#&>3#41JGR;#yJsu> zUM}=^qmqmV7G|Xb=HGySGWT!mGtj28Jie}H`P-{|WYP0!!JmE6tL#tnc^~rC?3~J9 zp6ljydQ5$+q7|hfx;dO@3aVTKmj*{a-Il8}a|n^2XuwbFU$+f$rD?lIi7}1Tm#|*V3`Vskl%sZ8MwT3s|DI95@o-sg^{QxVxmVbk zD&u3S7>W8(-4y|`^HTIMnn)%x)-N&)_WuBI`14MKf<>(dKoL=B@Mi&wg||*sK}K&i zW!pAxR^8(S&+d>_l5nh5oMff2;6r-#h*hmWN&g3rcjdesw;GppuAkXN`LVFYjn6Vy zUOk=!FbG%35{0=E{5!DQD02QgvQ$5={7;Ss!dy_JZ|E4Gg4XdlftKEoHc0)_|F?jf z%CxXa2F&IYR)2*@`ekwcfX54k1tkiD#hEbdy$D!&dHJ4JeQZH8(eQt|N)%+F^nfr| zUk2d=Y$ihN0z5r?dwK9HHp;`W7trieYd=5_jmxbH+mtaW@wEQA(^>j!BP9DcIrT#} zX-HxYErrEbM_>ePMR^zTcQe+l!%?IFfV|Eufo)0L20+lYCWTdB4NXF(Oz2iuQKGLj zS_T6%HdJ&U52uO@Q{j3UcL&D&NOV4lL z^ZsYl9W1(S3sZhKmD|5!BOqt|-`Rd7&~*dGGK0uB-+8w<|329|qN~jINi+{_mmW_K zwlEd}Vb~Ca#r=W!ozxE(p`$Eu>Fi}J{1nGgLPy4uWP{IzVEj?6>+Zr}@-Sr06TA>M zrrfLULt0nP;`U7Ea(_{5MX8le6*p0<<8^uOOL+ouLK?62&Pcjv@t_Ix#fr z&%1Y>qPn`qC7jr<5-Xi8Hr3=5k%vbI4Fi+a&#cBNgG6m_tvgDIGvY#ih>fgLvuVk} zUp+Ruw8X1`{?{)q|H7sf)xkJ1#n3nPiK=A_=3eo5Vhe45K0{%8(a`D8K{5V zhna-WTz71DBO=9RH?nD*G1h;fzXoCl0)Yv#uLinn7e4abPL@WTA;is-Mq`-fR48g^ z^P28mMg&9t8=$wcs*)}d)X5>%5(Ti}BMSi!){o-|ySl^vNz4@wJuE}0;90QC0k*<| zB&}Z2*+95D-`#=P4iTSh0OKCZaQA<0a^^<3eHafifuB9U(@ZPsd(_3glZ#zY!nD>@NHjVu zTU6XpW+gNywBfU>3CP1iiUIuX10}+Q_XgA$!d!h`VFf;N(1vq(6u61{wzq6@*=Wa) ziDBtn`rnq(saB6^2yfs5l6dPEbbDkO^a-jXFLFd*P~slQmeW1N9q7A1E8m&=DwKT2 zVv@Pjp`JNpKeCFB;TaUBj)=k%0pPA3Uk3y71S@J0xj}|PuipH5^I-!3hI%irvoEP(qjMw05AFm@lZ`=bUpmHiUcV;S^{+LGe#I`>;bmFTSp9Q5!ji(K)i7 z{g>#wA*Iav^(m<^-f7oWm1BbP=t^gT`*8y47oAP4)G_tHoU^!G0VLra!yAetNW}iY=Of<}JW?-t>rp|Ucq!`IbO>}$@Dc}m%EFnm)Rc2=M88fQ1f z5Idgxc;Ey3S_aU6Vm5jqLIl_hf8$-6{f*t*$!#JDnZ53>snB)sarvc&kU9aN)W{;} zbcuTkJ%8%}?r1V#hV766`T=*i!*8&vv9GHEokVaMzzpCJ8<})yNZ*li(Yojn@#z?Q z4tq?^Z;}PLrlH{;i>xUGWJf#}dY}ZbsuRAwd*oIeT#4RtR7lYN^}XD|+vF-nJf#aV z)8HvpWP<%0F<3=qI`z^{n5HS2Z{yJB#hxhikY_iyKEQdp_I3agaJ1@;?wuBz{qG>) zd)_9_+~=?D=xIWX?yN{lw0 zb?qF`{O6{E%=d4&Cc)c?`4`*3^s*p5Ksv)#)|14CE{?o?bljHS)PLzA=YqjfU3%dW zvY_ipuTSAmt`^3;KZ;09UQMhs6W&74kUs}Z0R%D+&PejkdsTFWPp2j8mXC--AYc}7 zhYx^|!ok?|s#HJONM4Wt)`CN=M305Ae953jfK;nuxUqGF%qU0Oq6tuuS?!SV>Xfuo z7VUW@v2xb(r*^-xL}k$SKmlgzDV7vsy{n*T0^8#$i{4$SS8A1fUF%Ao(yaNglJ9);s~NkYvFb+v`P zkNGd?4 zmmzF2jBJ^WzKyk;N4NnGPBPW}-Vz+SuU^82CFgOF5NmIjM-fTv7_!Jd0D@_t)!jOO zGavgzsS$wv_r9;}2;JSh`Oe43FgrRj+7zjf9j@TH@?gD#=61Xcyn9i7beTAb?{v#b zDmlvQF-xwIUt?)h79$a1w!$Jp4|;uwhVem$8w_;UgmDJQH3on=!C5w^kD;A8P; z05GG2SBGKaR7b*^Nxa-5s)$>`D5HABSBHnf;pY#m_mmCQtIO^8k{_&y{fmEv1u#*n zzqB}Td+traULxQ(gv$=3C@5_6bwoe4T=Zi$SwvV#%;AK-D|5?~UYc%dbs~?U)W<;v z15B(x197eGFiw6++W~MF1W*X4bX-~`Zx=?HqSNwjoj&;OzcTLUSoM42Z_>=$`T145 zoWdRA1(AEC{8xr%?Mo5{B8`5ckL2?HQ&tG@*na2>htyTevA)G4ALOr`*^`$jyaoSN z|EKx|L^&DKDi-Iyzv^Eyf#a!laUA5L6++Eg^eNOZp1-T(2Ob=Oef>VY^5N_D{7mFZ zn&1PC-13{M4`j37H52-A2EHKk?*Z%GfdwV)yGo(ZHf!`pPuP)q=2UZM4u7K92x40# z{Y4ium@e(AYP}&x!nM9WI{w%JL0qOEIr1{+$?M@JX{Vnz1z%!?0Fq?zRh-?pHnA={ z%niF%UlRf#A%jU@(|E(w*j50Pg?Mte4!{3ESMa#O{0ha}b zd{KJ@SX6onIhBqkgN&3Kivn!#grB3{`r2MSYi~q7b@rMa+vt2uW#% zN#lOh`t^GxxcGGJwm%8sOv$TCs2q^-qV8r>*aW@Wz7%u`fa^eh@!%wdB>)bVWiWc0 zbv<%yzjVADIx0V~V)KNXtIJOi5Z1MK%PTG7#ncqQ_zrdC23{>J#4ihKyOQ{;;k zpdl6EWRcq<;ov+{Yoa0L>WSNmKcnV7Z%LRwmhS90!&{jPBF?&hhFi%o$yNgPruhj^ z0zBd)mRyxikiV#%?+7Pkr812e1UAba#}g#uGj|Xw(GQ>icQWZ0m)zf|8_dui{0cO8 z-|Jb+o_DkorQ4q97|zsb-(q*azOPRsVrdTp1-`^LWA{a}E6$5n1Umo~Fj$3ivlf-! zGe~a~-gEyfq|_In!h@_R3Xsmh@+zv3p>JxpyPq+@W&MB=)c?kjd6+tj?OGL($Lhl! zF{t8=L!u=ld2x6Prt3iE!D4=Y&UP`Qdj^~li7v$J@8dExLDOgnEkhL?H|*+DRjZZE9Unwh*7cc z@Vj~vOY_5Ge#J;GN`@;e-#mh}Uhp-xEhg_ywUda^)JXl~M=$3?Kl_qGHWo5UIG{$4 zDzGtl2|eh+O8PJ{Pi}%SuX1^x6dr|ad@pHV&3*?kYRwisvOj3{A|5S+XUzCHKXyD= zoGt9>WQN4~EJ&P;Jm?;tUs>r*dn^tpI8+D=-BK`f+8<6ysFB%rL&9AUfmxu{VCJ_S z&ocABK>0!t;hZ=`TpSqD(84Su0&TFkw2CQT`+7aS?pa5LL;N2K_xJX;h@yhaIgX{Q z1Fn3pZ_$c2vNVwgV)p-ijDoa#*LAThXYp=qwqVh}y=OLeT7|~l8y^BuV^$O;am=&n z1D3W;0u3N2)Tx#^v4@U6_Lo&w^`XU@gwM+6+Z^M4V8@S}SaKo@fC34eyls;rRPeGlBo^a{1VLoI){uR`08@zuQaK7noI? z(}QNGQHEDC_?n=db}4`7W53op|4a!~mVXK42sGc;h4@|V*Y;2~QOWvWcs^b-$^WYn zA5BQi#&HiNJau+#bhr|iRpEvTeAuJCKfb-^A1O;@s^X!w{4H5OjqLer)@8&}vI#d| zVWsfSY{{Xm;SC`E`pvSqa?Vnv;%;ri#W7x0W3_FA2cz6F&fEFBJ=t)(VfpW1_*0He zo7hNB*>6i-@lPmcb*Cq-c%EiE3yh=UA*(X4Wvcv@^s2p0!ubPC?wY)XCS{JC+E?Bh zy}f^S9_CzB5+Dr^nHSj@u#?mmEfaZD4`r%w6;yQxhCJU+xmhH;e5L1;a4VxNto@Ey zxeVhSVxxIwP0t=$iurEsyk0Aa2fc)}yC$IzyTtYl585S6GA`*Ap|QUHtHLh9`v1Y% zG=oRpiyq|RFMCkfZiLv6d$#8uTVtp&xvaA7XbY7`NljkkS#h08C1^dyYVlSo9@BE? zi89yZ=_?QDrPiZd!TBxTTv`;+2RaQel^`qrSm?)u5`p1jXp{0i}9^HI}< zWzFmXo&_$`3)ZLnJQS4FG?X-7x~L3)>SVARY9$#yolg3p7f;E63pu-Vx$JB_`7Rpl z$Q^v4v$pb2s`)9G5VX$TKO{D z%lc*=2cMTDhI!c(?D)J4{?_+}N~_T4fc#82sg6NaiImw%OrM%nlOMaElkzhQDIPlD zO!=ymY>hLha-KfMATG^?CpMZ_z22EH-k@_X=Qne=F=ghCJa35AGY*wWm(9Z_{~X=XHlk>CH!&ZRysf-IB{>RWKsb{Z{_{U-nAO!(WYqZ*xay#uz`jPb)@ z$$-icPb`5Vk&79X;GU+0y9}VENs+5FV3-$dcurv%dvlESqz3Je;Fo zgBLyOv{+((QeXf#&LmROa3m#Q=C$jxr&UFWsQ<2enW>+^SxrsKqaKyHsevShMLn7r zjJU=e#eDx?^HIA&3WU5LBseWexD8kgA{eizENbvs^pvYUeN2X0;a@qzdOyW&x&$eZ zP0$>OUM&L%7;YS#Z zibXVum^jR}{;W;~8cuCA>+DVhDLBdE;f=ZTrYmCnN)?l=t6mqx;53{|Jg6y` z4`Mo{>u*tq)K-u(CJxm>Orv-BuPr zP^Q?5N2vy#w`n-O zT<78R2!))~8L`&LvP$m#AGDvbGD@zdJbfXrsJGk@@8s7JWQIEqi(h76PEVVO8SlC3 zUB7gbX}wBfY#Tljl-Z_zXIp|VgK)vnpFpVpim)Whf^KKbXgIVQEY*aj8WHwR+&l6) z*%5-gf>q01_I!P3IG?ymXl%_)*Fw)j2%Db!19OzIde;CL&68z=m*{sKl(werCSz|P zvvK}Tm5a{|j?1@pESp+Fjhh}$Z|~%Bx#O@>Z#0h9Ey2ZaV=6uH8tfwxe>5XuO3HUe zv$~{=$=;8BowdF6#FOX`@KyP8Je$GJnN>#U@C|4AP(pM1)^0ZFGTkg((LAl#9z}jc z6^jTxi^*0EbJBsXSddLU5g$U)Bd$MbIJrX2hBUrnH3XvA@2}p_Sbd;6 zCwfl4y{uB+sxNqLen1?}#S2pk?ak+fk)m~E!Fc&iUJ@sOW-z4iQA%K)GChwM{uLAc z;;ksUD*)GB&=L-Ek&>U)&fRmJ0k}K#&HwbM3b1ImPj*qrDIOEYJ+>jE3=Ei?39(qp znW&A#1cG}7e_j~Z4mSrOEn(zvz-o~@CuBB8Eu8dvabtX zm&rB7q(-F{z1zBf)E%GJwW=ywLZ+(WU%j$TOW-WnsJ%_EbY9-@Q}hlQG6}6otOPRk zW;JR6`6wxgn4H*LixHreqBf^0;~Lwkz;XpbH=4LgjwJt>=1fkA!kN}tLLu$CO{}2T zrcSIbB1HI$8J?%gW4^4g2U@m> z8kP0fcQ zEe6;K$y?NHSYZez*srW4P%r#r{wjwxIXYFwyp+I;3_3o@PNJKlV4m1mv#?_!akyV| zE?Hj>rSkB}Z$Q%CB1$RNT&k<SA5UBJ5K5bUvEk9m{}=+vXFoj+HNEXQiTQh(vbM4~@=kx@Uc0jpH`t>t(}R5&+@hk)|<)?XwmAqNQIWH^vrEa){DgABtG zuif9vAEkC+p0x|x^X$ZHJ}h2b1DCt{iO%u!YHVc8M0emPNI>q2h6mR{-;6nQe5x1( zuSi6b1M&NQ@8Lnn>yOU0gI4z-%1H56udXZm&YxTev6Wy>{?}~*y}bcHEn_xrZS1L= z`c7g-mu?5M{x2&y4AmX%V?kaf)8^lhGyc zb;~L~lLFz234bBKD*eVRe;umIFx){;c44xuQlq!nYc3!lEY7lPyFsXxpS)c)=j+I* z;vuInyD89pFo?}@)?zfT*HSi|(>kwMm&x|e2#C)VWZ3dnRb}T3+9^~=gK9bqR<&5K z$#5J;>)JZ3hO;wc_5(y9?{e*_M0y!fh3^W))MPzZ`mJIAz`aX5R$~ ze5IRh`}|O0Vx8aE`0x{NrDkuH&S5Hp7B5ek#>A4e1--nKaO^Neo@>+-&XK-8^Rbdi z1?=yc+uhxtaS_;uA{Ow_mA9$6xmBoA346Za=9ykEa_fc7RSn%G~G}Krg%3KD{J;HT*m=eJhjj+rotaH;%=w`lHeD&syy00O{-t zv+n)@2lo(2M8p+umm~yb3cmvnA;p89R{?Bw6_{Hl@^cE+pGVGlxo(=-sERQDsO9qL z9L}&qr6e>|wr9F@Lj_d&XFSa{cL3l2lC($&`k>5=mb_> zTK&hATXkWnmOF5nI5`9#I=2Hkp(A{KL2THXB8{}Q@5SeKFMkmy%IKfoCNpOFU$@eu z+62wR2B#uuD`^ck&=P0rg6#%q0JRf*ua&TjK@^pr`wz;CJx%3fwt=rFZq%Q&RW|7{ zm(SZ==G1_$#h!bZ+l*qc{Q%2y()Na!tHqXWlEciA9^ac>1yCBzzOUB1%s)|w!(mQx zrub<Fo&HPI?=p)pUZ?c#xI&3a77tlV*lG&eSONQW8ObT}j|C(l0`rC<-qd z_hQ#CXX+Sj$H*DEqr=I>#cqq+sjvQ1?%MHn=&fi0j;a6$L=eYFC*|{~#hS-N3S>vO z!Dk_2zAs49w$4c7uNL*tnQ_K`!V5DlxKtgKxw=hr(eu&$@g;4*l(l%})MUvA4@vBl zrct{zs9gL=sBj*qvHXVA}j!VMbbWjLh*F(zGUT8$LON_qSJ;R{vg{~!x(;<>w2_PAeQ`jB=?{=jF&A|LP zu!#k;&K==~U}KGn4v`K7kb%22Pp&6bh7`a!iBAbwy4vgjMXGr* zAPpQ6Hf`yb@^(UzboUn6ETYG&1x^YE`CXmNXl=ribRa9J?;gW84QKPFCB#|enYM9Y zblf*<1@yBNtBG;IPr|P$*0s8i1#{(f%NHlh z&gY(~K)bz|cHud(k@GWZ9eQK}-T%=Mvr)sH)$9xf<((Ck04;(O7@Dp_nBASWl`}?J zNr0u|nu}~-m0T`6pLxg!tlsB1Jr6_fuf8oNyX@``Iy2;FhV&Q)koh~e}K8{P4C4!EC|C!y*k5a%dRArnh_7$b(`3>CtX=a7o~+Rwe)GcsK(90A6=BLw75r zyS1#Pt2KB6MB$>hMQ+2v;}Kj^RzgM=E-eIy%fjI+^504RpMZmtl^x3a-wV7pH>m>! v*#3;5?}T#qM7ml7%2rMm)-VkRq>Z(nHPXu4rPo>xd#B2C6D8 #222222 #292929 - #8176c2 #67b1d4 diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 0b0b345c35..752d79cce4 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -45,8 +45,6 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final long AURORA_TESTNET_ID = 1313161555; public static final long MILKOMEDA_C1_ID = 2001; public static final long MILKOMEDA_C1_TEST_ID = 200101; - public static final long PHI_MAIN_ID = 4181; - public static final long PHI_V2_MAIN_ID = 144; public static final long SEPOLIA_TESTNET_ID = 11155111; public static final long OPTIMISM_GOERLI_TEST_ID = 420; public static final long ARBITRUM_GOERLI_TEST_ID = 421613; @@ -87,8 +85,6 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final String AURORA_TESTNET_RPC_URL = "https://testnet.aurora.dev"; public static final String MILKOMEDA_C1_RPC = "https://rpc-mainnet-cardano-evm.c1.milkomeda.com"; public static final String MILKOMEDA_C1_TEST_RPC = "https://rpc-devnet-cardano-evm.c1.milkomeda.com"; - public static final String PHI_MAIN_RPC_URL = "https://rpc1.phi.network"; - public static final String PHI_NETWORK_V2_RPC = "https://connect.phi.network"; public static final String SEPOLIA_TESTNET_RPC_URL = "https://rpc.sepolia.org"; public static final String OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL = "https://goerli.optimism.io"; public static final String ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL = "https://goerli-rollup.arbitrum.io/rpc"; @@ -172,10 +168,6 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit MILKOMEDA_C1_ID, false)); put(MILKOMEDA_C1_TEST_ID, new NetworkInfo("Milkomeda Cardano (Test)","milktADA", MILKOMEDA_C1_TEST_RPC, "https://explorer-devnet-cardano-evm.c1.milkomeda.com/tx/", MILKOMEDA_C1_TEST_ID, false)); - put(PHI_MAIN_ID, new NetworkInfo("PHI", "\u03d5", PHI_MAIN_RPC_URL, "https://explorer.phi.network/tx/", - PHI_MAIN_ID, false)); - put(PHI_V2_MAIN_ID, new NetworkInfo("PHI v2", "\u03d5", PHI_NETWORK_V2_RPC, "https://phiscan.com/tx/", - PHI_V2_MAIN_ID, false)); put(SEPOLIA_TESTNET_ID, new NetworkInfo("Sepolia (Test)", "ETH", SEPOLIA_TESTNET_RPC_URL, "https://sepolia.etherscan.io/tx/", SEPOLIA_TESTNET_ID, false)); put(OPTIMISM_GOERLI_TEST_ID, new NetworkInfo("Optimism Goerli (Test)", "ETH", OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL, "https://blockscout.com/optimism/goerli/tx/", @@ -225,4 +217,4 @@ public static String getChainSymbol(long chainId) return networkMap.get(MAINNET_ID).symbol; } } -} \ No newline at end of file +} From 2d815f4bf74ac8d944ad747c64141195c9340c9a Mon Sep 17 00:00:00 2001 From: Seaborn Lee Date: Thu, 17 Nov 2022 22:50:47 +0800 Subject: [PATCH 149/183] Install Ganache (#2953) --- .github/workflows/e2e.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 2807ef8dad..71e044a55f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -25,6 +25,12 @@ jobs: java-version: 11 architecture: arm64 + - uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + - run: npm install ganache --global + - name: Run tests uses: reactivecircus/android-emulator-runner@v2 with: From cec552742fc671a1a2d2895609f15a07eaacba67 Mon Sep 17 00:00:00 2001 From: Seaborn Date: Sat, 19 Nov 2022 07:03:43 +0800 Subject: [PATCH 150/183] Fix most of the crashes (#2956) * Fix NPEs --- .../walletconnect/WalletConnectSessionItem.java | 17 ++++++++++------- .../alphawallet/app/ui/DappBrowserFragment.java | 2 +- .../app/ui/QRScanning/QRScannerActivity.java | 4 ++++ .../com/alphawallet/app/ui/SwapActivity.java | 8 +++++++- .../app/ui/WalletActionsActivity.java | 5 ++++- .../app/ui/WalletConnectSessionActivity.java | 2 +- .../adapter/SingleSelectNetworkAdapter.java | 2 +- .../com/alphawallet/app/widget/GasWidget.java | 8 +++++++- 8 files changed, 35 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectSessionItem.java b/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectSessionItem.java index b5df80e809..a3c65ee7a6 100644 --- a/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectSessionItem.java +++ b/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectSessionItem.java @@ -7,20 +7,23 @@ */ public class WalletConnectSessionItem { - public final String name; - public final String url; - public final String icon; + public String name = ""; + public String url = ""; + public String icon = ""; public final String sessionId; public final String localSessionId; public final long chainId; public WalletConnectSessionItem(RealmWCSession s) { - name = s.getRemotePeerData().getName(); - url = s.getRemotePeerData().getUrl(); - icon = s.getRemotePeerData().getIcons().size() > 0 ? s.getRemotePeerData().getIcons().get(0) : null; + if (s.getRemotePeerData() != null) + { + name = s.getRemotePeerData().getName(); + url = s.getRemotePeerData().getUrl(); + icon = s.getRemotePeerData().getIcons().size() > 0 ? s.getRemotePeerData().getIcons().get(0) : null; + } sessionId = s.getSession().getTopic(); localSessionId = s.getSessionId(); chainId = s.getChainId() == 0 ? 1 : s.getChainId(); //older sessions without chainId set must be mainnet } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index 11d39fba4c..b06fb5a885 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -601,7 +601,7 @@ public void comeIntoFocus() { if (viewModel != null) { - if (viewModel.getActiveNetwork() == null || activeNetwork.chainId != viewModel.getActiveNetwork().chainId) + if (viewModel.getActiveNetwork() == null || activeNetwork == null || activeNetwork.chainId != viewModel.getActiveNetwork().chainId) { viewModel.checkForNetworkChanges(); } diff --git a/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java b/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java index 30edb20fd3..3759d80781 100644 --- a/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java @@ -404,6 +404,10 @@ public void onBackPressed() @Override public boolean onKeyDown(int keyCode, KeyEvent event) { + if (barcodeView == null) + { + return false; + } return barcodeView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); } diff --git a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java index cb5d4bb3e3..91775526af 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SwapActivity.java @@ -261,7 +261,13 @@ public void onSelectionChanged(Token token) @Override public void onMaxClicked() { - String max = viewModel.getBalance(sourceSelector.getToken()); + Token token = sourceSelector.getToken(); + if (token == null) + { + return; + } + + String max = viewModel.getBalance(token); if (!max.isEmpty()) { sourceSelector.setAmount(max); diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletActionsActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletActionsActivity.java index 17fa5680a5..c337f854f4 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletActionsActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletActionsActivity.java @@ -286,7 +286,10 @@ private void confirmDelete(Wallet wallet) { result -> { if (result.getResultCode() == RESULT_OK) { - successOverlay.setVisibility(View.VISIBLE); + if (successOverlay != null) + { + successOverlay.setVisibility(View.VISIBLE); + } handler.postDelayed(this, 1000); backupSuccessful(); finish(); diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java index 021229dad5..1bf38a4b49 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java @@ -77,7 +77,7 @@ public void onReceive(Context context, Intent intent) public WalletConnectSessionActivity() { - broadcastManager = LocalBroadcastManager.getInstance(this); + broadcastManager = LocalBroadcastManager.getInstance(getApplicationContext()); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SingleSelectNetworkAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SingleSelectNetworkAdapter.java index 26da36152e..d072f1c255 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SingleSelectNetworkAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/SingleSelectNetworkAdapter.java @@ -96,7 +96,7 @@ public int getItemCount() public void selectDefault() { - if (!hasSelection) + if (!hasSelection && !networkList.isEmpty()) { networkList.get(0).setSelected(true); notifyItemChanged(0); diff --git a/app/src/main/java/com/alphawallet/app/widget/GasWidget.java b/app/src/main/java/com/alphawallet/app/widget/GasWidget.java index 90ef428494..e79b665ed0 100644 --- a/app/src/main/java/com/alphawallet/app/widget/GasWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/GasWidget.java @@ -39,6 +39,7 @@ import io.realm.Realm; import io.realm.RealmQuery; +import timber.log.Timber; /** * Created by JB on 19/11/2020. @@ -319,6 +320,11 @@ public void run() { GasSpeed2 gs = gasSpread.getSelectedGasFee(currentGasSpeedIndex); + if (gs == null || gs.gasPrice == null || gs.gasPrice.maxFeePerGas == null) + { + return; + } + Token baseCurrency = tokensService.getTokenOrBase(token.tokenInfo.chainId, token.getWallet()); BigInteger networkFee = gs.gasPrice.maxFeePerGas.multiply(getUseGasLimit()); String gasAmountInBase = BalanceUtils.getSlidingBaseValue(new BigDecimal(networkFee), baseCurrency.tokenInfo.decimals, GasSettingsActivity.GAS_PRECISION); @@ -350,7 +356,7 @@ public void run() } catch (Exception e) { - // + Timber.w(e); } timeEstimate.setText(displayStr); speedText.setText(gs.speed); From a54db34df9f5d8bc5941204668b3d28a78da8385 Mon Sep 17 00:00:00 2001 From: Seaborn Date: Sat, 19 Nov 2022 15:51:45 +0800 Subject: [PATCH 151/183] 2888 update walletconnect sign v2 sdk (#2946) * Approve wallet connect v2 pair proposal and show sessions * Show settled sessions * Fix sessions list not refreshed after disconnect session * Show session request on any activity * Show personal sign request * Approve session request * Show loading when pairing * Wait connection opened * Show progress bar * Show wallet connect sessions on wallet fragment * Fetch sessions count * Refactor to use WalletConnectInteract * Show WC sessions tips only on tab ALL * Remove WC sessions tips when all sessions ends * Click to goto WC sessions list * Fix token search bar not shown * Handle wallet not exist * Set WalletConnectDelegate in App.java * Refactor, move WalletConnect code into AWWalletConnectClient * Show notification when session connected * Show notification when app start * Show list when more than 1 session, otherwise show session details * Refactor: move settled into WalletConnectSessionItem * Navigate to session list or details rule apply to system notification * Refactor sign personal message * Sign typed data * eth_sendTransaction * eth_signTransaction * Fix eth_signTypedData * eth_sign * Stop service when session disconnected * Stop service, remove notification once all session disconnected * Move project id to BuildConfig * Refactor - use DialogFragment to registerForActivityResult * Adopt dark mode for active session notification card * Catch WalletConnect initialize exception * Increase memory to avoid OOM * Update test runner version * Modify test dependencies version * Upgrade minSdkVersion to 24 required by WalletConnect * Approve session request * refactor: Active sessions tips * Show session details * Adapt SignTypedData format change * Show only active v1 sessions for banner * Start/stop v2 service * Remove test since WC2 not support API 23 * Put WC project id into secret file --- .gitignore | 1 + app/build.gradle | 33 +- app/check/detekt-baseline.xml | 26 +- .../java/com/alphawallet/app/util/Helper.java | 5 + .../alphawallet/app/util/SnapshotUtil.java | 23 +- app/src/main/AndroidManifest.xml | 20 +- app/src/main/cpp/keys.c | 10 + .../main/java/com/alphawallet/app/App.java | 102 ++++- app/src/main/java/com/alphawallet/app/C.java | 3 + .../com/alphawallet/app/di/ToolsModule.java | 50 ++- .../com/alphawallet/app/entity/Wallet.java | 202 +++++----- .../entity/walletconnect/NamespaceParser.java | 72 ++++ .../WalletConnectV2SessionItem.java | 100 +++++ .../app/interact/WalletConnectInteract.java | 131 ++++++ .../app/repository/KeyProvider.java | 14 + .../app/repository/KeyProviderJNIImpl.java | 14 + .../app/repository/TokenRepository.java | 1 - .../app/service/PriceAlertsService.java | 4 +- .../app/service/WalletConnectService.java | 5 + .../app/service/WalletConnectV2Service.java | 68 ++++ .../com/alphawallet/app/ui/BaseActivity.java | 113 ++++-- .../app/ui/DappBrowserFragment.java | 2 + .../com/alphawallet/app/ui/HomeActivity.java | 4 +- .../app/ui/NewSettingsFragment.java | 1 - .../app/ui/QRScanning/QRScannerActivity.java | 24 +- .../com/alphawallet/app/ui/SendActivity.java | 148 ++++--- .../app/ui/TransactionDetailActivity.java | 19 +- .../app/ui/TransferNFTActivity.java | 1 - .../app/ui/WalletConnectActivity.java | 10 +- .../ui/WalletConnectNotificationActivity.java | 52 +++ .../app/ui/WalletConnectSessionActivity.java | 118 +++--- .../app/ui/WalletConnectV2Activity.java | 377 ++++++++++++++++++ .../alphawallet/app/ui/WalletFragment.java | 34 +- .../app/ui/widget/adapter/ChainAdapter.java | 45 +++ .../app/ui/widget/adapter/MethodAdapter.java | 38 ++ .../app/ui/widget/adapter/TokensAdapter.java | 141 ++++--- .../app/ui/widget/adapter/WalletAdapter.java | 133 ++++++ .../app/ui/widget/entity/ChainItem.java | 2 +- .../app/ui/widget/entity/HeaderItem.java | 2 +- .../WalletConnectSessionSortedItem.java | 26 ++ .../holder/WalletConnectSessionHolder.java | 37 ++ .../alphawallet/app/util/LayoutHelper.java | 30 ++ .../java/com/alphawallet/app/util/Utils.java | 14 +- .../app/viewmodel/DappBrowserViewModel.java | 35 +- .../SelectNetworkFilterViewModel.java | 6 +- .../viewmodel/WalletConnectV2ViewModel.java | 65 +++ .../app/viewmodel/WalletConnectViewModel.java | 92 +++-- .../app/viewmodel/WalletViewModel.java | 13 +- .../SignMethodDialogViewModel.java | 128 ++++++ .../walletconnect/AWWalletConnectClient.java | 362 +++++++++++++++++ .../app/walletconnect/SignRequest.java | 27 ++ .../TransactionDialogBuilder.java | 198 +++++++++ .../WalletConnectV2SessionRequestHandler.java | 93 +++++ .../app/walletconnect/entity/BaseRequest.java | 54 +++ .../entity/SignPersonalMessageRequest.java | 25 ++ .../entity/SignTypedDataRequest.java | 23 ++ .../walletconnect/util/WCMethodChecker.java | 29 ++ .../util/WalletConnectHelper.java | 14 + .../app/web3j/StructuredDataEncoder.java | 10 + .../app/widget/ActionSheetDialog.java | 6 +- .../com/alphawallet/app/widget/GasWidget.java | 1 + .../app/widget/SignDataWidget.java | 19 + .../app/widget/SignMethodDialog.java | 188 +++++++++ .../app/widget/SignTransactionDialog.java | 6 +- .../res/drawable/ic_wallet_connect_card.xml | 18 + .../res/layout/activity_wallet_connect_v2.xml | 162 ++++++++ .../res/layout/dialog_action_sheet_sign.xml | 5 + .../main/res/layout/dialog_sign_method.xml | 189 +++++++++ app/src/main/res/layout/item_chain.xml | 27 ++ app/src/main/res/layout/item_method.xml | 14 + app/src/main/res/layout/item_sign_data.xml | 4 +- app/src/main/res/layout/item_wallet.xml | 113 ++++++ .../layout/item_wallet_connect_sessions.xml | 41 ++ app/src/main/res/values-es/strings.xml | 16 +- app/src/main/res/values-fr/strings.xml | 16 +- app/src/main/res/values-land/strings.xml | 8 +- app/src/main/res/values-my/strings.xml | 16 +- app/src/main/res/values-night/colors.xml | 1 + app/src/main/res/values-vi/strings.xml | 16 +- app/src/main/res/values-zh/strings.xml | 16 +- app/src/main/res/values/attrs.xml | 5 +- app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 13 +- app/src/main/res/values/styles.xml | 3 + .../app/di/mock/KeyProviderMockImpl.java | 6 + .../KeyProviderMockNonProductionImpl.java | 6 + .../ui/QRScanning/QRScannerActivityTest.java | 32 -- .../QRScanning/WalletConnectHelperTest.java | 30 ++ .../app/viewmodel/HomeViewModelTest.java | 5 +- .../app/walletconnect/SignRequestTest.java | 33 ++ .../SignPersonalMessageRequestTest.java | 35 ++ .../entity/SignTypedDataRequestTest.java | 32 ++ .../entity/WCWCMethodCheckerTest.java | 30 ++ .../app/web3/Web3ViewClientTest.java | 3 +- .../app/widget/BuyEthOptionsViewTest.java | 5 +- .../shadows/ShadowWalletConnectClient.kt | 26 ++ app/src/test/resources/robolectric.properties | 1 + e2e.sh | 2 +- gradle.properties | 3 +- .../token/entity/EthereumMessage.java | 3 +- .../token/entity/EthereumTypedMessage.java | 48 ++- .../token/entity/SignMessageType.java | 2 +- 102 files changed, 4140 insertions(+), 495 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/entity/walletconnect/NamespaceParser.java create mode 100644 app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectV2SessionItem.java create mode 100644 app/src/main/java/com/alphawallet/app/interact/WalletConnectInteract.java create mode 100644 app/src/main/java/com/alphawallet/app/service/WalletConnectV2Service.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/WalletConnectNotificationActivity.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainAdapter.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/adapter/MethodAdapter.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletAdapter.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/entity/WalletConnectSessionSortedItem.java create mode 100644 app/src/main/java/com/alphawallet/app/ui/widget/holder/WalletConnectSessionHolder.java create mode 100644 app/src/main/java/com/alphawallet/app/util/LayoutHelper.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectV2ViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/walletconnect/SignMethodDialogViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/SignRequest.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/entity/BaseRequest.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequest.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequest.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/util/WCMethodChecker.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/util/WalletConnectHelper.java create mode 100644 app/src/main/java/com/alphawallet/app/widget/SignMethodDialog.java create mode 100644 app/src/main/res/drawable/ic_wallet_connect_card.xml create mode 100644 app/src/main/res/layout/activity_wallet_connect_v2.xml create mode 100644 app/src/main/res/layout/dialog_sign_method.xml create mode 100644 app/src/main/res/layout/item_chain.xml create mode 100644 app/src/main/res/layout/item_method.xml create mode 100644 app/src/main/res/layout/item_wallet.xml create mode 100644 app/src/main/res/layout/item_wallet_connect_sessions.xml delete mode 100644 app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerActivityTest.java create mode 100644 app/src/test/java/com/alphawallet/app/ui/QRScanning/WalletConnectHelperTest.java create mode 100644 app/src/test/java/com/alphawallet/app/walletconnect/SignRequestTest.java create mode 100644 app/src/test/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequestTest.java create mode 100644 app/src/test/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequestTest.java create mode 100644 app/src/test/java/com/alphawallet/app/walletconnect/entity/WCWCMethodCheckerTest.java create mode 100644 app/src/test/java/com/alphawallet/shadows/ShadowWalletConnectClient.kt create mode 100644 app/src/test/resources/robolectric.properties diff --git a/.gitignore b/.gitignore index aa4d612d51..5433bb5dab 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,7 @@ gen-external-apklibs fastlane/.google-play-key.json DCIM/ +.project vendor/ .project output/ diff --git a/app/build.gradle b/app/build.gradle index 83394ce917..b133472ba1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -89,7 +89,7 @@ android { versionName "3.61" applicationId "io.stormbird.wallet" - minSdkVersion 23 + minSdkVersion 24 targetSdkVersion 32 testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' testInstrumentationRunnerArguments clearPackageData: 'true' @@ -98,10 +98,13 @@ android { def DEFAULT_INFURA_API_KEY = "\"da3717f25f824cc1baa32d812386d93f\"" def DEFAULT_OPENSEA_API_KEY = "\"...\""; //Put your OpenSea developer API key in here, otherwise you are reliant on the backup NFT fetch method (which usually works ok) def DEFAULT_POLYGONSCAN_API_KEY = "\"\""; //Put your Polygonscan developer API key in here to get access to Polygon/Mumbai token discovery and transactions + def DEFUALT_WALLETCONNECT_PROJECT_ID = "\"40c6071febfd93f4fe485c232a8a4cd9\"" def DEFAULT_AURORA_API_KEY = "\"HFDDY5BNKGXBB82DE2G8S64C3C41B76PYI\""; //Put your Aurorascan.dev API key here - this one will rate limit as it is common buildConfigField 'int', 'DB_VERSION', '45' + buildConfigField "String", XInfuraAPI, DEFAULT_INFURA_API_KEY + buildConfigField "String", "WALLETCONNECT_PROJECT_ID", DEFUALT_WALLETCONNECT_PROJECT_ID ndk { abiFilters "armeabi-v7a", "x86", "x86_64", "arm64-v8a" @@ -110,6 +113,8 @@ android { pickFirst 'META-INF/LICENSE.md' pickFirst 'META-INF/NOTICE.md' pickFirst 'META-INF/LICENSE-notice.md' + pickFirst 'META-INF/INDEX.LIST' + pickFirst 'META-INF/DEPENDENCIES' pickFirst 'solidity/ens/build/AbstractENS.bin' } @@ -119,6 +124,7 @@ android { cFlags "-DOSKEY=\\\"" + DEFAULT_OPENSEA_API_KEY + "\\\"" cFlags "-DPSKEY=\\\"" + DEFAULT_POLYGONSCAN_API_KEY + "\\\"" cFlags "-DASKEY=\\\"" + DEFAULT_AURORA_API_KEY + "\\\"" + cFlags "-DWALLETCONNECT_PROJECT_ID=\\\"" + DEFUALT_WALLETCONNECT_PROJECT_ID + "\\\"" } } } @@ -184,8 +190,14 @@ android { abortOnError false } compileOptions { - targetCompatibility JavaVersion.VERSION_1_8 - sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_11 + sourceCompatibility JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = '11' + } + dexOptions { + javaMaxHeapSize = "4g" } externalNativeBuild { cmake { @@ -266,7 +278,7 @@ dependencies { // Bar code scanning implementation 'com.journeyapps:zxing-android-embedded:4.3.0' - implementation 'com.google.zxing:core:3.4.1' + implementation 'com.google.zxing:core:3.5.0' // Sugar implementation 'androidx.constraintlayout:constraintlayout:2.1.4' @@ -315,9 +327,9 @@ dependencies { testImplementation 'androidx.test.ext:junit:1.1.3' // E2e tests - androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'androidx.test:core:1.4.0' - androidTestUtil 'androidx.test:orchestrator:1.4.1' + androidTestImplementation 'androidx.test:runner:1.5.0-alpha02' + androidTestImplementation 'androidx.test:core:1.4.1-alpha05' + androidTestUtil 'androidx.test:orchestrator:1.4.2-alpha02' androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', { exclude group: "com.android.support", module: "support-annotations" }) @@ -328,6 +340,7 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0' + androidTestImplementation 'androidx.browser:browser:1.4.0' implementation 'com.trustwallet:wallet-core:2.6.4' @@ -344,6 +357,12 @@ dependencies { //Timber implementation 'com.jakewharton.timber:timber:5.0.1' + implementation('com.walletconnect:auth:1.1.0', { + exclude group: 'org.web3j', module: '*' + }) + implementation 'com.walletconnect:sign:2.1.0' + implementation 'com.walletconnect:android-core:1.3.0' + implementation 'androidx.work:work-runtime:2.7.1' //Analytics diff --git a/app/check/detekt-baseline.xml b/app/check/detekt-baseline.xml index 322db15915..7b1a54b655 100644 --- a/app/check/detekt-baseline.xml +++ b/app/check/detekt-baseline.xml @@ -1,18 +1,15 @@ - + - + ComplexCondition:WCSession.kt$WCSession.Companion$bridge == null || key == null || topic == null || version == null - ComplexMethod:WCClient.kt$WCClient$private fun handleRequest(request: JsonRpcRequest<JsonArray>) - FunctionNaming:SuggestEIP1559.kt$fun SuggestEIP1559(gasService: GasService, feeHistory: FeeHistory): Single<MutableMap<Int, EIP1559FeeOracleResult>> + ComplexMethod:WCClient.kt$WCClient$private fun handleRequest(request: JsonRpcRequest<JsonArray>) + EmptyFunctionBlock:ShadowWalletConnectClient.kt$ShadowWalletConnectClient${} + EmptySecondaryConstructor:ShadowWalletConnectClient.kt$ShadowWalletConnectClient${} + FunctionNaming:SuggestEIP1559.kt$fun SuggestEIP1559(gasService: GasService, feeHistory: FeeHistory): Single<MutableMap<Int, EIP1559FeeOracleResult>> FunctionParameterNaming:SuggestEIP1559.kt$_needBlocks: Int FunctionParameterNaming:SuggestEIP1559.kt$_ptr: Int FunctionParameterNaming:WCClient.kt$WCClient$_chainId: Long - MagicNumber:JsonRpcModels.kt$JsonRpcError.Companion$32000 - MagicNumber:JsonRpcModels.kt$JsonRpcError.Companion$32600 - MagicNumber:JsonRpcModels.kt$JsonRpcError.Companion$32601 - MagicNumber:JsonRpcModels.kt$JsonRpcError.Companion$32602 - MagicNumber:JsonRpcModels.kt$JsonRpcError.Companion$32700 MagicNumber:SuggestEIP1559.kt$0.9 MagicNumber:SuggestEIP1559.kt$100.0 MagicNumber:SuggestEIP1559.kt$16 @@ -25,7 +22,7 @@ MaxLineLength:SuggestEIP1559.kt$// If a narrower time window yields a lower base fee suggestion than a wider window then we are probably in a price dip. MaxLineLength:SuggestEIP1559.kt$// In this case getting included with a low priority fee is not guaranteed; instead we use the higher base fee suggestion MaxLineLength:SuggestEIP1559.kt$// feeHistory API call with reward percentile specified is expensive and therefore is only requested for a few non-full recent blocks. - MaxLineLength:SuggestEIP1559.kt$else -> (1 - cos((percentile - sampleMinPercentile) * 2 * Math.PI / (sampleMaxPercentile - sampleMinPercentile))) / 2 + MaxLineLength:SuggestEIP1559.kt$else -> (1 - cos((percentile - sampleMinPercentile) * 2 * Math.PI / (sampleMaxPercentile - sampleMinPercentile))) / 2 MaxLineLength:SuggestEIP1559.kt$internal MaxLineLength:SuggestEIP1559.kt$private MaxLineLength:SuggestEIP1559.kt$private const val rewardBlockPercentile = 40 // suggested priority fee to be selected from sorted individual block reward percentiles @@ -33,7 +30,6 @@ MaxLineLength:SuggestEIP1559.kt$result += ((samplingCurveValue - samplingCurveLast) * baseFee[order[i]].toDouble()).toBigDecimal().toBigInteger() MaxLineLength:SuggestEIP1559.kt$return MaxLineLength:SuggestEIP1559.kt$val feeHistory = gasService.getChainFeeHistory(blockCount, "0x" + (firstBlock + ptr).toString(16), rewardPercentile.toString()).blockingGet() - MaxLineLength:WCClient.kt$WCClient$fun NewLineAtEndOfFile:Enums.kt$com.alphawallet.app.walletconnect.entity.Enums.kt NewLineAtEndOfFile:EthereumModels.kt$com.alphawallet.app.walletconnect.entity.EthereumModels.kt NewLineAtEndOfFile:Exceptions.kt$com.alphawallet.app.walletconnect.entity.Exceptions.kt @@ -41,12 +37,13 @@ NewLineAtEndOfFile:JsonRpcModels.kt$com.alphawallet.app.walletconnect.entity.JsonRpcModels.kt NewLineAtEndOfFile:ReleaseTree.kt$com.alphawallet.app.util.ReleaseTree.kt NewLineAtEndOfFile:SessionModels.kt$com.alphawallet.app.walletconnect.entity.SessionModels.kt + NewLineAtEndOfFile:ShadowWalletConnectClient.kt$com.alphawallet.shadows.ShadowWalletConnectClient.kt NewLineAtEndOfFile:SuggestEIP1559.kt$com.alphawallet.app.entity.SuggestEIP1559.kt NewLineAtEndOfFile:WCSession.kt$com.alphawallet.app.walletconnect.WCSession.kt - ReturnCount:SuggestEIP1559.kt$internal fun predictMinBaseFee(baseFee: Array<BigInteger>, order: List<Int>, timeFactor: Double): BigInteger + ReturnCount:SuggestEIP1559.kt$internal fun predictMinBaseFee(baseFee: Array<BigInteger>, order: List<Int>, timeFactor: Double): BigInteger ReturnCount:WCSession.kt$WCSession.Companion$fun from(from: String): WCSession? SwallowedException:WCClient.kt$WCClient$e: JsonSyntaxException - ThrowsCount:WCClient.kt$WCClient$private fun handleRequest(request: JsonRpcRequest<JsonArray>) + ThrowsCount:WCClient.kt$WCClient$private fun handleRequest(request: JsonRpcRequest<JsonArray>) TooGenericExceptionCaught:WCClient.kt$WCClient$e: Exception TooManyFunctions:WCClient.kt$WCClient : WebSocketListener TopLevelPropertyNaming:SuggestEIP1559.kt$private const val extraPriorityFeeRatio = 0.25 // extra priority fee offered in case of expected baseFee rise @@ -56,7 +53,8 @@ TopLevelPropertyNaming:SuggestEIP1559.kt$private const val rewardPercentile = 10 // effective reward value to be selected from each individual block TopLevelPropertyNaming:SuggestEIP1559.kt$private const val sampleMaxPercentile = 30 TopLevelPropertyNaming:SuggestEIP1559.kt$private const val sampleMinPercentile = 10 // sampled percentile range of exponentially weighted baseFee history - UnusedPrivateMember:WCClient.kt$WCClient$private val TAG = WCClient::class.java.simpleName + UnusedPrivateMember:ShadowWalletConnectClient.kt$ShadowWalletConnectClient$delegate: WalletConnectClient.WalletDelegate + UnusedPrivateMember:ShadowWalletConnectClient.kt$ShadowWalletConnectClient$onError: (WalletConnectException) -> Unit = {} VariableNaming:WCClient.kt$WCClient$private val TAG = WCClient::class.java.simpleName WildcardImport:WCClient.kt$import com.alphawallet.app.walletconnect.entity.* WildcardImport:WCClient.kt$import okhttp3.* diff --git a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java index 5a88e835f1..a7ea9d5f44 100644 --- a/app/src/androidTest/java/com/alphawallet/app/util/Helper.java +++ b/app/src/androidTest/java/com/alphawallet/app/util/Helper.java @@ -14,6 +14,7 @@ import android.content.Context; import android.view.KeyEvent; import android.view.View; + import android.view.inputmethod.InputMethodManager; import androidx.test.espresso.PerformException; @@ -24,6 +25,10 @@ import androidx.test.espresso.util.HumanReadables; import androidx.test.espresso.util.TreeIterables; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; + +import java.util.concurrent.TimeoutException; import com.alphawallet.app.R; import org.hamcrest.Matcher; diff --git a/app/src/androidTest/java/com/alphawallet/app/util/SnapshotUtil.java b/app/src/androidTest/java/com/alphawallet/app/util/SnapshotUtil.java index d02a1e8d23..bba09a6a4b 100644 --- a/app/src/androidTest/java/com/alphawallet/app/util/SnapshotUtil.java +++ b/app/src/androidTest/java/com/alphawallet/app/util/SnapshotUtil.java @@ -1,5 +1,6 @@ package com.alphawallet.app.util; +import android.os.Build; import android.os.Environment; import androidx.test.platform.app.InstrumentationRegistry; @@ -7,14 +8,26 @@ import java.io.File; -public class SnapshotUtil { - public static void take(String testName) { - File path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath()); - if (!path.exists()) { +import timber.log.Timber; + +public class SnapshotUtil +{ + public static String SNAPSHOT_DIR = ""; + + public static void take(String testName) + { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + { + Timber.tag("SnapshotUtil").d("Skipping snapshot for API < 30"); + return; + } + File path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/" + SNAPSHOT_DIR); + if (!path.exists()) + { path.mkdirs(); } UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); - device.takeScreenshot(new File(path, testName + ".png")); + device.takeScreenshot(new File(path, testName + "." + Build.VERSION.SDK_INT + ".png")); } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ab525be802..02a932abeb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,6 +13,7 @@ + + + + + + + + + NewStringUTF(env, key); #endif } + +JNIEXPORT jstring JNICALL +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getWalletConnectProjectId( JNIEnv* env, jclass thiz ) +{ +#if (HAS_KEYS == 1) + return getDecryptedKey(env, walletConnectProjectId); +#else + return (*env)->NewStringUTF(env, WALLETCONNECT_PROJECT_ID); +#endif +} diff --git a/app/src/main/java/com/alphawallet/app/App.java b/app/src/main/java/com/alphawallet/app/App.java index f8d48b1a4a..dbbbe33fc1 100644 --- a/app/src/main/java/com/alphawallet/app/App.java +++ b/app/src/main/java/com/alphawallet/app/App.java @@ -3,17 +3,23 @@ import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; +import android.app.Activity; import android.app.Application; import android.app.UiModeManager; import android.content.Context; +import android.os.Bundle; import androidx.appcompat.app.AppCompatDelegate; import androidx.preference.PreferenceManager; import com.alphawallet.app.util.ReleaseTree; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; + +import java.util.Stack; + +import javax.inject.Inject; import dagger.hilt.android.HiltAndroidApp; -import io.reactivex.functions.Consumer; import io.reactivex.plugins.RxJavaPlugins; import io.realm.Realm; import timber.log.Timber; @@ -21,11 +27,27 @@ @HiltAndroidApp public class App extends Application { + @Inject + AWWalletConnectClient awWalletConnectClient; + + private static App mInstance; + private final Stack activityStack = new Stack<>(); + + public static App getInstance() + { + return mInstance; + } + + public Activity getTopActivity() + { + return activityStack.peek(); + } @Override public void onCreate() { super.onCreate(); + mInstance = this; Realm.init(this); if (BuildConfig.DEBUG) @@ -64,9 +86,79 @@ else if (mode == UiModeManager.MODE_NIGHT_NO) RxJavaPlugins.setErrorHandler(Timber::e); - // enable pin code for the application -// LockManager lockManager = LockManager.getInstance(); -// lockManager.enableAppLock(this, CustomPinActivity.class); -// lockManager.getAppLock().setShouldShowForgot(false); + try + { + awWalletConnectClient.init(this); + } + catch (Exception e) + { + Timber.tag("WalletConnect").e(e); + } + + registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() + { + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) + { + } + + @Override + public void onActivityDestroyed(Activity activity) + { + } + + @Override + public void onActivityStarted(Activity activity) + { + } + + @Override + public void onActivityResumed(Activity activity) + { + activityStack.push(activity); + } + + @Override + public void onActivityPaused(Activity activity) + { + pop(); + } + + @Override + public void onActivityStopped(Activity activity) + { + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) + { + } + }); + } + + @Override + public void onTrimMemory(int level) + { + super.onTrimMemory(level); + if (awWalletConnectClient != null) + { + awWalletConnectClient.shutdown(); + } + } + + @Override + public void onTerminate() + { + super.onTerminate(); + activityStack.clear(); + if (awWalletConnectClient != null) + { + awWalletConnectClient.shutdown(); + } + } + + private void pop() + { + activityStack.pop(); } } diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index e71cdd3244..4512a8a55a 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -300,6 +300,9 @@ public enum TokenStatus { public static final String APP_NAME = "PACKAGE_NAME"; public static final String ALPHAWALLET_LOGO_URI = "https://alphawallet.com/wp-content/themes/alphawallet/img/logo-horizontal-new.svg"; + public static final String ALPHAWALLET_WEBSITE = "https://alphawallet.com"; + public static final String WALLET_CONNECT_REACT_APP_RELAY_URL = "wss://relay.walletconnect.com"; + public static final String ALPHA_WALLET_LOGO_URL = "https://user-images.githubusercontent.com/51817359/158344418-c0f2bd19-38bb-4e64-a1d5-25ceb099688a.png"; // Theme/Dark Mode public static final int THEME_LIGHT = 0; diff --git a/app/src/main/java/com/alphawallet/app/di/ToolsModule.java b/app/src/main/java/com/alphawallet/app/di/ToolsModule.java index 63d1549f7d..c948956729 100644 --- a/app/src/main/java/com/alphawallet/app/di/ToolsModule.java +++ b/app/src/main/java/com/alphawallet/app/di/ToolsModule.java @@ -1,7 +1,11 @@ package com.alphawallet.app.di; +import android.content.Context; + import com.alphawallet.app.C; +import com.alphawallet.app.interact.WalletConnectInteract; import com.alphawallet.app.service.RealmManager; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.google.gson.Gson; import java.util.concurrent.TimeUnit; @@ -11,34 +15,46 @@ import dagger.Module; import dagger.Provides; import dagger.hilt.InstallIn; +import dagger.hilt.android.qualifiers.ApplicationContext; import dagger.hilt.components.SingletonComponent; import okhttp3.OkHttpClient; @Module @InstallIn(SingletonComponent.class) -public class ToolsModule { - - @Singleton - @Provides - Gson provideGson() { - return new Gson(); - } - - @Singleton - @Provides - OkHttpClient okHttpClient() { - return new OkHttpClient.Builder() +public class ToolsModule +{ + + @Singleton + @Provides + Gson provideGson() + { + return new Gson(); + } + + @Singleton + @Provides + OkHttpClient okHttpClient() + { + return new OkHttpClient.Builder() //.addInterceptor(new LogInterceptor()) .connectTimeout(C.CONNECT_TIMEOUT, TimeUnit.SECONDS) .readTimeout(C.READ_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(C.WRITE_TIMEOUT, TimeUnit.SECONDS) - .retryOnConnectionFailure(false) + .retryOnConnectionFailure(false) .build(); - } + } + + @Singleton + @Provides + RealmManager provideRealmManager() + { + return new RealmManager(); + } - @Singleton + @Singleton @Provides - RealmManager provideRealmManager() { - return new RealmManager(); + AWWalletConnectClient provideAWWalletConnectClient(@ApplicationContext Context context, WalletConnectInteract walletConnectInteract) + { + return new AWWalletConnectClient(context, walletConnectInteract); } } diff --git a/app/src/main/java/com/alphawallet/app/entity/Wallet.java b/app/src/main/java/com/alphawallet/app/entity/Wallet.java index 83a5990fa6..8d4a5d4d1f 100644 --- a/app/src/main/java/com/alphawallet/app/entity/Wallet.java +++ b/app/src/main/java/com/alphawallet/app/entity/Wallet.java @@ -10,7 +10,8 @@ import java.math.BigDecimal; -public class Wallet implements Parcelable { +public class Wallet implements Parcelable +{ public final String address; public String balance; public String ENSname; @@ -24,102 +25,113 @@ public class Wallet implements Parcelable { public boolean isSynced; public Token[] tokens; - public Wallet(String address) { - this.address = address; - this.balance = "-"; - this.ENSname = ""; - this.name = ""; - this.type = WalletType.NOT_DEFINED; - this.lastBackupTime = 0; - this.authLevel = KeyService.AuthenticationLevel.NOT_SET; - this.walletCreationTime = 0; - this.balanceSymbol = ""; - this.ENSAvatar = ""; - } - - private Wallet(Parcel in) - { - address = in.readString(); - balance = in.readString(); - ENSname = in.readString(); - name = in.readString(); - int t = in.readInt(); - type = WalletType.values()[t]; - lastBackupTime = in.readLong(); - t = in.readInt(); - authLevel = KeyService.AuthenticationLevel.values()[t]; - walletCreationTime = in.readLong(); - balanceSymbol = in.readString(); - ENSAvatar = in.readString(); - } - - public void setWalletType(WalletType wType) - { - type = wType; - } - - public static final Creator CREATOR = new Creator() { - @Override - public Wallet createFromParcel(Parcel in) { - return new Wallet(in); - } - - @Override - public Wallet[] newArray(int size) { - return new Wallet[size]; - } - }; - - public boolean sameAddress(String address) { - return this.address.equalsIgnoreCase(address); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int i) - { - parcel.writeString(address); - parcel.writeString(balance); - parcel.writeString(ENSname); - parcel.writeString(name); - parcel.writeInt(type.ordinal()); - parcel.writeLong(lastBackupTime); - parcel.writeInt(authLevel.ordinal()); - parcel.writeLong(walletCreationTime); - parcel.writeString(balanceSymbol); - parcel.writeString(ENSAvatar); - } - - public boolean setWalletBalance(Token token) - { - balanceSymbol = token.tokenInfo != null ? token.tokenInfo.symbol : "ETH"; - String newBalance = token.getFixedFormattedBalance(); - if (newBalance.equals(balance)) - { - return false; - } - else - { - balance = newBalance; - return true; - } - } - - public void zeroWalletBalance(NetworkInfo networkInfo) - { - if (balance.equals("-")) - { - balanceSymbol = networkInfo.symbol; - balance = BalanceUtils.getScaledValueFixed(BigDecimal.ZERO, 0, Token.TOKEN_BALANCE_PRECISION); - } - } + public Wallet(String address) + { + this.address = address; + this.balance = "-"; + this.ENSname = ""; + this.name = ""; + this.type = WalletType.NOT_DEFINED; + this.lastBackupTime = 0; + this.authLevel = KeyService.AuthenticationLevel.NOT_SET; + this.walletCreationTime = 0; + this.balanceSymbol = ""; + this.ENSAvatar = ""; + } + + private Wallet(Parcel in) + { + address = in.readString(); + balance = in.readString(); + ENSname = in.readString(); + name = in.readString(); + int t = in.readInt(); + type = WalletType.values()[t]; + lastBackupTime = in.readLong(); + t = in.readInt(); + authLevel = KeyService.AuthenticationLevel.values()[t]; + walletCreationTime = in.readLong(); + balanceSymbol = in.readString(); + ENSAvatar = in.readString(); + } + + public void setWalletType(WalletType wType) + { + type = wType; + } + + public static final Creator CREATOR = new Creator() + { + @Override + public Wallet createFromParcel(Parcel in) + { + return new Wallet(in); + } + + @Override + public Wallet[] newArray(int size) + { + return new Wallet[size]; + } + }; + + public boolean sameAddress(String address) + { + return this.address.equalsIgnoreCase(address); + } + + @Override + public int describeContents() + { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) + { + parcel.writeString(address); + parcel.writeString(balance); + parcel.writeString(ENSname); + parcel.writeString(name); + parcel.writeInt(type.ordinal()); + parcel.writeLong(lastBackupTime); + parcel.writeInt(authLevel.ordinal()); + parcel.writeLong(walletCreationTime); + parcel.writeString(balanceSymbol); + parcel.writeString(ENSAvatar); + } + + public boolean setWalletBalance(Token token) + { + balanceSymbol = token.tokenInfo != null ? token.tokenInfo.symbol : "ETH"; + String newBalance = token.getFixedFormattedBalance(); + if (newBalance.equals(balance)) + { + return false; + } + else + { + balance = newBalance; + return true; + } + } + + public void zeroWalletBalance(NetworkInfo networkInfo) + { + if (balance.equals("-")) + { + balanceSymbol = networkInfo.symbol; + balance = BalanceUtils.getScaledValueFixed(BigDecimal.ZERO, 0, Token.TOKEN_BALANCE_PRECISION); + } + } public boolean canSign() { - return BuildConfig.DEBUG || type != WalletType.WATCH; + return BuildConfig.DEBUG || !watchOnly(); + } + + public boolean watchOnly() + { + return type == WalletType.WATCH; } } diff --git a/app/src/main/java/com/alphawallet/app/entity/walletconnect/NamespaceParser.java b/app/src/main/java/com/alphawallet/app/entity/walletconnect/NamespaceParser.java new file mode 100644 index 0000000000..f80c6f2b4a --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/walletconnect/NamespaceParser.java @@ -0,0 +1,72 @@ +package com.alphawallet.app.entity.walletconnect; + +import com.walletconnect.sign.client.Sign; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class NamespaceParser +{ + private final List chains = new ArrayList<>(); + private final List methods = new ArrayList<>(); + private final List events = new ArrayList<>(); + private final List wallets = new ArrayList<>(); + + public void parseProposal(Map requiredNamespaces) + { + for (Map.Entry entry : requiredNamespaces.entrySet()) + { + chains.addAll(entry.getValue().getChains()); + methods.addAll(entry.getValue().getMethods()); + events.addAll(entry.getValue().getEvents()); + } + } + + public void parseSession(Map namespaces) + { + for (Map.Entry entry : namespaces.entrySet()) + { + chains.addAll(parseChains(entry.getValue().getAccounts())); + methods.addAll(entry.getValue().getMethods()); + events.addAll(entry.getValue().getEvents()); + wallets.addAll(parseWallets(entry.getValue().getAccounts())); + } + } + + private List parseWallets(List accounts) + { + return accounts.stream() + .map((account) -> account.substring(account.lastIndexOf(":") + 1)) + .collect(Collectors.toList()); + } + + private List parseChains(List accounts) + { + return accounts.stream() + .map((account) -> account.substring(0, account.lastIndexOf(":"))) + .collect(Collectors.toList()); + } + + public List getChains() + { + return chains; + } + + public List getMethods() + { + return methods; + } + + public List getEvents() + { + return events; + } + + public List getWallets() + { + return new ArrayList<>(new HashSet<>(wallets)); + } +} diff --git a/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectV2SessionItem.java b/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectV2SessionItem.java new file mode 100644 index 0000000000..f02562247a --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectV2SessionItem.java @@ -0,0 +1,100 @@ +package com.alphawallet.app.entity.walletconnect; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.walletconnect.sign.client.Sign; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class WalletConnectV2SessionItem extends WalletConnectSessionItem implements Parcelable +{ + public boolean settled; + public List chains = new ArrayList<>(); + public List wallets = new ArrayList<>(); + public List methods = new ArrayList<>(); + + public WalletConnectV2SessionItem(Sign.Model.Session s) + { + super(); + name = Objects.requireNonNull(s.getMetaData()).getName(); + url = Objects.requireNonNull(s.getMetaData()).getUrl(); + icon = s.getMetaData().getIcons().isEmpty() ? null : s.getMetaData().getIcons().get(0); + sessionId = s.getTopic(); + localSessionId = s.getTopic(); + settled = true; + NamespaceParser namespaceParser = new NamespaceParser(); + namespaceParser.parseSession(s.getNamespaces()); + chains = namespaceParser.getChains(); + methods = namespaceParser.getMethods(); + wallets = namespaceParser.getWallets(); + } + + public WalletConnectV2SessionItem(Parcel in) + { + name = in.readString(); + url = in.readString(); + icon = in.readString(); + sessionId = in.readString(); + localSessionId = in.readString(); + settled = in.readInt() == 1; + in.readStringList(chains); + in.readStringList(wallets); + in.readStringList(methods); + } + + public WalletConnectV2SessionItem() + { + } + + public static WalletConnectV2SessionItem from(Sign.Model.SessionProposal sessionProposal) + { + WalletConnectV2SessionItem item = new WalletConnectV2SessionItem(); + item.name = sessionProposal.getName(); + item.url = sessionProposal.getUrl(); + item.icon = sessionProposal.getIcons().isEmpty() ? null : sessionProposal.getIcons().get(0).toString(); + item.sessionId = sessionProposal.getProposerPublicKey(); + item.settled = false; + NamespaceParser namespaceParser = new NamespaceParser(); + namespaceParser.parseProposal(sessionProposal.getRequiredNamespaces()); + item.chains.addAll(namespaceParser.getChains()); + item.methods.addAll(namespaceParser.getMethods()); + return item; + } + + @Override + public int describeContents() + { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) + { + dest.writeString(name); + dest.writeString(url); + dest.writeString(icon); + dest.writeString(sessionId); + dest.writeString(localSessionId); + dest.writeInt(settled ? 1 : 0); + dest.writeStringList(chains); + dest.writeStringList(wallets); + dest.writeStringList(methods); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator<>() + { + public WalletConnectV2SessionItem createFromParcel(Parcel in) + { + return new WalletConnectV2SessionItem(in); + } + + @Override + public WalletConnectV2SessionItem[] newArray(int size) + { + return new WalletConnectV2SessionItem[0]; + } + }; +} diff --git a/app/src/main/java/com/alphawallet/app/interact/WalletConnectInteract.java b/app/src/main/java/com/alphawallet/app/interact/WalletConnectInteract.java new file mode 100644 index 0000000000..01fc497ac1 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/interact/WalletConnectInteract.java @@ -0,0 +1,131 @@ +package com.alphawallet.app.interact; + +import android.content.ComponentName; +import android.content.Context; +import android.content.ServiceConnection; +import android.os.IBinder; + +import com.alphawallet.app.entity.WalletConnectActions; +import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; +import com.alphawallet.app.entity.walletconnect.WalletConnectV2SessionItem; +import com.alphawallet.app.repository.entity.RealmWCSession; +import com.alphawallet.app.service.RealmManager; +import com.alphawallet.app.service.WalletConnectService; +import com.alphawallet.app.viewmodel.WalletConnectViewModel; +import com.alphawallet.app.walletconnect.WCClient; +import com.alphawallet.app.walletconnect.entity.WCUtils; +import com.walletconnect.sign.client.Sign; +import com.walletconnect.sign.client.SignClient; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import io.realm.Realm; +import io.realm.RealmResults; +import io.realm.Sort; +import timber.log.Timber; + +public class WalletConnectInteract +{ + private final RealmManager realmManager; + + @Inject + public WalletConnectInteract(RealmManager realmManager) + { + this.realmManager = realmManager; + } + + public int getSessionsCount() + { + return getSessions().size(); + } + + public List getSessions() + { + List result = new ArrayList<>(); + result.addAll(getWalletConnectV1SessionItems()); + result.addAll(getWalletConnectV2SessionItems()); + return result; + } + + public void fetchSessions(Context context, SessionFetchCallback sessionFetchCallback) + { + ServiceConnection connection = new ServiceConnection() + { + @Override + public void onServiceConnected(ComponentName name, IBinder service) + { + WalletConnectService walletConnectService = ((WalletConnectService.LocalBinder) service).getService(); + fetch(walletConnectService, sessionFetchCallback); + } + + @Override + public void onServiceDisconnected(ComponentName name) + { + } + }; + + WCUtils.startServiceLocal(context, connection, WalletConnectActions.CONNECT); + } + + private void fetch(WalletConnectService walletConnectService, SessionFetchCallback sessionFetchCallback) + { + List result = new ArrayList<>(); + List sessionItems = getWalletConnectV1SessionItems(); + for (WalletConnectSessionItem item : sessionItems) + { + WCClient wcClient = walletConnectService.getClient(item.sessionId); + if (wcClient != null && wcClient.isConnected()) + { + result.add(item); + } + } + + result.addAll(getWalletConnectV2SessionItems()); + sessionFetchCallback.onFetched(result); + } + + private List getWalletConnectV1SessionItems() + { + List sessions = new ArrayList<>(); + try (Realm realm = realmManager.getRealmInstance(WalletConnectViewModel.WC_SESSION_DB)) + { + RealmResults items = realm.where(RealmWCSession.class) + .sort("lastUsageTime", Sort.DESCENDING) + .findAll(); + + for (RealmWCSession r : items) + { + sessions.add(new WalletConnectSessionItem(r)); + } + } + + return sessions; + } + + private List getWalletConnectV2SessionItems() + { + List result = new ArrayList<>(); + try + { + List listOfSettledSessions = SignClient.INSTANCE.getListOfSettledSessions(); + for (Sign.Model.Session session : listOfSettledSessions) + { + result.add(new WalletConnectV2SessionItem(session)); + } + } + catch (IllegalStateException e) + { + Timber.e(e); + } + return result; + } + + public interface SessionFetchCallback + { + void onFetched(List sessions); + } +} + diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java index 848353be7f..dc6a441977 100644 --- a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java @@ -3,16 +3,30 @@ public interface KeyProvider { String getBSCExplorerKey(); + String getAnalyticsKey(); + String getEtherscanKey(); + String getPolygonScanKey(); + String getAuroraScanKey(); + String getCovalentKey(); + String getKlaytnKey(); + String getInfuraKey(); + String getSecondaryInfuraKey(); + String getRampKey(); + String getOpenSeaKey(); + String getMailchimpKey(); + String getCoinbasePayAppId(); + + String getWalletConnectProjectId(); } diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java index 48f65d7170..e07661d698 100644 --- a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java @@ -8,16 +8,30 @@ public KeyProviderJNIImpl() } public native String getInfuraKey(); + public native String getSecondaryInfuraKey(); + public native String getBSCExplorerKey(); + public native String getAnalyticsKey(); + public native String getEtherscanKey(); + public native String getPolygonScanKey(); + public native String getAuroraScanKey(); + public native String getCovalentKey(); + public native String getKlaytnKey(); + public native String getRampKey(); + public native String getOpenSeaKey(); + public native String getMailchimpKey(); + public native String getCoinbasePayAppId(); + + public native String getWalletConnectProjectId(); } diff --git a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java index b1ef17ac41..a296787916 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java @@ -76,7 +76,6 @@ public class TokenRepository implements TokenRepositoryType { private static final String TAG = "TRT"; private final TokenLocalSource localSource; - private final KeyProvider keyProvider = KeyProviderFactory.get(); private final EthereumNetworkRepositoryType ethereumNetworkRepository; private final OkHttpClient okClient; private final Context context; diff --git a/app/src/main/java/com/alphawallet/app/service/PriceAlertsService.java b/app/src/main/java/com/alphawallet/app/service/PriceAlertsService.java index f88028858d..1eb02a6d95 100644 --- a/app/src/main/java/com/alphawallet/app/service/PriceAlertsService.java +++ b/app/src/main/java/com/alphawallet/app/service/PriceAlertsService.java @@ -5,6 +5,8 @@ import android.os.Binder; import android.os.IBinder; +import androidx.annotation.Nullable; + import com.alphawallet.app.R; import com.alphawallet.app.entity.CurrencyItem; import com.alphawallet.app.entity.Wallet; @@ -26,8 +28,6 @@ import javax.inject.Inject; -import androidx.annotation.Nullable; - import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; diff --git a/app/src/main/java/com/alphawallet/app/service/WalletConnectService.java b/app/src/main/java/com/alphawallet/app/service/WalletConnectService.java index 73c6bff9c7..910dc5f936 100644 --- a/app/src/main/java/com/alphawallet/app/service/WalletConnectService.java +++ b/app/src/main/java/com/alphawallet/app/service/WalletConnectService.java @@ -56,6 +56,11 @@ public int onStartCommand(Intent intent, int flags, int startId) { Timber.tag(TAG).d("SERVICE STARTING"); + if (intent == null) + { + return Service.START_STICKY; + } + try { int actionVal = Integer.parseInt(intent.getAction()); diff --git a/app/src/main/java/com/alphawallet/app/service/WalletConnectV2Service.java b/app/src/main/java/com/alphawallet/app/service/WalletConnectV2Service.java new file mode 100644 index 0000000000..2843870357 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/service/WalletConnectV2Service.java @@ -0,0 +1,68 @@ +package com.alphawallet.app.service; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.IBinder; + +import androidx.annotation.RequiresApi; +import androidx.core.app.NotificationCompat; + +import com.alphawallet.app.R; +import com.alphawallet.app.ui.WalletConnectNotificationActivity; + +import dagger.hilt.android.AndroidEntryPoint; + +@AndroidEntryPoint +public class WalletConnectV2Service extends Service +{ + @Override + public IBinder onBind(Intent intent) + { + return null; + } + + @RequiresApi(api = Build.VERSION_CODES.O) + @Override + public void onCreate() + { + super.onCreate(); + String CHANNEL_ID = "my_channel_01"; + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + "WalletConnect V2", + NotificationManager.IMPORTANCE_DEFAULT); + + NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.createNotificationChannel(channel); + + Intent intent = new Intent(getApplicationContext(), WalletConnectNotificationActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_IMMUTABLE); + Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) + .setSmallIcon(R.drawable.ic_logo) + .setContentTitle(getString(R.string.notify_wallet_connect_title)) + .setContentText(getString(R.string.notify_wallet_connect_content)) + .setContentIntent(pendingIntent) + .build(); + + startForeground(1, notification); + notificationManager.notify(1, notification); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) + { + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onDestroy() + { + super.onDestroy(); + stopForeground(true); + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java b/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java index 1b4ed26388..3b446adab7 100644 --- a/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java @@ -1,22 +1,30 @@ package com.alphawallet.app.ui; +import android.content.Intent; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; +import com.alphawallet.app.R; +import com.alphawallet.app.entity.AuthenticationFailType; +import com.alphawallet.app.entity.Operation; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; +import com.alphawallet.app.viewmodel.BaseViewModel; +import com.alphawallet.app.widget.SignTransactionDialog; + import androidx.annotation.DrawableRes; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; -import com.alphawallet.app.R; -import com.alphawallet.app.viewmodel.BaseViewModel; - -public abstract class BaseActivity extends AppCompatActivity { +public abstract class BaseActivity extends AppCompatActivity +{ - protected Toolbar toolbar() { + protected Toolbar toolbar() + { Toolbar toolbar = findViewById(R.id.toolbar); - if (toolbar != null) { + if (toolbar != null) + { setSupportActionBar(toolbar); toolbar.setTitle(R.string.empty); } @@ -28,80 +36,125 @@ protected void setTitle(String title) { ActionBar actionBar = getSupportActionBar(); TextView toolbarTitle = findViewById(R.id.toolbar_title); - if (toolbarTitle != null) { - if (actionBar != null) { + if (toolbarTitle != null) + { + if (actionBar != null) + { actionBar.setTitle(R.string.empty); } toolbarTitle.setText(title); } } - protected void setSubtitle(String subtitle) { + protected void setSubtitle(String subtitle) + { ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { + if (actionBar != null) + { actionBar.setSubtitle(subtitle); } } - protected void enableDisplayHomeAsUp() { + protected void enableDisplayHomeAsUp() + { ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { + if (actionBar != null) + { actionBar.setDisplayHomeAsUpEnabled(true); } } - protected void enableDisplayHomeAsUp(@DrawableRes int resourceId) { + protected void enableDisplayHomeAsUp(@DrawableRes int resourceId) + { ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { + if (actionBar != null) + { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(resourceId); } } - protected void enableDisplayHomeAsHome(boolean active) { + protected void enableDisplayHomeAsHome(boolean active) + { ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { + if (actionBar != null) + { actionBar.setDisplayHomeAsUpEnabled(active); actionBar.setHomeAsUpIndicator(R.drawable.ic_browser_home); } } - protected void dissableDisplayHomeAsUp() { + protected void dissableDisplayHomeAsUp() + { ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { + if (actionBar != null) + { actionBar.setDisplayHomeAsUpEnabled(false); } } - protected void hideToolbar() { + protected void hideToolbar() + { ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { + if (actionBar != null) + { actionBar.hide(); } } - protected void showToolbar() { + protected void showToolbar() + { ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { + if (actionBar != null) + { actionBar.show(); } } @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - onBackPressed(); - finish(); - break; + public boolean onOptionsItemSelected(MenuItem item) + { + if (item.getItemId() == android.R.id.home) + { + onBackPressed(); + finish(); } return true; } - public void displayToast(String message) { - if (message != null) { + public void displayToast(String message) + { + if (message != null) + { Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); BaseViewModel.onPushToast(null); } } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + super.onActivityResult(requestCode, resultCode, data); + + //Interpret the return code; if it's within the range of values possible to return from PIN confirmation then separate out + //the task code from the return value. We have to do it this way because there's no way to send a bundle across the PIN dialog + //and out through the PIN dialog's return back to here + if (AWWalletConnectClient.authCallback == null) + { + return; + } + + if (requestCode >= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS && requestCode <= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + 10) + { + Operation taskCode = Operation.values()[requestCode - SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS]; + if (resultCode == RESULT_OK) + { + AWWalletConnectClient.authCallback.authenticatePass(taskCode); + } + else + { + AWWalletConnectClient.authCallback.authenticateFail("", AuthenticationFailType.PIN_FAILED, taskCode); + } + } + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index b06fb5a885..1f241c52ae 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -6,6 +6,7 @@ import static com.alphawallet.app.entity.tokens.Token.TOKEN_BALANCE_PRECISION; import static com.alphawallet.app.ui.HomeActivity.RESET_TOKEN_SERVICE; import static com.alphawallet.app.ui.MyAddressActivity.KEY_ADDRESS; +import static com.alphawallet.app.util.KeyboardUtils.showKeyboard; import static com.alphawallet.app.util.Utils.isValidUrl; import static com.alphawallet.app.widget.AWalletAlertDialog.ERROR; import static com.alphawallet.app.widget.AWalletAlertDialog.WARNING; @@ -1932,6 +1933,7 @@ private String determineMimeType(@NotNull WebChromeClient.FileChooserParams file } else { + //TODO: Resolve types switch (firstType) { case "png": diff --git a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java index 123f818cea..2c073ede66 100644 --- a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java @@ -63,7 +63,6 @@ import com.alphawallet.app.entity.FragmentMessenger; import com.alphawallet.app.entity.HomeCommsInterface; import com.alphawallet.app.entity.HomeReceiver; -import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletPage; @@ -927,10 +926,9 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - Operation taskCode = null; + super.onActivityResult(requestCode, resultCode, data); if (requestCode >= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS && requestCode <= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + 10) { - taskCode = Operation.values()[requestCode - SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS]; requestCode = SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS; } diff --git a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java index e2d0c69065..98bdf77935 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/NewSettingsFragment.java @@ -627,7 +627,6 @@ private void onSupportSettingClicked() private void onWalletConnectSettingClicked() { Intent intent = new Intent(getActivity(), WalletConnectSessionActivity.class); - intent.putExtra("wallet", wallet); startActivity(intent); } diff --git a/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java b/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java index 3759d80781..fbfc48d0c5 100644 --- a/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/QRScanning/QRScannerActivity.java @@ -19,7 +19,6 @@ import android.text.TextUtils; import android.view.KeyEvent; import android.widget.TextView; -import android.widget.Toast; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; @@ -39,6 +38,8 @@ import com.alphawallet.app.entity.analytics.QrScanSource; import com.alphawallet.app.ui.BaseActivity; import com.alphawallet.app.ui.WalletConnectActivity; +import com.alphawallet.app.ui.WalletConnectV2Activity; +import com.alphawallet.app.walletconnect.util.WalletConnectHelper; import com.alphawallet.app.viewmodel.QrScannerViewModel; import com.alphawallet.app.widget.AWalletAlertDialog; import com.google.zxing.BarcodeFormat; @@ -93,12 +94,6 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) - { - Toast.makeText(this, R.string.toast_qr_scanning_requires_api_24, Toast.LENGTH_SHORT).show(); - finish(); - } - hideSystemUI(); int rc = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA); @@ -384,9 +379,18 @@ private void displayErrorDialog(String title, String errorMessage) private void startWalletConnect(String qrCode) { - Intent intent = new Intent(this, WalletConnectActivity.class); - intent.putExtra("qrCode", qrCode); - intent.putExtra(C.EXTRA_CHAIN_ID, chainIdOverride); + Intent intent; + if (WalletConnectHelper.isWalletConnectV1(qrCode)) + { + intent = new Intent(this, WalletConnectActivity.class); + intent.putExtra("qrCode", qrCode); + intent.putExtra(C.EXTRA_CHAIN_ID, chainIdOverride); + } + else + { + intent = new Intent(this, WalletConnectV2Activity.class); + intent.putExtra("url", qrCode); + } startActivity(intent); setResult(WALLET_CONNECT); finish(); diff --git a/app/src/main/java/com/alphawallet/app/ui/SendActivity.java b/app/src/main/java/com/alphawallet/app/ui/SendActivity.java index b002545445..b925de8cdb 100644 --- a/app/src/main/java/com/alphawallet/app/ui/SendActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/SendActivity.java @@ -200,100 +200,96 @@ public void onBackPressed() @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - Operation taskCode = null; - if (requestCode >= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS && requestCode <= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + 10) { - taskCode = Operation.values()[requestCode - SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS]; - requestCode = SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS; - } - - if (requestCode >= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS && requestCode <= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + 10) - { - if (confirmationDialog != null && confirmationDialog.isShowing()) - confirmationDialog.completeSignRequest(resultCode == RESULT_OK); - } - else if (requestCode == C.BARCODE_READER_REQUEST_CODE) - { - switch (resultCode) + Operation taskCode = null; + if (requestCode >= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS && requestCode <= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + 10) { - case Activity.RESULT_OK: - if (data != null) - { - String qrCode = data.getStringExtra(C.EXTRA_QR_CODE); + taskCode = Operation.values()[requestCode - SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS]; + requestCode = SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS; + } - //if barcode is still null, ensure we don't GPF - if (qrCode == null) - { - //Toast.makeText(this, R.string.toast_qr_code_no_address, Toast.LENGTH_SHORT).show(); - displayScanError(); - return; - } - else if (qrCode.startsWith("wc:")) - { - startWalletConnect(qrCode); - } - else + if (requestCode >= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS && requestCode <= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + 10) + { + if (confirmationDialog != null && confirmationDialog.isShowing()) + confirmationDialog.completeSignRequest(resultCode == RESULT_OK); + } + else if (requestCode == C.BARCODE_READER_REQUEST_CODE) + { + switch (resultCode) + { + case Activity.RESULT_OK: + if (data != null) { + String qrCode = data.getStringExtra(C.EXTRA_QR_CODE); - QRParser parser = QRParser.getInstance(EthereumNetworkBase.extraChains()); - QRResult result = parser.parse(qrCode); - String extracted_address = null; - if (result != null) + //if barcode is still null, ensure we don't GPF + if (qrCode == null) { - extracted_address = result.getAddress(); - switch (result.getProtocol()) - { - case "address": - addressInput.setAddress(extracted_address); - break; - case "ethereum": - //EIP681 protocol - validateEIP681Request(result, false); - break; - default: - displayScanError(); - break; - } + //Toast.makeText(this, R.string.toast_qr_code_no_address, Toast.LENGTH_SHORT).show(); + displayScanError(); + return; } - else //try magiclink + else { - ParseMagicLink magicParser = new ParseMagicLink(new CryptoFunctions(), EthereumNetworkRepository.extraChains()); - try + QRParser parser = QRParser.getInstance(EthereumNetworkBase.extraChains()); + QRResult result = parser.parse(qrCode); + String extracted_address = null; + if (result != null) { - if (magicParser.parseUniversalLink(qrCode).chainId > 0) //see if it's a valid link + extracted_address = result.getAddress(); + switch (result.getProtocol()) { - //let's try to import the link - viewModel.showImportLink(this, qrCode); - finish(); - return; + case "address": + addressInput.setAddress(extracted_address); + break; + case "ethereum": + //EIP681 protocol + validateEIP681Request(result, false); + break; + default: + break; } } - catch (SalesOrderMalformed e) + else //try magiclink { - e.printStackTrace(); + ParseMagicLink magicParser = new ParseMagicLink(new CryptoFunctions(), EthereumNetworkRepository.extraChains()); + try + { + if (magicParser.parseUniversalLink(qrCode).chainId > 0) //see if it's a valid link + { + //let's try to import the link + viewModel.showImportLink(this, qrCode); + finish(); + return; + } + } + catch (SalesOrderMalformed e) + { + e.printStackTrace(); + } } - } - if (extracted_address == null) - { - displayScanError(); + if (extracted_address == null) + { + displayScanError(); + } } } - } - break; - case QRScannerActivity.DENY_PERMISSION: - showCameraDenied(); - break; - default: - Timber.tag("SEND").e(String.format(getString(R.string.barcode_error_format), - "Code: " + resultCode - )); - break; + break; + case QRScannerActivity.DENY_PERMISSION: + showCameraDenied(); + break; + default: + Timber.tag("SEND").e(String.format(getString(R.string.barcode_error_format), + "Code: " + resultCode + )); + break; + } + } + else + { + super.onActivityResult(requestCode, resultCode, data); } - } - else - { - super.onActivityResult(requestCode, resultCode, data); } } diff --git a/app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java b/app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java index 68016c92b6..7f7d525f08 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TransactionDetailActivity.java @@ -1,5 +1,10 @@ package com.alphawallet.app.ui; +import static com.alphawallet.app.C.Key.WALLET; +import static com.alphawallet.app.ui.widget.holder.TransactionHolder.TRANSACTION_BALANCE_PRECISION; +import static com.alphawallet.app.widget.AWalletAlertDialog.ERROR; +import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; + import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; @@ -25,6 +30,7 @@ import com.alphawallet.app.entity.Transaction; import com.alphawallet.app.entity.TransactionData; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; @@ -34,7 +40,6 @@ import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.ActionSheetDialog; -import com.alphawallet.app.entity.analytics.ActionSheetMode; import com.alphawallet.app.widget.ChainName; import com.alphawallet.app.widget.CopyTextView; import com.alphawallet.app.widget.FunctionButtonBar; @@ -42,22 +47,16 @@ import com.alphawallet.app.widget.TokenIcon; import com.alphawallet.token.tools.Numeric; +import org.web3j.crypto.Keys; + import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import timber.log.Timber; - -import static com.alphawallet.app.C.Key.WALLET; -import static com.alphawallet.app.ui.widget.holder.TransactionHolder.TRANSACTION_BALANCE_PRECISION; -import static com.alphawallet.app.widget.AWalletAlertDialog.ERROR; -import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; - -import org.web3j.crypto.Keys; - import dagger.hilt.android.AndroidEntryPoint; +import timber.log.Timber; @AndroidEntryPoint public class TransactionDetailActivity extends BaseActivity implements StandardFunctionInterface, ActionSheetCallback diff --git a/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java b/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java index 0c23a8d980..b4bf33b8f6 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TransferNFTActivity.java @@ -268,7 +268,6 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) break; } break; - case C.COMPLETED_TRANSACTION: Intent i = new Intent(); i.putExtra(C.EXTRA_TXHASH, data.getStringExtra(C.EXTRA_TXHASH)); diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java index 0af50cb176..b51293b3f3 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java @@ -46,6 +46,7 @@ import com.alphawallet.app.repository.SignRecord; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.viewmodel.WalletConnectViewModel; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.alphawallet.app.walletconnect.WCClient; import com.alphawallet.app.walletconnect.WCSession; import com.alphawallet.app.walletconnect.entity.WCEthereumSignMessage; @@ -76,6 +77,8 @@ import java.util.Collections; import java.util.UUID; +import javax.inject.Inject; + import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; @@ -130,6 +133,10 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa private String signData; private WCEthereumSignMessage.WCSignType signType; private long chainIdOverride; + + @Inject + AWWalletConnectClient awWalletConnectClient; + ActivityResultLauncher getNetwork = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getData() == null) return; @@ -980,6 +987,7 @@ private void killSession() viewModel.track(Analytics.Action.WALLET_CONNECT_SESSION_ENDED); client.killSession(); viewModel.disconnectSession(this, client.sessionId()); + awWalletConnectClient.updateNotification(); handler.postDelayed(this::finish, 5000); } else @@ -1321,7 +1329,7 @@ public void DAppReturn(byte[] data, Signable message) } }; - viewModel.signTransaction(getBaseContext(), tx, dappFunction, peerUrl.getText().toString(), viewModel.getChainId(getSessionId())); + viewModel.signTransaction(getBaseContext(), tx, dappFunction, peerUrl.getText().toString(), viewModel.getChainId(getSessionId()), viewModel.defaultWallet().getValue()); if (fromDappBrowser) switchToDappBrowser(); } diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectNotificationActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectNotificationActivity.java new file mode 100644 index 0000000000..8f1b7acd35 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectNotificationActivity.java @@ -0,0 +1,52 @@ +package com.alphawallet.app.ui; + +import android.content.Intent; +import android.os.Bundle; + +import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; +import com.alphawallet.app.interact.WalletConnectInteract; + +import java.util.List; + +import javax.inject.Inject; + +import androidx.annotation.Nullable; + +import dagger.hilt.android.AndroidEntryPoint; + +/** + * This activity is created to simplify notification click event, according to sessions count, when: + * 1: to session details + * more than 1: to sessions list + */ +@AndroidEntryPoint +public class WalletConnectNotificationActivity extends BaseActivity +{ + @Inject + WalletConnectInteract walletConnectInteract; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + route(); + finish(); + } + + private void route() + { + Intent intent; + List sessions = walletConnectInteract.getSessions(); + if (sessions.size() == 1) + { + intent = WalletConnectSessionActivity.newIntent(getApplicationContext(), sessions.get(0)); + } + else + { + intent = new Intent(getApplicationContext(), WalletConnectSessionActivity.class); + } + + startActivity(intent); + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java index 1bf38a4b49..e5f8986736 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java @@ -1,6 +1,6 @@ package com.alphawallet.app.ui; -import static com.alphawallet.app.C.Key.WALLET; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import android.content.BroadcastReceiver; import android.content.Context; @@ -21,6 +21,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.PopupMenu; import androidx.lifecycle.ViewModelProvider; import androidx.localbroadcastmanager.content.LocalBroadcastManager; @@ -30,17 +31,19 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.analytics.Analytics; -import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.entity.analytics.QrScanSource; import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; +import com.alphawallet.app.entity.walletconnect.WalletConnectV2SessionItem; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.ui.QRScanning.QRScannerActivity; +import com.alphawallet.app.ui.widget.divider.ListDivider; import com.alphawallet.app.viewmodel.WalletConnectViewModel; -import com.alphawallet.app.widget.AWalletAlertDialog; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.bumptech.glide.Glide; import java.util.List; +import javax.inject.Inject; + import dagger.hilt.android.AndroidEntryPoint; import timber.log.Timber; @@ -58,9 +61,7 @@ public class WalletConnectSessionActivity extends BaseActivity private Button btnConnectWallet; private LinearLayout layoutNoActiveSessions; private CustomAdapter adapter; - private Wallet wallet; private List wcSessions; - private int connectionCount = -1; private final BroadcastReceiver walletConnectChangeReceiver = new BroadcastReceiver() { @Override @@ -70,11 +71,13 @@ public void onReceive(Context context, Intent intent) if (action.equals(C.WALLET_CONNECT_COUNT_CHANGE)) { handler.post(() -> adapter.notifyDataSetChanged()); - connectionCount = intent.getIntExtra("count", 0); } } }; + @Inject + AWWalletConnectClient awWalletConnectClient; + public WalletConnectSessionActivity() { broadcastManager = LocalBroadcastManager.getInstance(getApplicationContext()); @@ -84,13 +87,14 @@ public WalletConnectSessionActivity() protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_wallet_connect_sessions); toolbar(); setTitle(getString(R.string.title_wallet_connect)); - wallet = getIntent().getParcelableExtra(WALLET); initViewModel(); + recyclerView = findViewById(R.id.list); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.addItemDecoration(new ListDivider(this)); layoutNoActiveSessions = findViewById(R.id.layout_no_sessions); btnConnectWallet = findViewById(R.id.btn_connect_wallet); btnConnectWallet.setOnClickListener(v -> openQrScanner()); @@ -130,38 +134,38 @@ private void setupList() { wcSessions = viewModel.getSessions(); - if (wcSessions != null) + layoutNoActiveSessions.setVisibility(View.VISIBLE); + if (wcSessions.isEmpty()) { - if (wcSessions.isEmpty()) + layoutNoActiveSessions.setVisibility(View.VISIBLE); + // remove ghosting when all items deleted + if (recyclerView != null) { - layoutNoActiveSessions.setVisibility(View.VISIBLE); - // remove ghosting when all items deleted - if (recyclerView != null) + RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter != null) { - RecyclerView.Adapter adapter = recyclerView.getAdapter(); - if (adapter != null) - { - adapter.notifyDataSetChanged(); - } + adapter.notifyDataSetChanged(); } } - else - { - layoutNoActiveSessions.setVisibility(View.GONE); - recyclerView = findViewById(R.id.list); - recyclerView.setLayoutManager(new LinearLayoutManager(this)); - adapter = new CustomAdapter(); - recyclerView.setAdapter(adapter); - adapter.notifyDataSetChanged(); - } } + else + { + layoutNoActiveSessions.setVisibility(View.GONE); + recyclerView = findViewById(R.id.list); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + adapter = new CustomAdapter(); + recyclerView.setAdapter(adapter); + adapter.notifyDataSetChanged(); + } + + adapter = new CustomAdapter(); + recyclerView.setAdapter(adapter); } @Override public void onResume() { super.onResume(); - connectionCount = -1; initViewModel(); setupList(); startConnectionCheck(); @@ -199,8 +203,6 @@ else if (item.getItemId() == R.id.action_delete) private void openQrScanner() { Intent intent = new Intent(this, QRScannerActivity.class); - intent.putExtra("wallet", wallet); - intent.putExtra(QrScanSource.KEY, QrScanSource.WALLET_CONNECT.getValue()); intent.putExtra(C.EXTRA_UNIVERSAL_SCAN, true); startActivity(intent); } @@ -245,16 +247,27 @@ private void setupClient(final String sessionId, final CustomAdapter.CustomViewH private void dialogConfirmDelete(WalletConnectSessionItem session) { - AWalletAlertDialog dialog = new AWalletAlertDialog(this); - dialog.setTitle(R.string.title_delete_session); - dialog.setMessage(getString(R.string.delete_session, session.name)); - dialog.setButton(R.string.delete, v -> { - dialog.dismiss(); - viewModel.deleteSession(session.sessionId); - setupList(); - }); - dialog.setSecondaryButton(R.string.action_cancel, v -> dialog.dismiss()); - dialog.setCancelable(false); + AlertDialog.Builder builder = new AlertDialog.Builder(this); + AlertDialog dialog = builder.setTitle(R.string.title_delete_session) + .setMessage(getString(R.string.delete_session, session.name)) + .setPositiveButton(R.string.delete, (d, w) -> { + viewModel.deleteSession(session, new AWWalletConnectClient.WalletConnectV2Callback() + { + @Override + public void onSessionDisconnected() + { + runOnUiThread(() -> { + setupList(); + awWalletConnectClient.updateNotification(); + }); + } + }); + }) + .setNegativeButton(R.string.action_cancel, (d, w) -> { + d.dismiss(); + }) + .setCancelable(false) + .create(); dialog.show(); } @@ -292,10 +305,8 @@ public void onBindViewHolder(CustomAdapter.CustomViewHolder holder, int position holder.peerUrl.setText(session.url); holder.chainIcon.setImageResource(EthereumNetworkRepository.getChainLogo(session.chainId)); holder.clickLayer.setOnClickListener(v -> { - //go to wallet connect session page - Intent intent = new Intent(getApplication(), WalletConnectActivity.class); - intent.putExtra("session", session.sessionId); - startActivity(intent); + Context context = getApplicationContext(); + context.startActivity(newIntent(context, session)); }); setupClient(session.sessionId, holder); @@ -336,4 +347,21 @@ class CustomViewHolder extends RecyclerView.ViewHolder } } } + + public static Intent newIntent(Context context, WalletConnectSessionItem session) + { + Intent intent; + if (session instanceof WalletConnectV2SessionItem) + { + intent = new Intent(context, WalletConnectV2Activity.class); + intent.putExtra("session", (WalletConnectV2SessionItem) session); + } + else + { + intent = new Intent(context, WalletConnectActivity.class); + intent.putExtra("session", session.sessionId); + } + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); + return intent; + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java new file mode 100644 index 0000000000..6446be8d24 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java @@ -0,0 +1,377 @@ +package com.alphawallet.app.ui; + +import static java.util.stream.Collectors.toList; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.NetworkInfo; +import com.alphawallet.app.entity.StandardFunctionInterface; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.walletconnect.NamespaceParser; +import com.alphawallet.app.entity.walletconnect.WalletConnectV2SessionItem; +import com.alphawallet.app.ui.widget.adapter.ChainAdapter; +import com.alphawallet.app.ui.widget.adapter.MethodAdapter; +import com.alphawallet.app.ui.widget.adapter.WalletAdapter; +import com.alphawallet.app.util.LayoutHelper; +import com.alphawallet.app.viewmodel.SelectNetworkFilterViewModel; +import com.alphawallet.app.viewmodel.WalletConnectV2ViewModel; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; +import com.alphawallet.app.widget.AWalletAlertDialog; +import com.alphawallet.app.widget.FunctionButtonBar; +import com.bumptech.glide.Glide; +import com.walletconnect.sign.client.Sign; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.inject.Inject; + +import dagger.hilt.android.AndroidEntryPoint; + +@AndroidEntryPoint +public class WalletConnectV2Activity extends BaseActivity implements StandardFunctionInterface, AWWalletConnectClient.WalletConnectV2Callback +{ + @Inject + AWWalletConnectClient awWalletConnectClient; + private WalletConnectV2ViewModel viewModel; + private SelectNetworkFilterViewModel selectNetworkFilterViewModel; + + private ImageView icon; + private TextView peerName; + private TextView peerUrl; + private ProgressBar progressBar; + private LinearLayout infoLayout; + private FunctionButtonBar functionBar; + private ListView chainList; + private ListView walletList; + private ListView methodList; + + private WalletConnectV2SessionItem session; + private WalletAdapter walletAdapter; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_wallet_connect_v2); + toolbar(); + setTitle(getString(R.string.title_wallet_connect)); + initViews(); + + String url = retrieveUrl(); + if (!TextUtils.isEmpty(url)) + { + progressBar.setVisibility(View.VISIBLE); + awWalletConnectClient.pair(url, (msg) -> { + if (TextUtils.isEmpty(msg)) + { + return; + } + new Handler().post(() -> { + Toast.makeText(WalletConnectV2Activity.this, msg, Toast.LENGTH_SHORT).show(); + finish(); + }); + }); + return; + } + + this.session = retrieveSession(getIntent()); + initViewModel(); + } + + @Override + protected void onNewIntent(Intent intent) + { + super.onNewIntent(intent); + this.session = retrieveSession(intent); + initViewModel(); + } + + private String retrieveUrl() + { + return getIntent().getStringExtra("url"); + } + + private WalletConnectV2SessionItem retrieveSession(Intent intent) + { + return intent.getParcelableExtra("session"); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider(this) + .get(WalletConnectV2ViewModel.class); + + viewModel.wallets().observe(this, this::onWalletsFetched); + viewModel.defaultWallet().observe(this, this::onDefaultWallet); + + selectNetworkFilterViewModel = new ViewModelProvider(this) + .get(SelectNetworkFilterViewModel.class); + } + + private void onWalletsFetched(Wallet[] wallets) + { + tryDisplaySessionStatus(); + } + + private void tryDisplaySessionStatus() + { + if (viewModel.wallets().getValue() != null && viewModel.defaultWallet().getValue() != null) + { + displaySessionStatus(session); + progressBar.setVisibility(View.GONE); + functionBar.setVisibility(View.VISIBLE); + infoLayout.setVisibility(View.VISIBLE); + } + } + + private void onDefaultWallet(Wallet wallet) + { + tryDisplaySessionStatus(); + } + + private void displaySessionStatus(WalletConnectV2SessionItem session) + { + if (session.icon == null) + { + icon.setImageResource(R.drawable.ic_coin_eth_small); + } + else + { + Glide.with(this) + .load(session.icon) + .circleCrop() + .into(icon); + } + peerName.setText(session.name); + peerUrl.setText(session.url); + + chainList.setAdapter(new ChainAdapter(this, session.chains)); + if (session.settled) + { + walletAdapter = new WalletAdapter(this, findWallets(session.wallets)); + } + else + { + walletAdapter = new WalletAdapter(this, viewModel.wallets().getValue(), viewModel.defaultWallet().getValue()); + } + walletList.setAdapter(walletAdapter); + methodList.setAdapter(new MethodAdapter(this, session.methods)); + resizeList(); + + if (session.settled) + { + functionBar.setupFunctions(new StandardFunctionInterface() + { + @Override + public void handleClick(String action, int actionId) + { + endSessionDialog(); + } + }, Collections.singletonList(R.string.action_end_session)); + } + else + { + functionBar.setupFunctions(new StandardFunctionInterface() + { + @Override + public void handleClick(String action, int actionId) + { + if (actionId == R.string.dialog_approve) + { + approve(AWWalletConnectClient.sessionProposal); + } + else + { + reject(AWWalletConnectClient.sessionProposal); + } + } + }, Arrays.asList(R.string.dialog_approve, R.string.dialog_reject)); + } + + } + + private List findWallets(List addresses) + { + List result = new ArrayList<>(); + Map map = toMap(Objects.requireNonNull(viewModel.wallets().getValue())); + for (String address : addresses) + { + Wallet wallet = map.get(address); + if (wallet == null) + { + wallet = new Wallet(address); + } + result.add(wallet); + } + return result; + } + + private Map toMap(Wallet[] wallets) + { + HashMap map = new HashMap<>(); + for (Wallet wallet : wallets) + { + map.put(wallet.address, wallet); + } + return map; + } + + private void resizeList() + { + LayoutHelper.resizeList(chainList); + LayoutHelper.resizeList(walletList); + LayoutHelper.resizeList(methodList); + } + + private void initViews() + { + progressBar = findViewById(R.id.progress); + infoLayout = findViewById(R.id.layout_info); + icon = findViewById(R.id.icon); + peerName = findViewById(R.id.peer_name); + peerUrl = findViewById(R.id.peer_url); + chainList = findViewById(R.id.chain_list); + walletList = findViewById(R.id.wallet_list); + methodList = findViewById(R.id.method_list); + + progressBar.setVisibility(View.VISIBLE); + infoLayout.setVisibility(View.GONE); + + functionBar = findViewById(R.id.layoutButtons); + functionBar.setupFunctions(this, Arrays.asList(R.string.dialog_approve, R.string.dialog_reject)); + + functionBar.setVisibility(View.GONE); + } + + private void endSessionDialog() + { + runOnUiThread(() -> + { + + AWalletAlertDialog dialog = new AWalletAlertDialog(this, AWalletAlertDialog.ERROR); + dialog.setTitle(R.string.dialog_title_disconnect_session); + dialog.setButton(R.string.action_close, v -> { + dialog.dismiss(); + killSession(session.sessionId); + }); + dialog.setSecondaryButton(R.string.action_cancel, v -> dialog.dismiss()); + dialog.setCancelable(false); + dialog.show(); + }); + } + + private void killSession(String sessionId) + { + awWalletConnectClient.disconnect(sessionId, this); + } + + private void reject(Sign.Model.SessionProposal sessionProposal) + { + awWalletConnectClient.reject(sessionProposal, this); + } + + private void approve(Sign.Model.SessionProposal sessionProposal) + { + List disabledNetworks = disabledNetworks(sessionProposal.getRequiredNamespaces()); + if (disabledNetworks.isEmpty()) + { + awWalletConnectClient.approve(sessionProposal, getSelectedAccounts(), this); + } + else + { + showDialog(disabledNetworks); + } + } + + private void showDialog(List disabledNetworks) + { + AWalletAlertDialog dialog = new AWalletAlertDialog(this); + dialog.setMessage(String.format(getString(R.string.network_must_be_enabled), joinNames(disabledNetworks))); + dialog.setButton(R.string.select_active_networks, view -> { + Intent intent = new Intent(this, SelectNetworkFilterActivity.class); + startActivity(intent); + dialog.dismiss(); + }); + dialog.setSecondaryButton(R.string.action_cancel, (view) -> dialog.dismiss()); + dialog.show(); + } + + @NonNull + private String joinNames(List disabledNetworks) + { + return disabledNetworks.stream() + .map((chainId) -> { + NetworkInfo network = selectNetworkFilterViewModel.getNetworkByChain(chainId); + if (network != null) + { + return network.name; + } + return String.valueOf(chainId); + }) + .collect(Collectors.joining(", ")); + } + + private List disabledNetworks(Map requiredNamespaces) + { + NamespaceParser namespaceParser = new NamespaceParser(); + namespaceParser.parseProposal(requiredNamespaces); + List enabledChainIds = selectNetworkFilterViewModel.getActiveNetworks(); + List result = new ArrayList<>(); + List chains = namespaceParser.getChains().stream().map((s) -> Long.parseLong(s.split(":")[1])).collect(toList()); + for (Long chainId : chains) + { + if (!enabledChainIds.contains(chainId)) + { + result.add(chainId); + } + } + return result; + } + + private List getSelectedAccounts() + { + return walletAdapter.getSelectedWallets().stream() + .map((wallet) -> wallet.address).collect(toList()); + } + + @Override + public void onSessionProposalApproved() + { + finish(); + } + + @Override + public void onSessionProposalRejected() + { + finish(); + } + + @Override + public void onSessionDisconnected() + { + finish(); + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java index 53b51f98d7..8c01d10254 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java @@ -41,12 +41,14 @@ import com.alphawallet.app.R; import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.BackupOperationType; +import com.alphawallet.app.entity.BackupTokenCallback; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.ServiceSyncCallback; import com.alphawallet.app.entity.TokenFilter; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.WalletPage; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; @@ -64,6 +66,7 @@ import com.alphawallet.app.ui.widget.holder.WarningHolder; import com.alphawallet.app.util.LocaleUtils; import com.alphawallet.app.viewmodel.WalletViewModel; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.alphawallet.app.widget.BuyEthOptionsView; import com.alphawallet.app.widget.LargeTitleView; import com.alphawallet.app.widget.NotificationView; @@ -76,8 +79,11 @@ import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import javax.inject.Inject; + import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; @@ -113,10 +119,19 @@ public class WalletFragment extends BaseFragment implements private RealmResults realmUpdates; private LargeTitleView largeTitleView; private long realmUpdateTime; - private ActivityResultLauncher networkSettingsHandler; private ActivityResultLauncher handleBackupClick; private ActivityResultLauncher tokenManagementLauncher; + @Inject + AWWalletConnectClient awWalletConnectClient; + + private ActivityResultLauncher networkSettingsHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> + { + //send instruction to restart tokenService + getParentFragmentManager().setFragmentResult(RESET_TOKEN_SERVICE, new Bundle()); + }); + @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) @@ -234,6 +249,9 @@ private void initViewModel() viewModel.defaultWallet().observe(getViewLifecycleOwner(), this::onDefaultWallet); viewModel.onFiatValues().observe(getViewLifecycleOwner(), this::updateValue); viewModel.getTokensService().startWalletSync(this); + viewModel.activeWalletConnectSessions().observe(getViewLifecycleOwner(), walletConnectSessionItems -> { + adapter.showActiveWalletConnectSessions(walletConnectSessionItems); + }); } private void initViews(@NonNull View view) @@ -390,6 +408,7 @@ private void refreshList() adapter.clear(); viewModel.prepare(); viewModel.notifyRefresh(); + awWalletConnectClient.updateNotification(); }); } @@ -582,6 +601,15 @@ private void onTokens(TokenCardMeta[] tokens) { setRealmListener(realmUpdateTime); } + + if (currentTabPos.equals(TokenFilter.ALL)) + { + awWalletConnectClient.updateNotification(); + } + else + { + adapter.showActiveWalletConnectSessions(Collections.emptyList()); + } } /** @@ -737,7 +765,7 @@ public void remindMeLater(Wallet wallet) handler.post(() -> { if (viewModel != null) viewModel.setKeyWarningDismissTime(wallet.address); - if (adapter != null) adapter.removeBackupWarning(); + if (adapter != null) adapter.removeItem(WarningHolder.VIEW_TYPE); }); } @@ -747,7 +775,7 @@ public void storeWalletBackupTime(String backedUpKey) handler.post(() -> { if (viewModel != null) viewModel.setKeyBackupTime(backedUpKey); - if (adapter != null) adapter.removeBackupWarning(); + if (adapter != null) adapter.removeItem(WarningHolder.VIEW_TYPE); }); } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainAdapter.java new file mode 100644 index 0000000000..27329f7e25 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainAdapter.java @@ -0,0 +1,45 @@ +package com.alphawallet.app.ui.widget.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; + +import com.alphawallet.app.R; +import com.alphawallet.app.repository.EthereumNetworkRepository; +import com.alphawallet.app.walletconnect.util.WalletConnectHelper; +import com.alphawallet.app.widget.ChainName; + +import java.util.List; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class ChainAdapter extends ArrayAdapter +{ + public ChainAdapter(Context context, List chains) + { + super(context, 0, chains); + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) + { + long chainId = WalletConnectHelper.getChainId(getItem(position)); + if (convertView == null) + { + convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_chain, parent, false); + } + + ChainName chainName = convertView.findViewById(R.id.chain_name); + ImageView chainIcon = convertView.findViewById(R.id.chain_icon); + + chainName.setChainID(chainId); + chainIcon.setImageResource(EthereumNetworkRepository.getChainLogo(chainId)); + + return convertView; + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MethodAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MethodAdapter.java new file mode 100644 index 0000000000..e15db09a8e --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MethodAdapter.java @@ -0,0 +1,38 @@ +package com.alphawallet.app.ui.widget.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import com.alphawallet.app.R; + +import java.util.List; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class MethodAdapter extends ArrayAdapter +{ + public MethodAdapter(@NonNull Context context, List methods) + { + super(context, 0, methods); + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) + { + if (convertView == null) + { + convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_method, parent, false); + } + + TextView methodName = convertView.findViewById(R.id.tv_method_name); + + methodName.setText(getItem(position)); + return convertView; + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java index 7d397e65ee..9972fe894a 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java @@ -3,17 +3,13 @@ import android.content.Intent; import android.view.ViewGroup; -import androidx.activity.result.ActivityResultLauncher; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.SortedList; - import com.alphawallet.app.R; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.TokenFilter; import com.alphawallet.app.entity.tokendata.TokenGroup; import com.alphawallet.app.entity.tokens.TokenCardMeta; +import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; import com.alphawallet.app.repository.TokensMappingRepository; import com.alphawallet.app.repository.TokensRealmSource; import com.alphawallet.app.service.AssetDefinitionService; @@ -28,6 +24,7 @@ import com.alphawallet.app.ui.widget.entity.TestNetTipsItem; import com.alphawallet.app.ui.widget.entity.TokenSortedItem; import com.alphawallet.app.ui.widget.entity.TotalBalanceSortedItem; +import com.alphawallet.app.ui.widget.entity.WalletConnectSessionSortedItem; import com.alphawallet.app.ui.widget.entity.WarningData; import com.alphawallet.app.ui.widget.entity.WarningSortedItem; import com.alphawallet.app.ui.widget.holder.AssetInstanceScriptHolder; @@ -40,13 +37,20 @@ import com.alphawallet.app.ui.widget.holder.TokenGridHolder; import com.alphawallet.app.ui.widget.holder.TokenHolder; import com.alphawallet.app.ui.widget.holder.TotalBalanceHolder; +import com.alphawallet.app.ui.widget.holder.WalletConnectSessionHolder; import com.alphawallet.app.ui.widget.holder.WarningHolder; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; -public class TokensAdapter extends RecyclerView.Adapter { +import androidx.activity.result.ActivityResultLauncher; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SortedList; + +public class TokensAdapter extends RecyclerView.Adapter +{ private static final String TAG = "TKNADAPTER"; private TokenFilter filterType = TokenFilter.ALL; @@ -62,39 +66,47 @@ public class TokensAdapter extends RecyclerView.Adapter { private boolean showTestNetTips = false; protected final TokensAdapterCallback tokensAdapterCallback; - protected final SortedList items = new SortedList<>(SortedItem.class, new SortedList.Callback() { + protected final SortedList items = new SortedList<>(SortedItem.class, new SortedList.Callback() + { @Override - public int compare(SortedItem o1, SortedItem o2) { + public int compare(SortedItem o1, SortedItem o2) + { return o1.compare(o2); } @Override - public void onChanged(int position, int count) { + public void onChanged(int position, int count) + { notifyItemRangeChanged(position, count); } @Override - public boolean areContentsTheSame(SortedItem oldItem, SortedItem newItem) { + public boolean areContentsTheSame(SortedItem oldItem, SortedItem newItem) + { return oldItem.areContentsTheSame(newItem); } @Override - public boolean areItemsTheSame(SortedItem item1, SortedItem item2) { + public boolean areItemsTheSame(SortedItem item1, SortedItem item2) + { return item1.areItemsTheSame(item2); } @Override - public void onInserted(int position, int count) { + public void onInserted(int position, int count) + { notifyItemRangeInserted(position, count); } @Override - public void onRemoved(int position, int count) { + public void onRemoved(int position, int count) + { notifyItemRangeRemoved(position, count); } @Override - public void onMoved(int fromPosition, int toPosition) { + public void onMoved(int fromPosition, int toPosition) + { notifyItemMoved(fromPosition, toPosition); } }); @@ -113,7 +125,8 @@ public TokensAdapter(TokensAdapterCallback tokensAdapterCallback, AssetDefinitio new TokensMappingRepository(aService.getTokenLocalSource()); } - protected TokensAdapter(TokensAdapterCallback tokensAdapterCallback, AssetDefinitionService aService) { + protected TokensAdapter(TokensAdapterCallback tokensAdapterCallback, AssetDefinitionService aService) + { this.tokensAdapterCallback = tokensAdapterCallback; this.assetService = aService; this.tokensService = null; @@ -126,14 +139,17 @@ protected TokensAdapter(TokensAdapterCallback tokensAdapterCallback, AssetDefini public long getItemId(int position) { Object obj = items.get(position); - if (obj instanceof TokenSortedItem) { + if (obj instanceof TokenSortedItem) + { TokenCardMeta tcm = ((TokenSortedItem) obj).value; - // This is an attempt to obtain a 'unique' id - // to fully utilise the RecyclerView's setHasStableIds feature. - // This will drastically reduce 'blinking' when the list changes + // This is an attempt to obtain a 'unique' id + // to fully utilise the RecyclerView's setHasStableIds feature. + // This will drastically reduce 'blinking' when the list changes return tcm.getUID(); - } else { + } + else + { return position; } } @@ -180,6 +196,10 @@ public BinderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int vie holder = new WarningHolder(R.layout.item_warning, parent); break; + case WalletConnectSessionHolder.VIEW_TYPE: + holder = new WalletConnectSessionHolder(R.layout.item_wallet_connect_sessions, parent); + break; + case AssetInstanceScriptHolder.VIEW_TYPE: holder = new AssetInstanceScriptHolder(R.layout.item_ticket, parent, null, assetService, false); break; @@ -188,7 +208,7 @@ public BinderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int vie holder = new ChainNameHeaderHolder(R.layout.item_chainname_header, parent); break; - // NB to save ppl a lot of effort this view doesn't show - item_total_balance has height coded to 1dp. + // NB to save ppl a lot of effort this view doesn't show - item_total_balance has height coded to 1dp. case TotalBalanceHolder.VIEW_TYPE: default: holder = new TotalBalanceHolder(R.layout.item_total_balance, parent); @@ -206,7 +226,7 @@ public void onBindViewHolder(BinderViewHolder holder, int position) public void onRViewRecycled(RecyclerView.ViewHolder holder) { - ((BinderViewHolder)holder).onDestroyView(); + ((BinderViewHolder) holder).onDestroyView(); } @Override @@ -229,17 +249,20 @@ public int getItemViewType(int position) } @Override - public int getItemCount() { + public int getItemCount() + { return items.size(); } - public void setWalletAddress(String walletAddress) { + public void setWalletAddress(String walletAddress) + { this.walletAddress = walletAddress; } private void addSearchTokensLayout() { - if (walletAddress != null && !walletAddress.isEmpty()) { + if (walletAddress != null && !walletAddress.isEmpty()) + { items.add(new ManageTokensSearchItem(new ManageTokensData(walletAddress, managementLauncher), -1)); } } @@ -254,7 +277,8 @@ private void addHeaderLayout(TokenCardMeta tcm) private void addManageTokensLayout() { if (walletAddress != null && !walletAddress.isEmpty() && tokensService.isMainNetActive() - && (filterType == TokenFilter.ALL || filterType == TokenFilter.ASSETS)) { //only show buy button if filtering all or assets + && (filterType == TokenFilter.ALL || filterType == TokenFilter.ASSETS)) + { //only show buy button if filtering all or assets items.add(new ManageTokensSortedItem(new ManageTokensData(walletAddress, managementLauncher))); } } @@ -264,19 +288,6 @@ public void addWarning(WarningData data) items.add(new WarningSortedItem(data, 1)); } - public void removeBackupWarning() - { - for (int i = 0; i < items.size(); i++) - { - if (items.get(i).viewType == WarningHolder.VIEW_TYPE) - { - items.removeItemAt(i); - notifyItemRemoved(i); - break; - } - } - } - public void setTokens(TokenCardMeta[] tokens) { populateTokens(tokens, false); @@ -338,12 +349,15 @@ private void removeMatchingTokenDifferentWeight(TokenCardMeta token) public void removeToken(TokenCardMeta token) { - for (int i = 0; i < items.size(); i++) { + for (int i = 0; i < items.size(); i++) + { Object si = items.get(i); - if (si instanceof TokenSortedItem) { + if (si instanceof TokenSortedItem) + { TokenSortedItem tsi = (TokenSortedItem) si; TokenCardMeta thisToken = tsi.value; - if (thisToken.tokenId.equalsIgnoreCase(token.tokenId)) { + if (thisToken.tokenId.equalsIgnoreCase(token.tokenId)) + { items.removeItemAt(i); break; } @@ -354,12 +368,15 @@ public void removeToken(TokenCardMeta token) public void removeToken(long chainId, String tokenAddress) { String id = TokensRealmSource.databaseKey(chainId, tokenAddress); - for (int i = 0; i < items.size(); i++) { + for (int i = 0; i < items.size(); i++) + { Object si = items.get(i); - if (si instanceof TokenSortedItem) { + if (si instanceof TokenSortedItem) + { TokenSortedItem tsi = (TokenSortedItem) si; TokenCardMeta thisToken = tsi.value; - if (thisToken.tokenId.equalsIgnoreCase(id)) { + if (thisToken.tokenId.equalsIgnoreCase(id)) + { items.removeItemAt(i); break; } @@ -412,7 +429,8 @@ private boolean checkTokenValue(TokenCardMeta token, boolean allowThroughFilter) private void populateTokens(TokenCardMeta[] tokens, boolean clear) { items.beginBatchedUpdates(); - if (clear) { + if (clear) + { items.clear(); } @@ -447,7 +465,7 @@ public void setTotal(BigDecimal totalInCurrency) Object si = items.get(i); if (si instanceof TotalBalanceSortedItem) { - items.remove((TotalBalanceSortedItem)si); + items.remove((TotalBalanceSortedItem) si); items.add(total); notifyItemChanged(i); break; @@ -518,8 +536,8 @@ public int getScrollPosition() Object si = items.get(i); if (si instanceof TokenSortedItem) { - TokenSortedItem tsi = (TokenSortedItem) si; - TokenCardMeta token = tsi.value; + TokenSortedItem tsi = (TokenSortedItem) si; + TokenCardMeta token = tsi.value; if (scrollToken.equals(token)) { scrollToken = null; @@ -574,4 +592,29 @@ public List getSelected() return selected; } + + public void showActiveWalletConnectSessions(List sessions) + { + if (sessions.isEmpty()) + { + removeItem(WalletConnectSessionHolder.VIEW_TYPE); + } + else + { + items.add(new WalletConnectSessionSortedItem(sessions, 2)); + } + } + + public void removeItem(int viewType) + { + for (int i = 0; i < items.size(); i++) + { + if (items.get(i).viewType == viewType) + { + items.removeItemAt(i); + notifyItemRemoved(i); + break; + } + } + } } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletAdapter.java new file mode 100644 index 0000000000..6515965454 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletAdapter.java @@ -0,0 +1,133 @@ +package com.alphawallet.app.ui.widget.adapter; + +import android.content.Context; +import android.graphics.Paint; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.WalletType; +import com.alphawallet.app.widget.UserAvatar; +import com.google.android.material.checkbox.MaterialCheckBox; + +import java.util.ArrayList; +import java.util.List; + +public class WalletAdapter extends ArrayAdapter +{ + private Wallet defaultWallet; + private boolean[] selected; + private boolean readOnly; + + public WalletAdapter(Context context, Wallet[] wallets, Wallet defaultWallet) + { + super(context, 0, wallets); + selected = new boolean[wallets.length]; + this.defaultWallet = defaultWallet; + } + + public WalletAdapter(Context context, List wallets) + { + super(context, 0, wallets); + readOnly = true; + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) + { + if (convertView == null) + { + convertView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_wallet, parent, false); + + convertView.setTag(new ViewHolder(convertView)); + } + + ViewHolder holder = (ViewHolder) convertView.getTag(); + + Wallet wallet = getItem(position); + + if (TextUtils.isEmpty(wallet.ENSname)) + { + holder.walletName.setVisibility(View.GONE); + holder.walletAddressSeparator.setVisibility(View.GONE); + } + else + { + holder.walletName.setText(wallet.ENSname); + } + holder.walletAddress.setText(wallet.address); + if (wallet.type == WalletType.NOT_DEFINED) + { + holder.walletAddress.setPaintFlags(holder.walletAddress.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + } + holder.userAvatar.bind(wallet); + holder.balance.setText(String.format("%s %s", wallet.balance, wallet.balanceSymbol)); + + if (readOnly) + { + holder.checkbox.setVisibility(View.GONE); + } + else + { + if (wallet.address.equals(defaultWallet.address)) + { + holder.checkbox.setChecked(true); + selected[position] = true; + } + + holder.container.setOnClickListener(v -> + { + holder.checkbox.setChecked(!holder.checkbox.isChecked()); + selected[position] = !selected[position]; + }); + + } + return convertView; + } + + public List getSelectedWallets() + { + List selectedWallets = new ArrayList<>(); + for (int i = 0; i < getCount(); i++) + { + if (selected[i]) + { + selectedWallets.add(getItem(i)); + } + } + return selectedWallets; + } + + static class ViewHolder + { + View container; + TextView walletName; + TextView walletAddress; + TextView balance; + TextView walletAddressSeparator; + UserAvatar userAvatar; + MaterialCheckBox checkbox; + + public ViewHolder(@NonNull View view) + { + container = view; + walletName = view.findViewById(R.id.wallet_name); + walletAddress = view.findViewById(R.id.wallet_address); + balance = view.findViewById(R.id.wallet_balance); + walletAddressSeparator = view.findViewById(R.id.wallet_address_separator); + userAvatar = view.findViewById(R.id.wallet_icon); + checkbox = view.findViewById(R.id.checkbox); + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ChainItem.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ChainItem.java index e77a14606c..2e80b84d2f 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ChainItem.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ChainItem.java @@ -9,7 +9,7 @@ */ public class ChainItem extends SortedItem { - public static long CHAIN_ITEM_WEIGHT = 2; + public static long CHAIN_ITEM_WEIGHT = 4; public ChainItem(Long networkId, TokenGroup group) { super(ChainNameHeaderHolder.VIEW_TYPE, networkId, new TokenPosition(group, networkId, CHAIN_ITEM_WEIGHT)); diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/HeaderItem.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/HeaderItem.java index bdd409d525..44fa9155a0 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/HeaderItem.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/HeaderItem.java @@ -7,7 +7,7 @@ public class HeaderItem extends SortedItem { public HeaderItem(TokenGroup group) { - super(HeaderHolder.VIEW_TYPE, group, new TokenPosition(group, 1, 1, true)); + super(HeaderHolder.VIEW_TYPE, group, new TokenPosition(group, 1, 3, true)); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/WalletConnectSessionSortedItem.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/WalletConnectSessionSortedItem.java new file mode 100644 index 0000000000..b28d84d0b0 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/WalletConnectSessionSortedItem.java @@ -0,0 +1,26 @@ +package com.alphawallet.app.ui.widget.entity; + +import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; +import com.alphawallet.app.ui.widget.holder.WalletConnectSessionHolder; + +import java.util.List; + +public class WalletConnectSessionSortedItem extends SortedItem> +{ + public WalletConnectSessionSortedItem(List sessions, int weight) + { + super(WalletConnectSessionHolder.VIEW_TYPE, sessions, new TokenPosition(weight)); + } + + @Override + public boolean areContentsTheSame(SortedItem newItem) + { + return false; // always override the existed one + } + + @Override + public boolean areItemsTheSame(SortedItem other) + { + return other.viewType == viewType; + } +} diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/holder/WalletConnectSessionHolder.java b/app/src/main/java/com/alphawallet/app/ui/widget/holder/WalletConnectSessionHolder.java new file mode 100644 index 0000000000..01819e438f --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/ui/widget/holder/WalletConnectSessionHolder.java @@ -0,0 +1,37 @@ +package com.alphawallet.app.ui.widget.holder; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; +import com.alphawallet.app.ui.WalletConnectNotificationActivity; + +import java.util.List; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class WalletConnectSessionHolder extends BinderViewHolder> +{ + public static final int VIEW_TYPE = 2024; + private final View container; + + public WalletConnectSessionHolder(int resId, ViewGroup parent) + { + super(resId, parent); + container = findViewById(R.id.layout_item_wallet_connect); + } + + public void bind(@Nullable List sessionItemList, @NonNull Bundle addition) + { + container.setOnClickListener(view -> onClick()); + } + + private void onClick() + { + getContext().startActivity(new Intent(getContext(), WalletConnectNotificationActivity.class)); + } +} diff --git a/app/src/main/java/com/alphawallet/app/util/LayoutHelper.java b/app/src/main/java/com/alphawallet/app/util/LayoutHelper.java new file mode 100644 index 0000000000..b07985887f --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/LayoutHelper.java @@ -0,0 +1,30 @@ +package com.alphawallet.app.util; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListAdapter; +import android.widget.ListView; + +public class LayoutHelper +{ + public static void resizeList(ListView listView) + { + ListAdapter listAdapter = listView.getAdapter(); + if (listAdapter == null) + { + return; + } + //set listAdapter in loop for getting final size + int totalHeight = 0; + for (int size = 0; size < listAdapter.getCount(); size++) + { + View listItem = listAdapter.getView(size, null, listView); + listItem.measure(0, 0); + totalHeight += listItem.getMeasuredHeight(); + } + //setting listview item in adapter + ViewGroup.LayoutParams params = listView.getLayoutParams(); + params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); + listView.setLayoutParams(params); + } +} diff --git a/app/src/main/java/com/alphawallet/app/util/Utils.java b/app/src/main/java/com/alphawallet/app/util/Utils.java index 7aa601cfaa..8e9e071496 100644 --- a/app/src/main/java/com/alphawallet/app/util/Utils.java +++ b/app/src/main/java/com/alphawallet/app/util/Utils.java @@ -215,7 +215,7 @@ public static int getSigningTitle(Signable signable) return R.string.dialog_title_sign_personal_message; case SIGN_TYPED_DATA: case SIGN_TYPED_DATA_V3: - case SIGN_TYPES_DATA_V4: + case SIGN_TYPED_DATA_V4: return R.string.dialog_title_sign_typed_message; } } @@ -891,7 +891,17 @@ public static String loadFile(Context context, @RawRes int rawRes) { Timber.tag("READ_JS_TAG").d(ex, "Ex"); } - return new String(buffer); + + try + { + Timber.tag("READ_JS_TAG").d("HeapSize:%s", Runtime.getRuntime().freeMemory()); + return new String(buffer); + } + catch (Exception e) + { + Timber.tag("READ_JS_TAG").d(e, "Ex"); + } + return ""; } public static long timeUntil(long eventInMillis) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java index 5c67eb2cd1..1e08968eca 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java @@ -10,6 +10,7 @@ import android.webkit.WebView; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -42,7 +43,9 @@ import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.SendActivity; import com.alphawallet.app.ui.WalletConnectActivity; +import com.alphawallet.app.ui.WalletConnectV2Activity; import com.alphawallet.app.util.DappBrowserUtils; +import com.alphawallet.app.walletconnect.util.WalletConnectHelper; import com.alphawallet.app.web3.entity.WalletAddEthereumChainObject; import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.token.entity.Signable; @@ -280,14 +283,14 @@ public void sendTransaction(final Web3Transaction finalTx, long chainId, SendTra { disposable = createTransactionInteract .createWithSig(defaultWallet.getValue(), finalTx.gasPrice, finalTx.gasLimit, finalTx.payload, chainId) - .subscribe(txData -> callback.transactionSuccess(finalTx, txData.txHash), + .subscribe(txData -> callback.transactionSuccess(finalTx, txData.signature), error -> callback.transactionError(finalTx.leafPosition, error)); } else { disposable = createTransactionInteract .createWithSig(defaultWallet.getValue(), finalTx, chainId) - .subscribe(txData -> callback.transactionSuccess(finalTx, txData.txHash), + .subscribe(txData -> callback.transactionSuccess(finalTx, txData.signature), error -> callback.transactionError(finalTx.leafPosition, error)); } } @@ -334,13 +337,37 @@ public void stopBalanceUpdate() } public void handleWalletConnect(Context context, String url, NetworkInfo activeNetwork) + { + Intent intent; + if (WalletConnectHelper.isWalletConnectV1(url)) + { + intent = getIntentOfWalletConnectV1(context, url, activeNetwork); + } + else + { + intent = getIntentOfWalletConnectV2(context, url); + } + + context.startActivity(intent); + } + + @NonNull + private Intent getIntentOfWalletConnectV2(Context context, String url) + { + Intent intent = new Intent(context, WalletConnectV2Activity.class); + intent.putExtra("url", url); + return intent; + } + + @NonNull + private Intent getIntentOfWalletConnectV1(Context context, String url, NetworkInfo activeNetwork) { String importPassData = WalletConnectActivity.WC_LOCAL_PREFIX + url; Intent intent = new Intent(context, WalletConnectActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); intent.putExtra(C.EXTRA_CHAIN_ID, activeNetwork.chainId); intent.putExtra("qrCode", importPassData); - context.startActivity(intent); + return intent; } public TokensService getTokenService() @@ -381,7 +408,7 @@ public boolean addCustomChain(WalletAddEthereumChainObject chainObject) { String rpc = extractRpc(chainObject); if (rpc == null) return false; - + this.ethereumNetworkRepository.saveCustomRPCNetwork(chainObject.chainName, rpc, chainObject.getChainId(), chainObject.nativeCurrency.symbol, extractBlockExplorer(chainObject), "", false, -1L); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SelectNetworkFilterViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SelectNetworkFilterViewModel.java index 5102deb130..6e2bf31043 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SelectNetworkFilterViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SelectNetworkFilterViewModel.java @@ -1,7 +1,6 @@ package com.alphawallet.app.viewmodel; import com.alphawallet.app.entity.NetworkInfo; -import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; import com.alphawallet.app.repository.PreferenceRepositoryType; @@ -110,4 +109,9 @@ public void removeCustomNetwork(long chainId) { public TokensService getTokensService() { return tokensService; } + + public List getActiveNetworks() + { + return networkRepository.getFilterNetworkList(); + } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectV2ViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectV2ViewModel.java new file mode 100644 index 0000000000..9ceac34a04 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectV2ViewModel.java @@ -0,0 +1,65 @@ +package com.alphawallet.app.viewmodel; + +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.interact.FetchWalletsInteract; +import com.alphawallet.app.interact.GenericWalletInteract; + +import javax.inject.Inject; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import dagger.hilt.android.lifecycle.HiltViewModel; + +@HiltViewModel +public class WalletConnectV2ViewModel extends BaseViewModel +{ + private final MutableLiveData wallets = new MutableLiveData<>(); + private final MutableLiveData defaultWallet = new MutableLiveData<>(); + + private final FetchWalletsInteract fetchWalletsInteract; + private final GenericWalletInteract genericWalletInteract; + + public LiveData wallets() + { + return wallets; + } + + @Inject + WalletConnectV2ViewModel(FetchWalletsInteract fetchWalletsInteract, GenericWalletInteract genericWalletInteract) + { + this.fetchWalletsInteract = fetchWalletsInteract; + this.genericWalletInteract = genericWalletInteract; + + fetchWallets(); + fetchDefaultWallet(); + } + + private void fetchDefaultWallet() + { + disposable = genericWalletInteract + .find() + .subscribe(this::onDefaultWallet, this::onError); + } + + private void onDefaultWallet(Wallet wallet) + { + this.defaultWallet.postValue(wallet); + } + + public void fetchWallets() + { + disposable = fetchWalletsInteract + .fetch() + .subscribe(this::onWallets, this::onError); + } + + private void onWallets(Wallet[] wallets) + { + this.wallets.postValue(wallets); + } + + public LiveData defaultWallet() + { + return defaultWallet; + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java index 1ecd7c99ca..807510662e 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java @@ -24,9 +24,12 @@ import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletConnectActions; import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; +import com.alphawallet.app.entity.walletconnect.WalletConnectV2SessionItem; import com.alphawallet.app.interact.CreateTransactionInteract; +import com.alphawallet.app.interact.FetchWalletsInteract; import com.alphawallet.app.interact.FindDefaultNetworkInteract; import com.alphawallet.app.interact.GenericWalletInteract; +import com.alphawallet.app.interact.WalletConnectInteract; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; import com.alphawallet.app.repository.SignRecord; import com.alphawallet.app.repository.entity.RealmWCSession; @@ -37,6 +40,7 @@ import com.alphawallet.app.service.RealmManager; import com.alphawallet.app.service.TokensService; import com.alphawallet.app.service.WalletConnectService; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.alphawallet.app.walletconnect.WCClient; import com.alphawallet.app.walletconnect.WCSession; import com.alphawallet.app.walletconnect.entity.GetClientCallback; @@ -50,6 +54,7 @@ import com.alphawallet.token.entity.Signable; import com.alphawallet.token.tools.Numeric; +import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; @@ -64,7 +69,6 @@ import io.reactivex.schedulers.Schedulers; import io.realm.Realm; import io.realm.RealmResults; -import io.realm.Sort; import timber.log.Timber; @HiltViewModel @@ -77,7 +81,9 @@ public class WalletConnectViewModel extends BaseViewModel private final KeyService keyService; private final FindDefaultNetworkInteract findDefaultNetworkInteract; private final GenericWalletInteract genericWalletInteract; + private final FetchWalletsInteract fetchWalletsInteract; private final CreateTransactionInteract createTransactionInteract; + private final WalletConnectInteract walletConnectInteract; private final RealmManager realmManager; private final GasService gasService; private final TokensService tokensService; @@ -90,28 +96,35 @@ public class WalletConnectViewModel extends BaseViewModel @Nullable private Disposable prepareDisposable; + private final AWWalletConnectClient awWalletConnectClient; + private static final String TAG = "WCClientVM"; @Inject WalletConnectViewModel(KeyService keyService, FindDefaultNetworkInteract findDefaultNetworkInteract, - CreateTransactionInteract createTransactionInteract, + FetchWalletsInteract fetchWalletsInteract, CreateTransactionInteract createTransactionInteract, GenericWalletInteract genericWalletInteract, - RealmManager realmManager, + WalletConnectInteract walletConnectInteract, RealmManager realmManager, GasService gasService, TokensService tokensService, AnalyticsServiceType analyticsService, - EthereumNetworkRepositoryType ethereumNetworkRepository) + EthereumNetworkRepositoryType ethereumNetworkRepository, + AWWalletConnectClient awWalletConnectClient + ) { this.keyService = keyService; this.findDefaultNetworkInteract = findDefaultNetworkInteract; + this.fetchWalletsInteract = fetchWalletsInteract; this.createTransactionInteract = createTransactionInteract; this.genericWalletInteract = genericWalletInteract; + this.walletConnectInteract = walletConnectInteract; this.realmManager = realmManager; this.gasService = gasService; this.tokensService = tokensService; this.ethereumNetworkRepository = ethereumNetworkRepository; setAnalyticsService(analyticsService); + this.awWalletConnectClient = awWalletConnectClient; prepareDisposable = null; disposable = genericWalletInteract .find() @@ -205,7 +218,7 @@ public void signMessage(Signable message, DAppFunction dAppFunction) error -> dAppFunction.DAppError(error, message)); } - public void signTransaction(Context ctx, Web3Transaction w3tx, DAppFunction dAppFunction, String requesterURL, long chainId) + public void signTransaction(Context ctx, Web3Transaction w3tx, DAppFunction dAppFunction, String requesterURL, long chainId, Wallet fromWallet) { resetSignDialog(); EthereumMessage etm = new EthereumMessage(w3tx.getFormattedTransaction(ctx, chainId, getNetworkSymbol(chainId)).toString(), @@ -213,7 +226,7 @@ public void signTransaction(Context ctx, Web3Transaction w3tx, DAppFunction dApp if (w3tx.isConstructor()) { - disposable = createTransactionInteract.signTransaction(defaultWallet.getValue(), w3tx, chainId) + disposable = createTransactionInteract.signTransaction(fromWallet, w3tx, chainId) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(sig -> dAppFunction.DAppReturn(Numeric.hexStringToByteArray(sig.signature), etm), @@ -221,7 +234,7 @@ public void signTransaction(Context ctx, Web3Transaction w3tx, DAppFunction dApp } else { - disposable = createTransactionInteract.signTransaction(defaultWallet.getValue(), w3tx, chainId) + disposable = createTransactionInteract.signTransaction(fromWallet, w3tx, chainId) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(sig -> dAppFunction.DAppReturn(Numeric.hexStringToByteArray(sig.signature), etm), @@ -229,24 +242,34 @@ public void signTransaction(Context ctx, Web3Transaction w3tx, DAppFunction dApp } } - public void sendTransaction(final Web3Transaction finalTx, long chainId, SendTransactionInterface callback) + public void sendTransaction(final Web3Transaction finalTx, Wallet wallet, long chainId, SendTransactionInterface callback) { if (finalTx.isConstructor()) { disposable = createTransactionInteract - .createWithSig(defaultWallet.getValue(), finalTx.gasPrice, finalTx.gasLimit, finalTx.payload, chainId) - .subscribe(txData -> callback.transactionSuccess(finalTx, txData.txHash), + .createWithSig(wallet, finalTx.gasPrice, finalTx.gasLimit, finalTx.payload, chainId) + .subscribe(txData -> callback.transactionSuccess(finalTx, txData.signature), error -> callback.transactionError(finalTx.leafPosition, error)); } else { disposable = createTransactionInteract - .createWithSig(defaultWallet.getValue(), finalTx, chainId) - .subscribe(txData -> callback.transactionSuccess(finalTx, txData.txHash), + .createWithSig(wallet, finalTx, chainId) + .subscribe(txData -> callback.transactionSuccess(finalTx, txData.signature), error -> callback.transactionError(finalTx.leafPosition, error)); } } + public void sendTransaction(final Web3Transaction finalTx, long chainId, SendTransactionInterface callback) + { + sendTransaction(finalTx, defaultWallet.getValue(), chainId, callback); + } + + public Single calculateGasEstimate(Wallet wallet, byte[] transactionBytes, long chainId, String sendAddress, BigDecimal sendAmount, BigInteger defaultLimit) + { + return gasService.calculateGasEstimate(transactionBytes, chainId, sendAddress, sendAmount.toBigInteger(), wallet, defaultLimit); + } + public Single calculateGasEstimate(Wallet wallet, Web3Transaction transaction, long chainId) { if (transaction.isBaseTransfer()) @@ -407,20 +430,38 @@ public void updateSession(String sessionId, long sessionChainId) } } - public void deleteSession(String sessionId) + public void deleteSession(WalletConnectSessionItem session, AWWalletConnectClient.WalletConnectV2Callback callback) + { + if (session instanceof WalletConnectV2SessionItem) + { + deleteSessionV2(session, callback); + } + else + { + deleteSessionV1(session, callback); + } + } + + private void deleteSessionV2(WalletConnectSessionItem session, AWWalletConnectClient.WalletConnectV2Callback callback) + { + awWalletConnectClient.disconnect(session.sessionId, callback); + } + + private void deleteSessionV1(WalletConnectSessionItem session, AWWalletConnectClient.WalletConnectV2Callback callback) { - Timber.d("deleteSession: %s", sessionId); + Timber.d("deleteSession: %s", session.sessionId); try (Realm realm = realmManager.getRealmInstance(WC_SESSION_DB)) { realm.executeTransactionAsync(r -> { RealmWCSession sessionAux = r.where(RealmWCSession.class) - .equalTo("sessionId", sessionId) + .equalTo("sessionId", session.sessionId) .findFirst(); if (sessionAux != null) { sessionAux.deleteFromRealm(); } + callback.onSessionDisconnected(); }); } } @@ -479,20 +520,7 @@ public ArrayList getSignRecords(String sessionId) public List getSessions() { - List sessions = new ArrayList<>(); - try (Realm realm = realmManager.getRealmInstance(WC_SESSION_DB)) - { - RealmResults items = realm.where(RealmWCSession.class) - .sort("lastUsageTime", Sort.DESCENDING) - .findAll(); - - for (RealmWCSession r : items) - { - sessions.add(new WalletConnectSessionItem(r)); - } - } - - return sessions; + return walletConnectInteract.getSessions(); } public void removePendingRequest(Activity activity, long id) @@ -547,6 +575,7 @@ public void onServiceConnected(ComponentName name, IBinder service) { WalletConnectService walletConnectService = ((WalletConnectService.LocalBinder) service).getService(); walletConnectService.putClient(sessionId, client); + awWalletConnectClient.updateNotification(); } @Override @@ -678,6 +707,11 @@ public TokensService getTokenService() return tokensService; } + public Wallet findWallet(String address) + { + return fetchWalletsInteract.getWallet(address).blockingGet(); + } + public void endSession(String sessionId) { try (Realm realm = realmManager.getRealmInstance(WC_SESSION_DB)) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java index 4a81a7f24c..71e2e217fd 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java @@ -25,6 +25,7 @@ import com.alphawallet.app.entity.tokendata.TokenGroup; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; +import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; import com.alphawallet.app.interact.ChangeTokenEnableInteract; import com.alphawallet.app.interact.FetchTokensInteract; import com.alphawallet.app.interact.GenericWalletInteract; @@ -43,6 +44,7 @@ import com.alphawallet.app.ui.NameThisWalletActivity; import com.alphawallet.app.ui.QRScanning.QRScannerActivity; import com.alphawallet.app.ui.TokenManagementActivity; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.alphawallet.app.widget.WalletFragmentActionsView; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetDialog; @@ -51,6 +53,7 @@ import org.web3j.crypto.Keys; import java.math.BigDecimal; +import java.util.List; import javax.inject.Inject; @@ -84,6 +87,7 @@ public class WalletViewModel extends BaseViewModel private final OnRampRepositoryType onRampRepository; private long lastBackupCheck = 0; private BottomSheetDialog dialog; + private AWWalletConnectClient awWalletConnectClient; @Inject WalletViewModel( @@ -99,7 +103,8 @@ public class WalletViewModel extends BaseViewModel PreferenceRepositoryType preferenceRepository, RealmManager realmManager, OnRampRepositoryType onRampRepository, - AnalyticsServiceType analyticsService) + AnalyticsServiceType analyticsService, + AWWalletConnectClient awWalletConnectClient) { this.fetchTokensInteract = fetchTokensInteract; this.tokenDetailRouter = tokenDetailRouter; @@ -113,6 +118,7 @@ public class WalletViewModel extends BaseViewModel this.preferenceRepository = preferenceRepository; this.realmManager = realmManager; this.onRampRepository = onRampRepository; + this.awWalletConnectClient = awWalletConnectClient; setAnalyticsService(analyticsService); } @@ -429,4 +435,9 @@ public Intent getBuyIntent(String address) intent.putExtra(C.DAPP_URL_LOAD, onRampRepository.getUri(address, null)); return intent; } + + public MutableLiveData> activeWalletConnectSessions() + { + return awWalletConnectClient.sessionItemMutableLiveData(); + } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/walletconnect/SignMethodDialogViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/walletconnect/SignMethodDialogViewModel.java new file mode 100644 index 0000000000..e6e4975340 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/walletconnect/SignMethodDialogViewModel.java @@ -0,0 +1,128 @@ +package com.alphawallet.app.viewmodel.walletconnect; + +import static com.alphawallet.app.entity.cryptokeys.SignatureReturnType.SIGNATURE_GENERATED; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.widget.Toast; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.Operation; +import com.alphawallet.app.entity.SignAuthenticationCallback; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; +import com.alphawallet.app.interact.FetchWalletsInteract; +import com.alphawallet.app.repository.TransactionRepositoryType; +import com.alphawallet.app.service.KeyService; +import com.alphawallet.app.viewmodel.BaseViewModel; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; +import com.alphawallet.app.walletconnect.util.WalletConnectHelper; +import com.alphawallet.token.entity.Signable; +import com.alphawallet.token.tools.Numeric; +import com.walletconnect.sign.client.Sign; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; +import io.reactivex.Single; +import timber.log.Timber; + +@HiltViewModel +public class SignMethodDialogViewModel extends BaseViewModel +{ + private final AWWalletConnectClient awWalletConnectClient; + private final FetchWalletsInteract fetchWalletsInteract; + private final TransactionRepositoryType transactionRepositoryType; + private final KeyService keyService; + private final MutableLiveData completed = new MutableLiveData<>(false); + + @Inject + public SignMethodDialogViewModel(AWWalletConnectClient awWalletConnectClient, FetchWalletsInteract fetchWalletsInteract, TransactionRepositoryType transactionRepositoryType, KeyService keyService) + { + this.awWalletConnectClient = awWalletConnectClient; + this.fetchWalletsInteract = fetchWalletsInteract; + this.transactionRepositoryType = transactionRepositoryType; + this.keyService = keyService; + } + + public void sign(Activity activity, Wallet wallet, Sign.Model.SessionRequest sessionRequest, final Signable signable) + { + keyService.getAuthenticationForSignature(wallet, activity, new SignAuthenticationCallback() + { + @SuppressLint("CheckResult") + @Override + public void gotAuthorisation(boolean gotAuth) + { + if (gotAuth) + { + long chainId = WalletConnectHelper.getChainId(Objects.requireNonNull(sessionRequest.getChainId())); + Single signature = transactionRepositoryType.getSignature(wallet, signable, chainId); + signature + .delay(5, TimeUnit.SECONDS) // The WC connection shutdown when show biometric, when back to foreground, it will open new connection, so need delay to wait the connection opened + .subscribe(signatureFromKey -> onSuccess(signatureFromKey, sessionRequest), SignMethodDialogViewModel.this::onError); + } + else + { + Toast.makeText(activity, activity.getString(R.string.error_while_signing_transaction), Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void cancelAuthentication() + { + Timber.i("cancelAuthentication"); + } + }); + } + + public void onError(Throwable throwable) + { + Timber.e(throwable); + } + + private void onSuccess(SignatureFromKey signatureFromKey, Sign.Model.SessionRequest sessionRequest) + { + if (signatureFromKey.sigType == SIGNATURE_GENERATED) + { + String result = Numeric.toHexString(signatureFromKey.signature); + awWalletConnectClient.approve(sessionRequest, result); + } + else + { + Timber.i("sign fail: %s", signatureFromKey.failMessage); + awWalletConnectClient.reject(sessionRequest, signatureFromKey.failMessage); + } + completed.postValue(true); + } + + public void completeAuthentication(Operation taskCode) + { + keyService.completeAuthentication(taskCode); + } + + public void failedAuthentication(Operation taskCode) + { + keyService.failedAuthentication(taskCode); + } + + public LiveData completed() + { + return completed; + } + + public void reject(Sign.Model.SessionRequest sessionRequest) + { + awWalletConnectClient.reject(sessionRequest); + } + + public Single findWallet(String walletAddress) + { + return fetchWalletsInteract.getWallet(walletAddress); + } +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java b/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java new file mode 100644 index 0000000000..06e90254a8 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java @@ -0,0 +1,362 @@ +package com.alphawallet.app.walletconnect; + +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + +import android.app.Activity; +import android.app.Application; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.lifecycle.MutableLiveData; + +import com.alphawallet.app.App; +import com.alphawallet.app.BuildConfig; +import com.alphawallet.app.C; +import com.alphawallet.app.R; +import com.alphawallet.app.entity.AuthenticationCallback; +import com.alphawallet.app.entity.walletconnect.NamespaceParser; +import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; +import com.alphawallet.app.entity.walletconnect.WalletConnectV2SessionItem; +import com.alphawallet.app.interact.WalletConnectInteract; +import com.alphawallet.app.repository.KeyProvider; +import com.alphawallet.app.repository.KeyProviderFactory; +import com.alphawallet.app.service.WalletConnectV2Service; +import com.alphawallet.app.ui.WalletConnectV2Activity; +import com.alphawallet.app.viewmodel.walletconnect.SignMethodDialogViewModel; +import com.alphawallet.app.walletconnect.util.WCMethodChecker; +import com.walletconnect.android.Core; +import com.walletconnect.android.CoreClient; +import com.walletconnect.android.relay.ConnectionType; +import com.walletconnect.sign.client.Sign; +import com.walletconnect.sign.client.SignClient; +import com.walletconnect.sign.client.SignInterface; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import kotlin.Unit; +import timber.log.Timber; + +public class AWWalletConnectClient implements SignInterface.WalletDelegate +{ + private static final String TAG = AWWalletConnectClient.class.getName(); + public static AuthenticationCallback authCallback; + private final WalletConnectInteract walletConnectInteract; + public static Sign.Model.SessionProposal sessionProposal; + + public static SignMethodDialogViewModel viewModel; + private final Context context; + private final MutableLiveData> sessionItemMutableLiveData = new MutableLiveData<>(Collections.emptyList()); + private final KeyProvider keyProvider = KeyProviderFactory.get(); + + public AWWalletConnectClient(Context context, WalletConnectInteract walletConnectInteract) + { + this.context = context; + this.walletConnectInteract = walletConnectInteract; + } + + public void onSessionDelete(@NonNull Sign.Model.DeletedSession deletedSession) + { + updateNotification(); + } + + public void onSessionProposal(@NonNull Sign.Model.SessionProposal sessionProposal) + { + WalletConnectV2SessionItem sessionItem = WalletConnectV2SessionItem.from(sessionProposal); + if (!validChainId(sessionItem.chains)) + { + return; + } + AWWalletConnectClient.sessionProposal = sessionProposal; + Intent intent = new Intent(context, WalletConnectV2Activity.class); + intent.putExtra("session", sessionItem); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + private boolean validChainId(List chains) + { + for (String chainId : chains) + { + try + { + Long.parseLong(chainId.split(":")[1]); + } + catch (Exception e) + { + new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, String.format(context.getString(R.string.chain_not_support), chainId), Toast.LENGTH_SHORT).show()); + return false; + } + } + return true; + } + + @RequiresApi(api = Build.VERSION_CODES.O) + public void onSessionRequest(@NonNull Sign.Model.SessionRequest sessionRequest) + { + String method = sessionRequest.getRequest().getMethod(); + + if (!WCMethodChecker.includes(method)) + { + reject(sessionRequest); + return; + } + + Sign.Model.Session settledSession = getSession(sessionRequest.getTopic()); + + Activity topActivity = App.getInstance().getTopActivity(); + WalletConnectV2SessionRequestHandler handler = new WalletConnectV2SessionRequestHandler(sessionRequest, settledSession, topActivity, this); + handler.handle(method); + } + + private Sign.Model.Session getSession(String topic) + { + List listOfSettledSessions; + + try + { + listOfSettledSessions = SignClient.INSTANCE.getListOfSettledSessions(); + } + catch (IllegalStateException e) + { + listOfSettledSessions = Collections.emptyList(); + Timber.tag(TAG).e(e); + } + + + for (Sign.Model.Session session : listOfSettledSessions) + { + if (session.getTopic().equals(topic)) + { + return session; + } + } + return null; + } + + public void pair(String url, Consumer callback) + { + Core.Params.Pair pair = new Core.Params.Pair(url); + CoreClient.INSTANCE.getPairing().pair(pair, error -> { + Timber.e(error.getThrowable()); + callback.accept(error.getThrowable().getMessage()); + return null; + }); + } + + public void approve(Sign.Model.SessionRequest sessionRequest, String result) + { + Sign.Model.JsonRpcResponse jsonRpcResponse = new Sign.Model.JsonRpcResponse.JsonRpcResult(sessionRequest.getRequest().getId(), result); + Sign.Params.Response response = new Sign.Params.Response(sessionRequest.getTopic(), jsonRpcResponse); + SignClient.INSTANCE.respond(response, this::onSessionRequestApproveError); + } + + private Unit onSessionRequestApproveError(Sign.Model.Error error) + { + Timber.e(error.getThrowable()); + return null; + } + + public void reject(Sign.Model.SessionRequest sessionRequest) + { + reject(sessionRequest, context.getString(R.string.message_reject_request)); + } + + public void approve(Sign.Model.SessionProposal sessionProposal, List selectedAccounts, WalletConnectV2Callback callback) + { + String proposerPublicKey = sessionProposal.getProposerPublicKey(); + Sign.Params.Approve approve = new Sign.Params.Approve(proposerPublicKey, buildNamespaces(sessionProposal, selectedAccounts), sessionProposal.getRelayProtocol()); + SignClient.INSTANCE.approveSession(approve, this::onSessionApproveError); + callback.onSessionProposalApproved(); + new Handler().postDelayed(this::updateNotification, 3000); + } + + private Map buildNamespaces(Sign.Model.SessionProposal sessionProposal, List selectedAccounts) + { + Map result = new HashMap<>(); + Map namespaces = sessionProposal.getRequiredNamespaces(); + NamespaceParser namespaceParser = new NamespaceParser(); + namespaceParser.parseProposal(namespaces); + List accounts = toCAIP10(namespaceParser.getChains(), selectedAccounts); + for (Map.Entry entry : namespaces.entrySet()) + { + Sign.Model.Namespace.Session session = new Sign.Model.Namespace.Session(accounts, namespaceParser.getMethods(), namespaceParser.getEvents(), null); + result.put(entry.getKey(), session); + } + return result; + } + + private List toCAIP10(List chains, List selectedAccounts) + { + List result = new ArrayList<>(); + for (String chain : chains) + { + for (String account : selectedAccounts) + { + result.add(chain + ":" + account); + } + } + return result; + } + + private Unit onSessionApproveError(Sign.Model.Error error) + { + Timber.e(error.getThrowable()); + Toast.makeText(context, error.getThrowable().getLocalizedMessage(), Toast.LENGTH_SHORT).show(); + return null; + } + + public MutableLiveData> sessionItemMutableLiveData() + { + return sessionItemMutableLiveData; + } + + public void updateNotification() + { + walletConnectInteract.fetchSessions(context, items -> { + sessionItemMutableLiveData.postValue(items); + updateService(context, items); + }); + } + + private void updateService(Context context, List walletConnectSessionItems) + { + if (walletConnectSessionItems.isEmpty()) + { + context.stopService(new Intent(context, WalletConnectV2Service.class)); + } + else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + { + Intent service = new Intent(context, WalletConnectV2Service.class); + context.startForegroundService(service); + } + } + + + public void reject(Sign.Model.SessionProposal sessionProposal, WalletConnectV2Callback callback) + { + + SignClient.INSTANCE.rejectSession( + new Sign.Params.Reject(sessionProposal.getProposerPublicKey(), context.getString(R.string.message_reject_request)), + this::onSessionRejectError); + callback.onSessionProposalRejected(); + } + + private Unit onSessionRejectError(Sign.Model.Error error) + { + Timber.e(error.getThrowable()); + return null; + } + + public void disconnect(String sessionId, WalletConnectV2Callback callback) + { + SignClient.INSTANCE.disconnect(new Sign.Params.Disconnect(sessionId), this::onDisconnectError); + callback.onSessionDisconnected(); + updateNotification(); + } + + private Unit onDisconnectError(Sign.Model.Error error) + { + Timber.e(error.getThrowable()); + return null; + } + + public void reject(Sign.Model.SessionRequest sessionRequest, String failMessage) + { + Sign.Model.JsonRpcResponse jsonRpcResponse = new Sign.Model.JsonRpcResponse.JsonRpcError(sessionRequest.getRequest().getId(), 0, failMessage); + Sign.Params.Response response = new Sign.Params.Response(sessionRequest.getTopic(), jsonRpcResponse); + SignClient.INSTANCE.respond(response, this::onSessionRequestRejectError); + } + + private Unit onSessionRequestRejectError(Sign.Model.Error error) + { + Timber.e(error.getThrowable()); + return null; + } + + public void init(Application application) + { + Core.Model.AppMetaData appMetaData = getAppMetaData(application); + String relayServer = String.format("%s/?projectId=%s", C.WALLET_CONNECT_REACT_APP_RELAY_URL, keyProvider.getWalletConnectProjectId()); + CoreClient coreClient = CoreClient.INSTANCE; + coreClient.initialize(appMetaData, relayServer, ConnectionType.AUTOMATIC, application, null); + + SignClient.INSTANCE.initialize(new Sign.Params.Init(coreClient), e -> + { + Timber.tag(TAG).e("Init failed: %s", e.getThrowable().getMessage()); + return null; + }); + + try + { + SignClient.INSTANCE.setWalletDelegate(this); + } + catch (Exception e) + { + Timber.tag(TAG).e(e); + } + } + + @NonNull + private Core.Model.AppMetaData getAppMetaData(Application application) + { + String name = application.getString(R.string.app_name); + String url = C.ALPHAWALLET_WEBSITE; + String[] icons = {C.ALPHA_WALLET_LOGO_URL}; + String description = "The ultimate Web3 Wallet to power your tokens."; + String redirect = "kotlin-responder-wc:/request"; + return new Core.Model.AppMetaData(name, description, url, Arrays.asList(icons), redirect); + } + + public void shutdown() + { + Timber.tag(TAG).i("shutdown"); + } + + public void onConnectionStateChange(@NonNull Sign.Model.ConnectionState connectionState) + { + Timber.tag(TAG).i("onConnectionStateChange"); + } + + public void onSessionSettleResponse(@NonNull Sign.Model.SettledSessionResponse settledSessionResponse) + { + Timber.tag(TAG).i("onSessionSettleResponse"); + } + + public void onSessionUpdateResponse(@NonNull Sign.Model.SessionUpdateResponse sessionUpdateResponse) + { + Timber.tag(TAG).i("onSessionUpdateResponse"); + } + + public void onError(Sign.Model.Error error) + { + Timber.e(error.getThrowable()); + } + + public interface WalletConnectV2Callback + { + default void onSessionProposalApproved() + { + } + + default void onSessionProposalRejected() + { + } + + default void onSessionDisconnected() + { + } + } +} + diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/SignRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/SignRequest.java new file mode 100644 index 0000000000..a5dcaf920c --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/SignRequest.java @@ -0,0 +1,27 @@ +package com.alphawallet.app.walletconnect; + +import com.alphawallet.app.walletconnect.entity.BaseRequest; +import com.alphawallet.app.walletconnect.entity.WCEthereumSignMessage; +import com.alphawallet.token.entity.EthereumMessage; +import com.alphawallet.token.entity.SignMessageType; +import com.alphawallet.token.entity.Signable; + +public class SignRequest extends BaseRequest +{ + public SignRequest(String params) + { + super(params, WCEthereumSignMessage.WCSignType.MESSAGE); + } + + @Override + public Signable getSignable() + { + return new EthereumMessage(getMessage(), "", 0, SignMessageType.SIGN_MESSAGE); + } + + @Override + public String getWalletAddress() + { + return params.get(0); + } +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java b/app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java new file mode 100644 index 0000000000..75ef560ccb --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java @@ -0,0 +1,198 @@ +package com.alphawallet.app.walletconnect; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.widget.Toast; + +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.lifecycle.ViewModelStoreOwner; + +import com.alphawallet.app.entity.DAppFunction; +import com.alphawallet.app.entity.SendTransactionInterface; +import com.alphawallet.app.entity.SignAuthenticationCallback; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; +import com.alphawallet.app.viewmodel.WalletConnectViewModel; +import com.alphawallet.app.walletconnect.entity.WCEthereumTransaction; +import com.alphawallet.app.walletconnect.util.WalletConnectHelper; +import com.alphawallet.app.web3.entity.Web3Transaction; +import com.alphawallet.app.widget.ActionSheetDialog; +import com.alphawallet.token.entity.Signable; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.walletconnect.sign.client.Sign; + +import org.web3j.utils.Numeric; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +public class TransactionDialogBuilder extends DialogFragment +{ + private final Activity activity; + private final Sign.Model.SessionRequest sessionRequest; + private final Sign.Model.Session settledSession; + private final AWWalletConnectClient awWalletConnectClient; + private final boolean signOnly; + private WalletConnectViewModel viewModel; + private ActionSheetDialog actionSheetDialog; + private final ActivityResultLauncher activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> actionSheetDialog.setCurrentGasIndex(result)); + + public TransactionDialogBuilder(Activity activity, Sign.Model.SessionRequest sessionRequest, Sign.Model.Session settledSession, AWWalletConnectClient awWalletConnectClient, boolean signOnly) + { + this.activity = activity; + this.sessionRequest = sessionRequest; + this.settledSession = settledSession; + this.awWalletConnectClient = awWalletConnectClient; + this.signOnly = signOnly; + + initViewModel(); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider((ViewModelStoreOwner) activity) + .get(WalletConnectViewModel.class); + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) + { + Type listType = new TypeToken>() + { + }.getType(); + List list = new Gson().fromJson(sessionRequest.getRequest().getParams(), listType); + WCEthereumTransaction wcTx = list.get(0); + final Web3Transaction w3Tx = new Web3Transaction(wcTx, 0); + Wallet fromWallet = viewModel.findWallet(wcTx.getFrom()); + Token token = viewModel.getTokensService().getTokenOrBase(WalletConnectHelper.getChainId(Objects.requireNonNull(sessionRequest.getChainId())), w3Tx.recipient.toString()); + actionSheetDialog = new ActionSheetDialog(activity, w3Tx, token, "", w3Tx.recipient.toString(), viewModel.getTokensService(), new ActionSheetCallback() + { + @Override + public void getAuthorisation(SignAuthenticationCallback callback) + { + viewModel.getAuthenticationForSignature(fromWallet, activity, callback); + } + + @Override + public void signTransaction(Web3Transaction tx) + { + signMessage(fromWallet, tx, awWalletConnectClient); + } + + @Override + public void sendTransaction(Web3Transaction tx) + { + TransactionDialogBuilder.this.sendTransaction(fromWallet, tx, awWalletConnectClient); + } + + @Override + public void dismissed(String txHash, long callbackId, boolean actionCompleted) + { + if (!actionCompleted) + { + awWalletConnectClient.reject(sessionRequest); + } + } + + @Override + public void notifyConfirm(String mode) + { + } + + @Override + public ActivityResultLauncher gasSelectLauncher() + { + return activityResultLauncher; + } + }); + if (signOnly) + { + actionSheetDialog.setSignOnly(); + } + String url = Objects.requireNonNull(settledSession.getMetaData()).getUrl(); + actionSheetDialog.setURL(url); + actionSheetDialog.setCanceledOnTouchOutside(false); + actionSheetDialog.waitForEstimate(); + + viewModel.calculateGasEstimate(fromWallet, Numeric.hexStringToByteArray(w3Tx.payload), + WalletConnectHelper.getChainId(Objects.requireNonNull(sessionRequest.getChainId())), w3Tx.recipient.toString(), new BigDecimal(w3Tx.value), w3Tx.gasLimit) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(actionSheetDialog::setGasEstimate, + Throwable::printStackTrace) + .isDisposed(); + + return actionSheetDialog; + } + + private void signMessage(Wallet fromWallet, Web3Transaction tx, AWWalletConnectClient awWalletConnectClient) + { + viewModel.signTransaction(actionSheetDialog.getContext(), tx, new DAppFunction() + { + @Override + public void DAppError(Throwable error, Signable message) + { + reject(error, awWalletConnectClient); + } + + @Override + public void DAppReturn(byte[] data, Signable message) + { + approve(Numeric.toHexString(data), awWalletConnectClient); + actionSheetDialog.transactionWritten("."); + } + }, Objects.requireNonNull(settledSession.getMetaData()).getUrl(), WalletConnectHelper.getChainId(Objects.requireNonNull(sessionRequest.getChainId())), fromWallet); + } + + private void sendTransaction(Wallet wallet, Web3Transaction tx, AWWalletConnectClient awWalletConnectClient) + { + viewModel.sendTransaction(tx, wallet, WalletConnectHelper.getChainId(Objects.requireNonNull(sessionRequest.getChainId())), new SendTransactionInterface() + { + @Override + public void transactionSuccess(Web3Transaction web3Tx, String hashData) + { + approve(hashData, awWalletConnectClient); + actionSheetDialog.transactionWritten(hashData); + } + + @Override + public void transactionError(long callbackId, Throwable error) + { + reject(error, awWalletConnectClient); + } + }); + } + + private void reject(Throwable error, AWWalletConnectClient awWalletConnectClient) + { + Toast.makeText(activity, error.getMessage(), Toast.LENGTH_SHORT).show(); + awWalletConnectClient.reject(sessionRequest); + actionSheetDialog.dismiss(); + } + + private void approve(String hashData, AWWalletConnectClient awWalletConnectClient) + { + new Handler(Looper.getMainLooper()).postDelayed(() -> + awWalletConnectClient.approve(sessionRequest, hashData), 5000); + } + +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java b/app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java new file mode 100644 index 0000000000..a3c4bc3f9f --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java @@ -0,0 +1,93 @@ +package com.alphawallet.app.walletconnect; + +import android.app.Activity; +import android.app.Dialog; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.FragmentManager; + +import com.alphawallet.app.walletconnect.entity.BaseRequest; +import com.alphawallet.app.walletconnect.entity.SignPersonalMessageRequest; +import com.alphawallet.app.walletconnect.entity.SignTypedDataRequest; +import com.alphawallet.app.widget.SignMethodDialog; +import com.walletconnect.sign.client.Sign; + +import timber.log.Timber; + +public class WalletConnectV2SessionRequestHandler +{ + private final Sign.Model.SessionRequest sessionRequest; + private final Sign.Model.Session settledSession; + private final Activity activity; + private final AWWalletConnectClient client; + + public WalletConnectV2SessionRequestHandler(Sign.Model.SessionRequest sessionRequest, Sign.Model.Session settledSession, Activity activity, AWWalletConnectClient client) + { + this.sessionRequest = sessionRequest; + this.settledSession = settledSession; + this.activity = activity; + this.client = client; + } + + public void handle(String method) + { + activity.runOnUiThread(() -> { + showDialog(method); + }); + } + + private void showDialog(String method) + { + boolean isSignTransaction = "eth_signTransaction".equals(method); + boolean isSendTransaction = "eth_sendTransaction".equals(method); + if (isSendTransaction || isSignTransaction) + { + TransactionDialogBuilder transactionDialogBuilder = new TransactionDialogBuilder(activity, sessionRequest, settledSession, client, isSignTransaction); + FragmentManager fragmentManager = ((AppCompatActivity) activity).getSupportFragmentManager(); + transactionDialogBuilder.show(fragmentManager, "wc_call"); + return; + } + + if ("personal_sign".equals(method)) + { + personalSign().show(); + return; + } + + if ("eth_sign".equals(method)) + { + ethSign().show(); + return; + } + + if ("eth_signTypedData".equals(method)) + { + ethSignTypedData().show(); + return; + } + + Timber.e("Method %s not support.", method); + } + + private Dialog ethSign() + { + BaseRequest request = new SignRequest(sessionRequest.getRequest().getParams()); + return new SignMethodDialog(activity, sessionRequest, request, settledSession.getMetaData()); + } + + @NonNull + private SignMethodDialog ethSignTypedData() + { + BaseRequest request = new SignTypedDataRequest(sessionRequest.getRequest().getParams()); + return new SignMethodDialog(activity, sessionRequest, request, settledSession.getMetaData()); + } + + @NonNull + private SignMethodDialog personalSign() + { + BaseRequest request = new SignPersonalMessageRequest(sessionRequest.getRequest().getParams()); + return new SignMethodDialog(activity, sessionRequest, request, settledSession.getMetaData()); + } + +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/entity/BaseRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/BaseRequest.java new file mode 100644 index 0000000000..9df6a1d91e --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/BaseRequest.java @@ -0,0 +1,54 @@ +package com.alphawallet.app.walletconnect.entity; + +import static java.util.Arrays.asList; + +import com.alphawallet.token.entity.Signable; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.util.List; + +import timber.log.Timber; + +public abstract class BaseRequest +{ + private static final String TAG = BaseRequest.class.getName(); + protected String rawParams; + private final WCEthereumSignMessage.WCSignType type; + protected List params; + + public BaseRequest(String rawParams, WCEthereumSignMessage.WCSignType type) + { + Timber.tag(TAG).i(rawParams); + + this.rawParams = rawParams; + this.type = type; + try + { + params = new Gson().fromJson(rawParams, new TypeToken>() + { + }.getType()); + } + catch (Exception e) + { + String unwrapped = unwrap(rawParams); + int index = unwrapped.indexOf(","); + params = asList(unwrap(unwrapped.substring(0, index)), unwrapped.substring(index + 1)); + } + } + + protected String unwrap(String src) + { + StringBuilder stringBuilder = new StringBuilder(src); + return stringBuilder.substring(1, stringBuilder.length() - 1); + } + + protected String getMessage() + { + return new WCEthereumSignMessage(params, type).getData(); + } + + public abstract Signable getSignable(); + + public abstract String getWalletAddress(); +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequest.java new file mode 100644 index 0000000000..f8dc3c7f69 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequest.java @@ -0,0 +1,25 @@ +package com.alphawallet.app.walletconnect.entity; + +import com.alphawallet.token.entity.EthereumMessage; +import com.alphawallet.token.entity.SignMessageType; +import com.alphawallet.token.entity.Signable; + +public class SignPersonalMessageRequest extends BaseRequest +{ + public SignPersonalMessageRequest(String params) + { + super(params, WCEthereumSignMessage.WCSignType.PERSONAL_MESSAGE); + } + + @Override + public Signable getSignable() + { + return new EthereumMessage(getMessage(), "", 0, SignMessageType.SIGN_PERSONAL_MESSAGE); + } + + @Override + public String getWalletAddress() + { + return params.get(1); + } +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequest.java new file mode 100644 index 0000000000..54c55ff1bd --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequest.java @@ -0,0 +1,23 @@ +package com.alphawallet.app.walletconnect.entity; + +import com.alphawallet.app.entity.CryptoFunctions; +import com.alphawallet.token.entity.EthereumTypedMessage; +import com.alphawallet.token.entity.Signable; + +public class SignTypedDataRequest extends BaseRequest +{ + public SignTypedDataRequest(String params) + { + super(params, WCEthereumSignMessage.WCSignType.TYPED_MESSAGE); + } + + public String getWalletAddress() + { + return params.get(0); + } + + public Signable getSignable() + { + return new EthereumTypedMessage(getMessage(), "", 0, new CryptoFunctions()); + } +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/util/WCMethodChecker.java b/app/src/main/java/com/alphawallet/app/walletconnect/util/WCMethodChecker.java new file mode 100644 index 0000000000..bb0ec1f85e --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/util/WCMethodChecker.java @@ -0,0 +1,29 @@ +package com.alphawallet.app.walletconnect.util; + +import com.alphawallet.app.entity.TokensMapping; +import com.alphawallet.app.walletconnect.entity.WCMethod; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.List; + +public class WCMethodChecker +{ + private static final List methods; + + static + { + Gson gson = new Gson(); + String json = gson.toJson(WCMethod.values()); + Type type = new TypeToken>() + { + }.getType(); + methods = gson.fromJson(json, type); + } + + public static boolean includes(String method) + { + return methods.contains(method); + } +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/util/WalletConnectHelper.java b/app/src/main/java/com/alphawallet/app/walletconnect/util/WalletConnectHelper.java new file mode 100644 index 0000000000..5c3fd6f8d8 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/util/WalletConnectHelper.java @@ -0,0 +1,14 @@ +package com.alphawallet.app.walletconnect.util; + +public class WalletConnectHelper +{ + public static boolean isWalletConnectV1(String text) + { + return text.contains("@1?"); + } + + public static long getChainId(String chainId) + { + return Long.parseLong(chainId.split(":")[1]); + } +} diff --git a/app/src/main/java/com/alphawallet/app/web3j/StructuredDataEncoder.java b/app/src/main/java/com/alphawallet/app/web3j/StructuredDataEncoder.java index 3c6148f2f8..7113f89ade 100644 --- a/app/src/main/java/com/alphawallet/app/web3j/StructuredDataEncoder.java +++ b/app/src/main/java/com/alphawallet/app/web3j/StructuredDataEncoder.java @@ -13,6 +13,7 @@ package com.alphawallet.app.web3j; import com.fasterxml.jackson.databind.ObjectMapper; +import static org.web3j.abi.datatypes.Type.MAX_BYTE_LENGTH; import org.web3j.abi.TypeEncoder; import org.web3j.abi.datatypes.AbiTypes; @@ -26,6 +27,7 @@ import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -117,6 +119,14 @@ public Set getDependencies(String primaryType) { public String encodeStruct(String structName) { HashMap> types = jsonMessageObject.getTypes(); + if (!types.containsKey("EIP712Domain")) + { + types.put("EIP712Domain", Arrays.asList( + new StructuredData.Entry("name", "string"), + new StructuredData.Entry("version", "string"), + new StructuredData.Entry("verifyingContract", "address") + )); + } StringBuilder structRepresentation = new StringBuilder(structName + "("); for (StructuredData.Entry entry : types.get(structName)) { diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java index 2f7e8726a3..d7a4d9e7da 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java @@ -784,7 +784,6 @@ public void gotAuthorisation(boolean gotAuth) return; } confirmationWidget.startProgressCycle(4); - //send the transaction actionSheetCallback.sendTransaction(formTransaction()); actionSheetCallback.notifyConfirm(mode.getValue()); } @@ -888,3 +887,8 @@ private boolean has1559Gas() return false; } } + +interface OnGasSelectedCallback +{ + void onSelected(); +} diff --git a/app/src/main/java/com/alphawallet/app/widget/GasWidget.java b/app/src/main/java/com/alphawallet/app/widget/GasWidget.java index e79b665ed0..230787019e 100644 --- a/app/src/main/java/com/alphawallet/app/widget/GasWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/GasWidget.java @@ -24,6 +24,7 @@ import com.alphawallet.app.repository.TokensRealmSource; import com.alphawallet.app.repository.entity.RealmGasSpread; import com.alphawallet.app.repository.entity.RealmTokenTicker; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.alphawallet.app.service.GasService; import com.alphawallet.app.service.TickerService; import com.alphawallet.app.service.TokensService; diff --git a/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java b/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java index 34d247aa2d..ca9329ccad 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java @@ -1,6 +1,7 @@ package com.alphawallet.app.widget; import android.content.Context; +import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; @@ -38,6 +39,24 @@ public SignDataWidget(Context context, @Nullable AttributeSet attrs) moreArrow = findViewById(R.id.image_more); scrollView = findViewById(R.id.scroll_view); messageTitle = findViewById(R.id.text_message_title); + + boolean noTitle = getAttribute(context, attrs); + if (noTitle) + { + messageTitle.setText(""); + messageTitle.setVisibility(GONE); + } + } + + private boolean getAttribute(Context context, AttributeSet attrs) + { + TypedArray a = context.getTheme().obtainStyledAttributes( + attrs, + R.styleable.SignDataWidget, + 0, 0 + ); + + return a.getBoolean(R.styleable.SignDataWidget_noTitle, false); } public void setupSignData(Signable message) diff --git a/app/src/main/java/com/alphawallet/app/widget/SignMethodDialog.java b/app/src/main/java/com/alphawallet/app/widget/SignMethodDialog.java new file mode 100644 index 0000000000..7d6aa6bec5 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/widget/SignMethodDialog.java @@ -0,0 +1,188 @@ +package com.alphawallet.app.widget; + +import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.ViewModelProvider; +import androidx.lifecycle.ViewModelStoreOwner; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.StandardFunctionInterface; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.repository.EthereumNetworkRepository; +import com.alphawallet.app.util.Hex; +import com.alphawallet.app.viewmodel.walletconnect.SignMethodDialogViewModel; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; +import com.alphawallet.app.walletconnect.entity.BaseRequest; +import com.alphawallet.app.walletconnect.util.WalletConnectHelper; +import com.alphawallet.token.entity.SignMessageType; +import com.alphawallet.token.entity.Signable; +import com.bumptech.glide.Glide; +import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.google.android.material.bottomsheet.BottomSheetDialog; +import com.walletconnect.android.Core; +import com.walletconnect.sign.client.Sign; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +public class SignMethodDialog extends BottomSheetDialog +{ + private FunctionButtonBar functionBar; + private TextView dAppName; + private ImageView logo; + private TextView url; + private TextView walletTv; + private TextView message; + private ImageView networkIcon; + private ChainName networkName; + private final Activity activity; + private ImageView closeButton; + private final Sign.Model.SessionRequest sessionRequest; + private final BaseRequest request; + private String walletAddress; + private SignMethodDialogViewModel viewModel; + private final Signable signable; + private SignDataWidget signDataWidget; + private final Core.Model.AppMetaData metaData; + + public SignMethodDialog(@NonNull Activity activity, Sign.Model.SessionRequest sessionRequest, BaseRequest request, Core.Model.AppMetaData metaData) + { + super(activity); + this.activity = activity; + this.metaData = metaData; + this.sessionRequest = sessionRequest; + this.request = request; + this.signable = request.getSignable(); + View view = LayoutInflater.from(activity).inflate(R.layout.dialog_sign_method, null); + setContentView(view); + initViewModel(); + + BottomSheetBehavior behavior = BottomSheetBehavior.from((View) view.getParent()); + behavior.setState(STATE_EXPANDED); + behavior.setSkipCollapsed(true); + setCancelable(false); + + initViews(); + bindData(); + } + + private void bindData() + { + List icons = Objects.requireNonNull(metaData).getIcons(); + + if (icons.isEmpty()) + { + logo.setImageResource(R.drawable.ic_coin_eth_small); + } + else + { + Glide.with(activity) + .load(icons.get(0)) + .circleCrop() + .into(logo); + } + dAppName.setText(metaData.getName()); + url.setText(metaData.getUrl()); + walletAddress = request.getWalletAddress(); + walletTv.setText(walletAddress); + + long chainID = WalletConnectHelper.getChainId(Objects.requireNonNull(sessionRequest.getChainId())); + networkIcon.setImageResource(EthereumNetworkRepository.getChainLogo(chainID)); + networkName.setChainID(chainID); + functionBar.setupFunctions(new StandardFunctionInterface() + { + @Override + public void handleClick(String action, int actionId) + { + if (actionId == R.string.action_confirm) + { + approve(); + } + } + }, Collections.singletonList(R.string.action_confirm)); + + closeButton.setOnClickListener(v -> + { + viewModel.reject(sessionRequest); + dismiss(); + }); + + if (signable.getMessageType() == SignMessageType.SIGN_PERSONAL_MESSAGE + || signable.getMessageType() == SignMessageType.SIGN_MESSAGE) + { + message.setText(Hex.hexToUtf8(signable.getMessage())); + } + else + { + message.setVisibility(View.GONE); + signDataWidget.setVisibility(View.VISIBLE); + signDataWidget.setupSignData(request.getSignable()); + } + } + + private void initViews() + { + logo = findViewById(R.id.logo); + dAppName = findViewById(R.id.dapp_name); + url = findViewById(R.id.url); + walletTv = findViewById(R.id.wallet); + message = findViewById(R.id.message); + networkIcon = findViewById(R.id.network_icon); + networkName = findViewById(R.id.network_name); + functionBar = findViewById(R.id.layoutButtons); + closeButton = findViewById(R.id.image_close); + signDataWidget = findViewById(R.id.sign_widget); + } + + private void initViewModel() + { + viewModel = new ViewModelProvider((ViewModelStoreOwner) activity).get(SignMethodDialogViewModel.class); + } + + @SuppressLint("CheckResult") + private void approve() + { + AWWalletConnectClient.viewModel = viewModel; + viewModel.completed().observe((LifecycleOwner) activity, completed -> + { + if (completed) + { + dismiss(); + AWWalletConnectClient.viewModel = null; + } + }); + + viewModel.findWallet(walletAddress) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::onWalletFound); + } + + private void onWalletFound(Wallet wallet) + { + // The method find may return the first wallet if the specified wallet not found + if (!wallet.address.equals(walletAddress) || wallet.watchOnly()) + { + Toast.makeText(getContext(), activity.getString(R.string.wc_wallet_not_match), Toast.LENGTH_SHORT).show(); + } + else + { + functionBar.setPrimaryButtonWaiting(); + viewModel.sign(activity, wallet, sessionRequest, signable); + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java b/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java index fdbb452dbc..03ccd000a3 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java @@ -22,6 +22,7 @@ import com.alphawallet.app.entity.AuthenticationCallback; import com.alphawallet.app.entity.AuthenticationFailType; import com.alphawallet.app.entity.Operation; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import java.security.ProviderException; import java.util.concurrent.Executor; @@ -177,8 +178,11 @@ else if (km != null) if (intent == null) { authCallback.authenticateFail("Can not unlock", AuthenticationFailType.BIOMETRIC_AUTHENTICATION_NOT_AVAILABLE, callBackId); - } else { + } + else + { intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + AWWalletConnectClient.authCallback = authCallback; activity.startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + callBackId.ordinal()); } } diff --git a/app/src/main/res/drawable/ic_wallet_connect_card.xml b/app/src/main/res/drawable/ic_wallet_connect_card.xml new file mode 100644 index 0000000000..079e981fc2 --- /dev/null +++ b/app/src/main/res/drawable/ic_wallet_connect_card.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/app/src/main/res/layout/activity_wallet_connect_v2.xml b/app/src/main/res/layout/activity_wallet_connect_v2.xml new file mode 100644 index 0000000000..8e095ce0fb --- /dev/null +++ b/app/src/main/res/layout/activity_wallet_connect_v2.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_action_sheet_sign.xml b/app/src/main/res/layout/dialog_action_sheet_sign.xml index 549eb08bb8..7a30b4187b 100644 --- a/app/src/main/res/layout/dialog_action_sheet_sign.xml +++ b/app/src/main/res/layout/dialog_action_sheet_sign.xml @@ -17,6 +17,11 @@ android:layout_height="wrap_content" custom:label="@string/requester_url" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_chain.xml b/app/src/main/res/layout/item_chain.xml new file mode 100644 index 0000000000..79ce36a2f3 --- /dev/null +++ b/app/src/main/res/layout/item_chain.xml @@ -0,0 +1,27 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_method.xml b/app/src/main/res/layout/item_method.xml new file mode 100644 index 0000000000..9388bfa91f --- /dev/null +++ b/app/src/main/res/layout/item_method.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_sign_data.xml b/app/src/main/res/layout/item_sign_data.xml index 5645a8d63a..4ad89b3b8f 100644 --- a/app/src/main/res/layout/item_sign_data.xml +++ b/app/src/main/res/layout/item_sign_data.xml @@ -42,8 +42,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="start" - tools:text="Message:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337" /> - + tools:text="Message:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337\nMessage:\n Hi Alice!\nA number:\n 1337" + android:textSize="@dimen/sp12"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_wallet_connect_sessions.xml b/app/src/main/res/layout/item_wallet_connect_sessions.xml new file mode 100644 index 0000000000..d398015cf3 --- /dev/null +++ b/app/src/main/res/layout/item_wallet_connect_sessions.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2a6e6a0e8e..65c612b909 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -818,7 +818,7 @@ Unkown Network This dapp is requesting to change to an unknown chain: %1$s - No Active sessions + Sin sesiones activas Connect Wallet La frase de semillas solo puede contener palabras External Link @@ -843,6 +843,12 @@ Use 1559 Transactions Experimental 1559 Transactions Reiniciar + Métodos + Conexiones activas a Dapp basado en navegador + El usuario desconecta la sesión. + Nombre + Billetera + La billetera no existe o es solo reloj Chain ID: %1d Created By Token Standard @@ -880,12 +886,16 @@ under 1 second over 1 second not responding + No se admite la cadena %s. + La red %s debe estar habilitada antes de conectarse. + Select Token + Custom + WalletConnect está activa + Haga clic para ver las sesiones activas Modo de red de prueba ¿Dónde están mis tokens? No te preocupes. Tus tokens están a salvo. Estás viendo redes Testnet. Los desarrolladores los utilizan para probar nuevos diseños. Puede cambiar a Mainnet en cualquier momento. Cambiar a red principal - Select Token - Custom Name Note Connect diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8d9585cd50..b32fcba1f0 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -831,7 +831,7 @@ Unkown Network This dapp is requesting to change to an unknown chain: %1$s - No Active sessions + Aucune session active Connect Wallet La phrase de graine ne peut contenir que des mots External Link @@ -856,6 +856,12 @@ Use 1559 Transactions Experimental 1559 Transactions Réinitialiser + Méthodes + Connexions actives à Dapp basé sur un navigateur + L\'utilisateur déconnecte la session. + Nom + Portefeuille + Le portefeuille n\'existe pas ou il ne s\'agit que d\'une montre Chain ID: %1d Created By Token Standard @@ -893,12 +899,16 @@ under 1 second over 1 second not responding + La chaîne %s n\'est pas prise en charge. + Le réseau %s doit être activé avant la connexion. + Select Token + Custom + WalletConnect est actif + Cliquez pour voir les sessions actives Mode Testnet Où sont mes jetons ? Ne t\'en fais pas. Vos jetons sont en sécurité. Vous visualisez les réseaux Testnet. Ils sont utilisés par les développeurs pour tester de nouveaux designs. Vous pouvez passer à Mainnet à tout moment. Passer au réseau principal - Select Token - Custom Name Note Connect diff --git a/app/src/main/res/values-land/strings.xml b/app/src/main/res/values-land/strings.xml index 76ff0455f3..1f20a793a3 100644 --- a/app/src/main/res/values-land/strings.xml +++ b/app/src/main/res/values-land/strings.xml @@ -3,5 +3,11 @@ Send Multiple Tokens QR scanning requires Android 7.0 (API level 24) or above. Reset + Active connections to browser-based Dapp + User disconnect the session. + Name + Wallet + Wallet not exist or it\'s watch only. + Chain %s is not supported. Testnet mode - \ No newline at end of file + diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 19c793608d..d63e04560f 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -855,7 +855,7 @@ Governance Collectibles Connect Wallet - No Active sessions + အသက်ဝင်သော ဆက်ရှင်များမရှိပါ။ Send Multiple Tokens This dapp is requesting to change to an unknown chain: %1$s @@ -878,6 +878,12 @@ Use 1559 Transactions Experimental 1559 Transactions ပြန်လည်သတ်မှတ်ပါ။ + နည်းလမ်းများ + ဘရောက်ဆာအခြေခံ Dapp သို့ ချိတ်ဆက်မှုများ + အသုံးပြုသူသည် စက်ရှင်ကို ချိတ်ဆက်မှုဖြုတ်သည်။. + နာမည် + ပိုက်ဆံအိတ် + ပိုက်ဆံအိတ် မရှိပါ သို့မဟုတ် ၎င်းသည် နာရီသာဖြစ်သည် Chain ID: %1d Created By Token Standard @@ -915,12 +921,16 @@ under 1 second over 1 second not responding + ကွင်းဆက် %s ကို မပံ့ပိုးပါ။ + မချိတ်ဆက်မီ ကွန်ရက် %s ကို ဖွင့်ထားရပါမည်။ + Select Token + Custom + WalletConnect သည် အသက်ဝင်ပါသည်။ + အသက်ဝင်သော ဆက်ရှင်များကို ကြည့်ရန် နှိပ်ပါ။ Testnet မုဒ် ငါ့တိုကင်များ ဘယ်မှာလဲ စိတ်မပူပါနှင့်။ သင့်တိုကင်များသည် ဘေးကင်းပါသည်။ သင်သည် Testnet ကွန်ရက်များကို ကြည့်ရှုနေပါသည်။ ဒီဇိုင်းအသစ်များကို စမ်းသပ်ရန်အတွက် ၎င်းတို့ကို developer များက အသုံးပြုကြသည်။ သင်သည် အချိန်မရွေး Mainnet သို့ ပြောင်းနိုင်သည်။ Mainnet သို့ပြောင်းပါ။ - Select Token - Custom Name Note Connect diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 2a37abfac5..076e442d94 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -22,6 +22,7 @@ @color/cod @color/dusty @color/cod + @color/mine @color/translucent_dark @color/mercury diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 4c48f446f6..1c3f529efd 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -833,7 +833,7 @@ Unkown Network This dapp is requesting to change to an unknown chain: %1$s - No Active sessions + Không có phiên hoạt động nào Connect Wallet Cụm từ hạt giống chỉ có thể chứa từ External Link @@ -858,6 +858,12 @@ Use 1559 Transactions Experimental 1559 Transactions Cài lại + Phương pháp + Kết nối đang hoạt động với Dapp dựa trên trình duyệt + Người dùng ngắt kết nối phiên. + Tên + Ví tiền + Ví không tồn tại hoặc đó chỉ là đồng hồ Chain ID: %1d Created By Token Standard @@ -895,12 +901,16 @@ under 1 second over 1 second not responding + Chuỗi% s không được hỗ trợ. + Mạng% s phải được bật trước khi kết nối. + Select Token + Custom + WalletConnect đang hoạt động + Nhấp để xem các phiên hoạt động Chế độ testnet Token của tôi ở đâu? Đừng lo. Các mã thông báo của bạn được an toàn. Bạn đang xem các mạng Testnet. Chúng được các nhà phát triển sử dụng để thử các thiết kế mới. Bạn có thể chuyển sang Mainnet bất kỳ lúc nào. Chuyển sang Mainnet - Select Token - Custom Name Note Connect diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 70be1b5cd1..94071aab69 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -818,7 +818,7 @@ Unkown Network This dapp is requesting to change to an unknown chain: %1$s - No Active sessions + 没有活跃会话 Connect Wallet 助记符只能包含单词 External Link @@ -843,6 +843,12 @@ Use 1559 Transactions Experimental 1559 Transactions 重置 + 方法 + 与基于浏览器的 Dapp 的活跃连接 + 用户断开会话. + 名称 + 钱包 + 钱包不存在或者你只能查看钱包 Chain ID: %1d Created By Token Standard @@ -880,12 +886,16 @@ under 1 second over 1 second not responding + 暂不支持链 %s。 + 连接前必须启用网络 %s。 + Select Token + Custom + WalletConnect 处于活动状态 + 点击查看活跃会话 测试网模式 我的代币在哪里? 不用担心,您的代币是安全的。您正在查看 Testnet 网络,开发人员使用它们来尝试新设计。您可以随时切换到主网。 切换到主网 - Select Token - Custom Name Note Connect diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 079fbaad27..379baa0d98 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -111,6 +111,9 @@ + + + @@ -124,8 +127,6 @@ - - diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 1626b4e3a3..fbe541203a 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -66,6 +66,7 @@ @color/dove @color/white + @color/solitude @color/translucent_light @color/transparent diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 130e5d63e3..076c0876ad 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -889,7 +889,7 @@ Unknown Network This dapp is requesting to change to an unknown chain: %1$s - No Active sessions + No active sessions Connect Wallet Seed phrase can only contain words Token # @@ -913,6 +913,13 @@ %1$s%% have this trait Use 1559 Transactions Experimental 1559 Transactions + Methods + WalletConnect + Active connection to browser-based Dapp + User disconnect the session. + Name + Wallet + Wallet not exist or it\'s watch only Chain ID: %1d Created By Token Standard @@ -953,6 +960,10 @@ under 1 second over 1 second not responding + Chain %s is not supported. + Network %s must be enabled before connecting. + WalletConnect is active + Click to view active sessions Testnet Mode Where are my Tokens? Don\'t worry. Your tokens are safe. You are viewing Testnet networks. They are used by developers to try out new designs. You can switch to Mainnet any time. diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9defc3328a..c456b04436 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -198,4 +198,7 @@ @style/Aw.Typography + diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java index 82e0ba8e57..c4b68ca255 100644 --- a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java @@ -83,4 +83,10 @@ public String getCoinbasePayAppId() { return FAKE_KEY_FOR_TESTING; } + + @Override + public String getWalletConnectProjectId() + { + return FAKE_KEY_FOR_TESTING; + } } diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java index 34fb5eddce..b3be351fad 100644 --- a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java @@ -82,4 +82,10 @@ public String getCoinbasePayAppId() { return null; } + + @Override + public String getWalletConnectProjectId() + { + return null; + } } diff --git a/app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerActivityTest.java b/app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerActivityTest.java deleted file mode 100644 index 7d62e9db35..0000000000 --- a/app/src/test/java/com/alphawallet/app/ui/QRScanning/QRScannerActivityTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.alphawallet.app.ui.QRScanning; - -import com.alphawallet.shadows.ShadowRealm; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowToast; - -import androidx.lifecycle.Lifecycle; -import androidx.test.core.app.ActivityScenario; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; - -@RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowRealm.class}) -public class QRScannerActivityTest -{ - - @Test - @Config(sdk = 23) - public void given_api_23_when_onCreate_then_notify_feature_not_supported() - { - try (ActivityScenario scenario = ActivityScenario.launch(QRScannerActivity.class)) - { - assertThat(scenario.getState(), equalTo(Lifecycle.State.DESTROYED)); - assertThat(ShadowToast.getTextOfLatestToast(), equalTo("QR scanning requires Android 7.0 (API level 24) or above.")); - } - } -} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/ui/QRScanning/WalletConnectHelperTest.java b/app/src/test/java/com/alphawallet/app/ui/QRScanning/WalletConnectHelperTest.java new file mode 100644 index 0000000000..54ee7bee04 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/ui/QRScanning/WalletConnectHelperTest.java @@ -0,0 +1,30 @@ +package com.alphawallet.app.ui.QRScanning; + +import com.alphawallet.app.walletconnect.util.WalletConnectHelper; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class WalletConnectHelperTest +{ + @Test + public void testGetChainId() + { + long id = WalletConnectHelper.getChainId("eip155:42"); + assertThat(id, equalTo(42L)); + } + + @Test + public void testIsWalletConnectV1() + { + String textV1 = "wc:2a332c16-a4eb-4691-b2f8-f986d96cd362@1?bridge=https%3A%2F%2Fbridge.walletconnect.org&key=535e4408c9d7897bd89e37dbef79cb72e7a71d6669bb9505ce4158e3d34e67e6"; + assertTrue(WalletConnectHelper.isWalletConnectV1(textV1)); + + String textV2 = "wc:0aff88f09bf3870eda6e5ed2fa5556a67870e2103b71493f30d496e0c7b86f92@2?controller=false&publicKey=30bad0662bf0a411fc423e59a95cb868af9733df759a90bc569620f2b490bc4d&relay=%7B%22protocol%22%3A%22waku%22%7D"; + assertFalse(WalletConnectHelper.isWalletConnectV1(textV2)); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java b/app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java index 55373f1793..601ba0d5ae 100644 --- a/app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java +++ b/app/src/test/java/com/alphawallet/app/viewmodel/HomeViewModelTest.java @@ -6,6 +6,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.alphawallet.app.repository.SharedPreferenceRepository; +import com.alphawallet.shadows.ShadowApp; import com.alphawallet.shadows.ShadowRealm; import org.junit.Before; @@ -15,7 +16,7 @@ import org.robolectric.annotation.Config; @RunWith(AndroidJUnit4.class) -@Config(shadows = {ShadowRealm.class}) +@Config(shadows = {ShadowApp.class, ShadowRealm.class}) public class HomeViewModelTest { private HomeViewModel homeViewModel; @@ -43,4 +44,4 @@ public void should_set_is_new_wallet() homeViewModel.setNewWallet(address, false); assertThat(homeViewModel.checkNewWallet(address), is(false)); } -} \ No newline at end of file +} diff --git a/app/src/test/java/com/alphawallet/app/walletconnect/SignRequestTest.java b/app/src/test/java/com/alphawallet/app/walletconnect/SignRequestTest.java new file mode 100644 index 0000000000..4011a51f2a --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/walletconnect/SignRequestTest.java @@ -0,0 +1,33 @@ +package com.alphawallet.app.walletconnect; + +import com.alphawallet.token.entity.SignMessageType; + +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +public class SignRequestTest +{ + private SignRequest signRequest; + + @Before + public void setUp() throws Exception + { + signRequest = new SignRequest("[0xD0c424B3016E9451109ED97221304DeC639b3F84, 0x4d7920656d61696c206973206a6f686e40646f652e636f6d202d2031363437323235383333333539]"); + } + + @Test + public void testGetWalletAddress() + { + assertThat(signRequest.getWalletAddress(), equalTo("0xD0c424B3016E9451109ED97221304DeC639b3F84")); + } + + @Test + public void testGetSignable() + { + assertThat(signRequest.getSignable().getMessage(), equalTo("0x4d7920656d61696c206973206a6f686e40646f652e636f6d202d2031363437323235383333333539")); + assertThat(signRequest.getSignable().getMessageType(), equalTo(SignMessageType.SIGN_MESSAGE)); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequestTest.java b/app/src/test/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequestTest.java new file mode 100644 index 0000000000..fa5e13a295 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequestTest.java @@ -0,0 +1,35 @@ +package com.alphawallet.app.walletconnect.entity; + +import com.alphawallet.token.entity.SignMessageType; +import com.alphawallet.token.entity.Signable; + +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +public class SignPersonalMessageRequestTest +{ + private SignPersonalMessageRequest request; + + @Before + public void setUp() + { + request = new SignPersonalMessageRequest("[0x4d7920656d61696c206973206a6f686e40646f652e636f6d202d2031363437323232373636323838, 0xD0c424B3016E9451109ED97221304DeC639b3F84]"); + } + + @Test + public void testGetWalletAddress() + { + assertThat(request.getWalletAddress(), equalTo("0xD0c424B3016E9451109ED97221304DeC639b3F84")); + } + + @Test + public void testGetSignable() + { + Signable signable = request.getSignable(); + assertThat(signable.getMessage(), equalTo("0x4d7920656d61696c206973206a6f686e40646f652e636f6d202d2031363437323232373636323838")); + assertThat(signable.getMessageType(), equalTo(SignMessageType.SIGN_PERSONAL_MESSAGE)); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequestTest.java b/app/src/test/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequestTest.java new file mode 100644 index 0000000000..628678c987 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequestTest.java @@ -0,0 +1,32 @@ +package com.alphawallet.app.walletconnect.entity; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.Before; +import org.junit.Test; + +public class SignTypedDataRequestTest +{ + + private SignTypedDataRequest request; + + @Before + public void setUp() + { + String params = "[\"0xD0c424B3016E9451109ED97221304DeC639b3F84\",{\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallet\",\"type\":\"address\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person\"},{\"name\":\"contents\",\"type\":\"string\"}]},\"primaryType\":\"Mail\",\"domain\":{\"name\":\"Ether Mail\",\"version\":\"1\",\"chainId\":1,\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\"},\"message\":{\"from\":{\"name\":\"Cow\",\"wallet\":\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"},\"to\":{\"name\":\"Bob\",\"wallet\":\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\"},\"contents\":\"Hello, Bob!\"}}]"; + request = new SignTypedDataRequest(params); + } + + @Test + public void test_getWalletAddress() + { + assertThat(request.getWalletAddress(), equalTo("0xD0c424B3016E9451109ED97221304DeC639b3F84")); + } + + @Test + public void test_getMessage() + { + assertThat(request.getMessage(), equalTo("{\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallet\",\"type\":\"address\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person\"},{\"name\":\"contents\",\"type\":\"string\"}]},\"primaryType\":\"Mail\",\"domain\":{\"name\":\"Ether Mail\",\"version\":\"1\",\"chainId\":1,\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\"},\"message\":{\"from\":{\"name\":\"Cow\",\"wallet\":\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"},\"to\":{\"name\":\"Bob\",\"wallet\":\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\"},\"contents\":\"Hello, Bob!\"}}")); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/alphawallet/app/walletconnect/entity/WCWCMethodCheckerTest.java b/app/src/test/java/com/alphawallet/app/walletconnect/entity/WCWCMethodCheckerTest.java new file mode 100644 index 0000000000..1e9bf1eb50 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/walletconnect/entity/WCWCMethodCheckerTest.java @@ -0,0 +1,30 @@ +package com.alphawallet.app.walletconnect.entity; + +import com.alphawallet.app.walletconnect.util.WCMethodChecker; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class WCWCMethodCheckerTest +{ + @Test + public void test_includes() + { + assertTrue(WCMethodChecker.includes("wc_sessionRequest")); + assertTrue(WCMethodChecker.includes("wc_sessionUpdate")); + assertTrue(WCMethodChecker.includes("eth_sign")); + assertTrue(WCMethodChecker.includes("personal_sign")); + assertTrue(WCMethodChecker.includes("eth_signTypedData")); + assertTrue(WCMethodChecker.includes("eth_signTransaction")); + assertTrue(WCMethodChecker.includes("eth_sendTransaction")); + assertTrue(WCMethodChecker.includes("get_accounts")); + } + + @Test + public void test_not_includes() + { + assertFalse(WCMethodChecker.includes("wc_not_found")); + } +} diff --git a/app/src/test/java/com/alphawallet/app/web3/Web3ViewClientTest.java b/app/src/test/java/com/alphawallet/app/web3/Web3ViewClientTest.java index 6eff5afe14..5a39da802c 100644 --- a/app/src/test/java/com/alphawallet/app/web3/Web3ViewClientTest.java +++ b/app/src/test/java/com/alphawallet/app/web3/Web3ViewClientTest.java @@ -20,6 +20,7 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.alphawallet.shadows.ShadowApp; import com.alphawallet.shadows.ShadowJsInjectorClient; import com.alphawallet.shadows.ShadowRealm; @@ -39,7 +40,7 @@ import org.robolectric.shadows.ShadowToast; @RunWith(AndroidJUnit4.class) -@Config(shadows = {ShadowRealm.class, ShadowJsInjectorClient.class}) +@Config(shadows = {ShadowApp.class, ShadowRealm.class, ShadowJsInjectorClient.class}) public class Web3ViewClientTest { private static final String PACKAGE_NAME_OF_TELEGRAM = "org.telegram.messenger"; diff --git a/app/src/test/java/com/alphawallet/app/widget/BuyEthOptionsViewTest.java b/app/src/test/java/com/alphawallet/app/widget/BuyEthOptionsViewTest.java index 47f6cfa5b4..6631fbfba0 100644 --- a/app/src/test/java/com/alphawallet/app/widget/BuyEthOptionsViewTest.java +++ b/app/src/test/java/com/alphawallet/app/widget/BuyEthOptionsViewTest.java @@ -9,6 +9,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.alphawallet.app.R; +import com.alphawallet.shadows.ShadowApp; import com.alphawallet.shadows.ShadowRealm; import org.junit.Before; @@ -17,7 +18,7 @@ import org.robolectric.annotation.Config; @RunWith(AndroidJUnit4.class) -@Config(shadows = {ShadowRealm.class}) +@Config(shadows = {ShadowApp.class, ShadowRealm.class}) public class BuyEthOptionsViewTest { private BuyEthOptionsView buyEthOptionsView; @@ -45,4 +46,4 @@ public void testBuyWithCoinbasePay() verify(listener).onClick(buyWithCoinbaseButton); } -} \ No newline at end of file +} diff --git a/app/src/test/java/com/alphawallet/shadows/ShadowWalletConnectClient.kt b/app/src/test/java/com/alphawallet/shadows/ShadowWalletConnectClient.kt new file mode 100644 index 0000000000..c8195d410b --- /dev/null +++ b/app/src/test/java/com/alphawallet/shadows/ShadowWalletConnectClient.kt @@ -0,0 +1,26 @@ +@file:Suppress("UnusedPrivateMember") + +package com.alphawallet.shadows + +import com.walletconnect.android.internal.common.exception.WalletConnectException +import com.walletconnect.sign.client.Sign +import com.walletconnect.sign.client.SignClient +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements + +@Implements(SignClient::class) +class ShadowWalletConnectClient { + constructor() {} + + @Implementation + @Throws(IllegalStateException::class) + fun setWalletDelegate(delegate: SignClient.WalletDelegate) {} + + @Implementation + fun initialize( + initial: Sign.Params.Init, + onError: (WalletConnectException) -> Unit = {} + ) = with(initial) { + + } +} diff --git a/app/src/test/resources/robolectric.properties b/app/src/test/resources/robolectric.properties new file mode 100644 index 0000000000..9462318baf --- /dev/null +++ b/app/src/test/resources/robolectric.properties @@ -0,0 +1 @@ +sdk=31 \ No newline at end of file diff --git a/e2e.sh b/e2e.sh index 801dd7b93b..b764207d42 100755 --- a/e2e.sh +++ b/e2e.sh @@ -45,4 +45,4 @@ fi cp -r app/build/reports/androidTests/connected/flavors/noAnalytics/ output/html stopGanache -exit 1 \ No newline at end of file +exit 1 diff --git a/gradle.properties b/gradle.properties index 6030110a80..dcb67f2cfc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,6 +5,7 @@ # MaxMetaspaceSize=256m should be sufficent but this project has grown # bigger than typical. android.enableJetifier=true +android.jetifier.ignorelist=bcprov-jdk15on,com.squareup.moshi android.useAndroidX=true org.gradle.jvmargs=-Xms2048m -Xmx4096m android.suppressUnsupportedCompileSdk=32 @@ -13,4 +14,4 @@ android.suppressUnsupportedCompileSdk=32 # Make sure only check read:packages and read:user permissions if you want to create your own PAT, # and encode it with Base64 encoder https://www.base64encoder.io/ gpr.user=smarttokenlabs@hotmail.com -gpr.key=Z2hwX3NFR09PbXRkOFQ2M09RcEdmY0xvR1VXTVJ6ODJBSDAxWWQ4OA== \ No newline at end of file +gpr.key=Z2hwX3NFR09PbXRkOFQ2M09RcEdmY0xvR1VXTVJ6ODJBSDAxWWQ4OA== diff --git a/lib/src/main/java/com/alphawallet/token/entity/EthereumMessage.java b/lib/src/main/java/com/alphawallet/token/entity/EthereumMessage.java index f81da30576..7e47aa2021 100644 --- a/lib/src/main/java/com/alphawallet/token/entity/EthereumMessage.java +++ b/lib/src/main/java/com/alphawallet/token/entity/EthereumMessage.java @@ -44,7 +44,8 @@ private byte[] getEthereumMessage(String message) { } byte[] result; - if (messageType == SignMessageType.SIGN_PERSONAL_MESSAGE) + if (messageType == SignMessageType.SIGN_PERSONAL_MESSAGE + || messageType == SignMessageType.SIGN_MESSAGE) { byte[] prefix = getEthereumMessagePrefix(encodedMessage.length); diff --git a/lib/src/main/java/com/alphawallet/token/entity/EthereumTypedMessage.java b/lib/src/main/java/com/alphawallet/token/entity/EthereumTypedMessage.java index 927a8ce68d..ba07c87b60 100644 --- a/lib/src/main/java/com/alphawallet/token/entity/EthereumTypedMessage.java +++ b/lib/src/main/java/com/alphawallet/token/entity/EthereumTypedMessage.java @@ -9,7 +9,8 @@ import static com.alphawallet.token.entity.MessageUtils.encodeParams; import static com.alphawallet.token.entity.MessageUtils.encodeValues; -public class EthereumTypedMessage implements Signable { +public class EthereumTypedMessage implements Signable +{ byte[] structuredData; String displayOrigin; @@ -17,7 +18,8 @@ public class EthereumTypedMessage implements Signable { CharSequence userMessage; SignMessageType messageType; - public EthereumTypedMessage(byte[] value, CharSequence userMessage, String displayOrigin, long leafPosition) { + public EthereumTypedMessage(byte[] value, CharSequence userMessage, String displayOrigin, long leafPosition) + { this.structuredData = value; this.displayOrigin = displayOrigin; this.leafPosition = leafPosition; @@ -27,23 +29,16 @@ public EthereumTypedMessage(byte[] value, CharSequence userMessage, String displ public EthereumTypedMessage(String messageData, String domainName, long callbackId, CryptoFunctionsInterface cryptoFunctions) { + try { try { - ProviderTypedData[] rawData = new Gson().fromJson(messageData, ProviderTypedData[].class); - ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(); - writeBuffer.write(cryptoFunctions.keccak256(encodeParams(rawData))); - writeBuffer.write(cryptoFunctions.keccak256(encodeValues(rawData))); - this.userMessage = cryptoFunctions.formatTypedMessage(rawData); - this.structuredData = writeBuffer.toByteArray(); - messageType = SignMessageType.SIGN_TYPED_DATA; + parseV1(messageData, cryptoFunctions); } catch (JsonSyntaxException e) { - this.structuredData = cryptoFunctions.getStructuredData(messageData); - this.userMessage = cryptoFunctions.formatEIP721Message(messageData); - messageType = SignMessageType.SIGN_TYPED_DATA_V3; + parseV3(messageData, cryptoFunctions); } } catch (IOException e) @@ -57,16 +52,37 @@ public EthereumTypedMessage(String messageData, String domainName, long callback this.leafPosition = callbackId; } + private void parseV3(String messageData, CryptoFunctionsInterface cryptoFunctions) + { + this.structuredData = cryptoFunctions.getStructuredData(messageData); + this.userMessage = cryptoFunctions.formatEIP721Message(messageData); + messageType = SignMessageType.SIGN_TYPED_DATA_V3; + } + + private void parseV1(String messageData, CryptoFunctionsInterface cryptoFunctions) throws IOException + { + ProviderTypedData[] rawData = new Gson().fromJson(messageData, ProviderTypedData[].class); + ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(); + writeBuffer.write(cryptoFunctions.keccak256(encodeParams(rawData))); + writeBuffer.write(cryptoFunctions.keccak256(encodeValues(rawData))); + this.userMessage = cryptoFunctions.formatTypedMessage(rawData); + this.structuredData = writeBuffer.toByteArray(); + messageType = SignMessageType.SIGN_TYPED_DATA; + } + // User message is the text shown in the popup window - note CharSequence is used because message contains text formatting - public CharSequence getUserMessage() { + public CharSequence getUserMessage() + { return userMessage; } - public long getCallbackId() { + public long getCallbackId() + { return this.leafPosition; } - public byte[] getPrehash() { + public byte[] getPrehash() + { return structuredData; } @@ -87,4 +103,4 @@ public SignMessageType getMessageType() { return messageType; } -} \ No newline at end of file +} diff --git a/lib/src/main/java/com/alphawallet/token/entity/SignMessageType.java b/lib/src/main/java/com/alphawallet/token/entity/SignMessageType.java index 7c26a7fc82..2b8c0a6076 100644 --- a/lib/src/main/java/com/alphawallet/token/entity/SignMessageType.java +++ b/lib/src/main/java/com/alphawallet/token/entity/SignMessageType.java @@ -10,6 +10,6 @@ public enum SignMessageType SIGN_PERSONAL_MESSAGE, SIGN_TYPED_DATA, SIGN_TYPED_DATA_V3, - SIGN_TYPES_DATA_V4, + SIGN_TYPED_DATA_V4, ATTESTATION } From f26a4685365ded46e3eb1d5ba3ad5ca134aeb9a9 Mon Sep 17 00:00:00 2001 From: James Brown Date: Sat, 19 Nov 2022 19:32:05 +1100 Subject: [PATCH 152/183] Fix merge issue --- .../walletconnect/WalletConnectSessionItem.java | 11 ++++++++--- app/src/main/res/raw/token_anim.data | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectSessionItem.java b/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectSessionItem.java index a3c65ee7a6..8e0e48c195 100644 --- a/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectSessionItem.java +++ b/app/src/main/java/com/alphawallet/app/entity/walletconnect/WalletConnectSessionItem.java @@ -10,9 +10,9 @@ public class WalletConnectSessionItem public String name = ""; public String url = ""; public String icon = ""; - public final String sessionId; - public final String localSessionId; - public final long chainId; + public String sessionId; + public String localSessionId; + public long chainId; public WalletConnectSessionItem(RealmWCSession s) { @@ -26,4 +26,9 @@ public WalletConnectSessionItem(RealmWCSession s) localSessionId = s.getSessionId(); chainId = s.getChainId() == 0 ? 1 : s.getChainId(); //older sessions without chainId set must be mainnet } + + public WalletConnectSessionItem() + { + + } } diff --git a/app/src/main/res/raw/token_anim.data b/app/src/main/res/raw/token_anim.data index 927ff79c4a..20bca12c08 100644 --- a/app/src/main/res/raw/token_anim.data +++ b/app/src/main/res/raw/token_anim.data @@ -20,7 +20,7 @@

-
From e754b431c708e5fb6aa84a926fb0c1f8fab3ae14 Mon Sep 17 00:00:00 2001 From: James Brown Date: Sun, 20 Nov 2022 11:24:38 +1100 Subject: [PATCH 153/183] Fix crashbug and update gradle for release update. --- app/build.gradle | 4 +-- .../app/ui/WalletConnectSessionActivity.java | 26 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b133472ba1..f18635a838 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -85,8 +85,8 @@ android { } } defaultConfig { - versionCode 205 - versionName "3.61" + versionCode 218 + versionName "3.60.3" applicationId "io.stormbird.wallet" minSdkVersion 24 diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java index e5f8986736..9b22bb4512 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java @@ -55,7 +55,7 @@ public class WalletConnectSessionActivity extends BaseActivity { private final Handler handler = new Handler(Looper.getMainLooper()); - private final LocalBroadcastManager broadcastManager; + private LocalBroadcastManager broadcastManager; WalletConnectViewModel viewModel; private RecyclerView recyclerView; private Button btnConnectWallet; @@ -78,11 +78,6 @@ public void onReceive(Context context, Intent intent) @Inject AWWalletConnectClient awWalletConnectClient; - public WalletConnectSessionActivity() - { - broadcastManager = LocalBroadcastManager.getInstance(getApplicationContext()); - } - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -108,6 +103,11 @@ private void initViewModel() .get(WalletConnectViewModel.class); viewModel.serviceReady().observe(this, this::onServiceReady); } + + if (broadcastManager == null) + { + broadcastManager = LocalBroadcastManager.getInstance(getApplicationContext()); + } } private void onServiceReady(Boolean aBoolean) @@ -123,13 +123,6 @@ private void onServiceReady(Boolean aBoolean) } } - @Override - public void onPause() - { - super.onPause(); - stopConnectionCheck(); - } - private void setupList() { wcSessions = viewModel.getSessions(); @@ -173,6 +166,13 @@ public void onResume() viewModel.track(Analytics.Navigation.WALLET_CONNECT_SESSIONS); } + @Override + public void onPause() + { + super.onPause(); + stopConnectionCheck(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { From c980f1c9828ac9d4f2fa4eea6f68734e5c2a72c8 Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 28 Nov 2022 12:20:51 +1100 Subject: [PATCH 154/183] Refactor Sign Dialogs (#2962) * Move Signing operation from ActionSheetDialog into new dedicated ActionSheetSignDialog * Complete the refactoring work for the self-contained Signing dialog. * Fix build issue in test and clean up some formatting issues. * Fix checkstyle * Modify the interface and de-duplicate --- .editorconfig | 899 ------------------ .github/checkstyle-rules.xml | 16 +- .../app/entity/ActionSheetInterface.java | 51 + .../entity/SignAuthenticationCallback.java | 5 +- .../interact/CreateTransactionInteract.java | 10 +- .../app/interact/GenericWalletInteract.java | 10 +- .../app/repository/TransactionRepository.java | 529 ++++++----- .../repository/TransactionRepositoryType.java | 31 +- .../app/service/AccountKeystoreService.java | 8 +- .../app/service/KeystoreAccountService.java | 179 ++-- .../app/ui/AssetDisplayActivity.java | 10 +- .../com/alphawallet/app/ui/BaseActivity.java | 23 +- .../app/ui/DappBrowserFragment.java | 77 +- .../alphawallet/app/ui/FunctionActivity.java | 61 +- .../com/alphawallet/app/ui/HomeActivity.java | 104 +- .../alphawallet/app/ui/NFTAssetsFragment.java | 2 +- .../app/ui/WalletConnectActivity.java | 102 +- .../adapter/NonFungibleTokenAdapter.java | 38 +- .../ui/widget/entity/ActionSheetCallback.java | 40 +- .../app/viewmodel/ApiV1ViewModel.java | 4 +- .../app/viewmodel/DappBrowserViewModel.java | 13 - .../RedeemSignatureDisplayModel.java | 2 +- .../app/viewmodel/SellDetailViewModel.java | 10 +- .../app/viewmodel/SignDialogViewModel.java | 86 ++ .../app/viewmodel/TokenFunctionViewModel.java | 11 - .../TransferTicketDetailViewModel.java | 4 +- .../app/viewmodel/WalletConnectViewModel.java | 3 +- .../SignMethodDialogViewModel.java | 128 --- .../walletconnect/AWWalletConnectClient.java | 83 +- .../WalletConnectV2SessionRequestHandler.java | 73 +- .../app/walletconnect/entity/BaseRequest.java | 5 + .../walletconnect/entity/EthSignRequest.java | 33 + .../entity/SignPersonalMessageRequest.java | 6 + .../{ => entity}/SignRequest.java | 10 +- .../entity/SignTypedDataRequest.java | 6 + .../walletconnect/util/WCMethodChecker.java | 1 - .../util/WalletConnectHelper.java | 2 +- .../alphawallet/app/web3/Web3TokenView.java | 21 +- .../app/web3/entity/FunctionCallback.java | 4 - .../alphawallet/app/widget/ActionSheet.java | 53 ++ .../app/widget/ActionSheetDialog.java | 209 +--- .../app/widget/ActionSheetSignDialog.java | 157 +++ .../app/widget/ConfirmationWidget.java | 55 +- .../app/widget/SignDataWidget.java | 9 - .../app/widget/SignMethodDialog.java | 188 ---- .../app/widget/SignTransactionDialog.java | 6 +- .../res/layout/activity_wallet_connect_v2.xml | 4 +- .../layout/dialog_action_sheet_message.xml | 31 - .../res/layout/dialog_action_sheet_sign.xml | 7 +- app/src/main/res/layout/item_ticket.xml | 7 - .../java/com/alphawallet/app/ENSTest.java | 5 +- .../com/alphawallet/app/QRSelectionTest.java | 6 +- .../app/walletconnect/SignRequestTest.java | 9 +- 53 files changed, 1239 insertions(+), 2207 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/SignDialogViewModel.java delete mode 100644 app/src/main/java/com/alphawallet/app/viewmodel/walletconnect/SignMethodDialogViewModel.java create mode 100644 app/src/main/java/com/alphawallet/app/walletconnect/entity/EthSignRequest.java rename app/src/main/java/com/alphawallet/app/walletconnect/{ => entity}/SignRequest.java (69%) create mode 100644 app/src/main/java/com/alphawallet/app/widget/ActionSheet.java create mode 100644 app/src/main/java/com/alphawallet/app/widget/ActionSheetSignDialog.java delete mode 100644 app/src/main/java/com/alphawallet/app/widget/SignMethodDialog.java delete mode 100644 app/src/main/res/layout/dialog_action_sheet_message.xml diff --git a/.editorconfig b/.editorconfig index 6c31af5522..e857f5be57 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,902 +13,3 @@ ij_formatter_tags_enabled = false ij_smart_tabs = false ij_visual_guides = none ij_wrap_on_typing = false - -[*.java] -ij_java_align_consecutive_assignments = false -ij_java_align_consecutive_variable_declarations = false -ij_java_align_group_field_declarations = false -ij_java_align_multiline_annotation_parameters = false -ij_java_align_multiline_array_initializer_expression = false -ij_java_align_multiline_assignment = false -ij_java_align_multiline_binary_operation = false -ij_java_align_multiline_chained_methods = false -ij_java_align_multiline_extends_list = false -ij_java_align_multiline_for = true -ij_java_align_multiline_method_parentheses = false -ij_java_align_multiline_parameters = true -ij_java_align_multiline_parameters_in_calls = false -ij_java_align_multiline_parenthesized_expression = false -ij_java_align_multiline_records = true -ij_java_align_multiline_resources = true -ij_java_align_multiline_ternary_operation = false -ij_java_align_multiline_text_blocks = false -ij_java_align_multiline_throws_list = false -ij_java_align_subsequent_simple_methods = false -ij_java_align_throws_keyword = false -ij_java_annotation_parameter_wrap = off -ij_java_array_initializer_new_line_after_left_brace = false -ij_java_array_initializer_right_brace_on_new_line = false -ij_java_array_initializer_wrap = off -ij_java_assert_statement_colon_on_next_line = false -ij_java_assert_statement_wrap = off -ij_java_assignment_wrap = off -ij_java_binary_operation_sign_on_next_line = false -ij_java_binary_operation_wrap = off -ij_java_blank_lines_after_anonymous_class_header = 0 -ij_java_blank_lines_after_class_header = 0 -ij_java_blank_lines_after_imports = 1 -ij_java_blank_lines_after_package = 1 -ij_java_blank_lines_around_class = 1 -ij_java_blank_lines_around_field = 0 -ij_java_blank_lines_around_field_in_interface = 0 -ij_java_blank_lines_around_initializer = 1 -ij_java_blank_lines_around_method = 1 -ij_java_blank_lines_around_method_in_interface = 1 -ij_java_blank_lines_before_class_end = 0 -ij_java_blank_lines_before_imports = 1 -ij_java_blank_lines_before_method_body = 0 -ij_java_blank_lines_before_package = 0 -ij_java_block_brace_style = next_line -ij_java_block_comment_at_first_column = true -ij_java_builder_methods = none -ij_java_call_parameters_new_line_after_left_paren = false -ij_java_call_parameters_right_paren_on_new_line = false -ij_java_call_parameters_wrap = off -ij_java_case_statement_on_separate_line = true -ij_java_catch_on_new_line = true -ij_java_class_annotation_wrap = split_into_lines -ij_java_class_brace_style = next_line -ij_java_class_count_to_use_import_on_demand = 99 -ij_java_class_names_in_javadoc = 1 -ij_java_do_not_indent_top_level_class_members = false -ij_java_do_not_wrap_after_single_annotation = false -ij_java_do_while_brace_force = always -ij_java_doc_add_blank_line_after_description = true -ij_java_doc_add_blank_line_after_param_comments = false -ij_java_doc_add_blank_line_after_return = false -ij_java_doc_add_p_tag_on_empty_lines = true -ij_java_doc_align_exception_comments = true -ij_java_doc_align_param_comments = true -ij_java_doc_do_not_wrap_if_one_line = false -ij_java_doc_enable_formatting = true -ij_java_doc_enable_leading_asterisks = true -ij_java_doc_indent_on_continuation = false -ij_java_doc_keep_empty_lines = true -ij_java_doc_keep_empty_parameter_tag = true -ij_java_doc_keep_empty_return_tag = true -ij_java_doc_keep_empty_throws_tag = true -ij_java_doc_keep_invalid_tags = true -ij_java_doc_param_description_on_new_line = false -ij_java_doc_preserve_line_breaks = false -ij_java_doc_use_throws_not_exception_tag = true -ij_java_else_on_new_line = true -ij_java_enum_constants_wrap = off -ij_java_extends_keyword_wrap = off -ij_java_extends_list_wrap = off -ij_java_field_annotation_wrap = split_into_lines -ij_java_finally_on_new_line = true -ij_java_for_brace_force = never -ij_java_for_statement_new_line_after_left_paren = false -ij_java_for_statement_right_paren_on_new_line = false -ij_java_for_statement_wrap = off -ij_java_generate_final_locals = false -ij_java_generate_final_parameters = false -ij_java_if_brace_force = never -ij_java_imports_layout = $android.**,$androidx.**,$com.**,$junit.**,$net.**,$org.**,$java.**,$javax.**,$*,|,android.**,|,androidx.**,|,com.**,|,junit.**,|,net.**,|,org.**,|,java.**,|,javax.**,|,*,| -ij_java_indent_case_from_switch = true -ij_java_insert_inner_class_imports = false -ij_java_insert_override_annotation = true -ij_java_keep_blank_lines_before_right_brace = 2 -ij_java_keep_blank_lines_between_package_declaration_and_header = 2 -ij_java_keep_blank_lines_in_code = 2 -ij_java_keep_blank_lines_in_declarations = 2 -ij_java_keep_builder_methods_indents = false -ij_java_keep_control_statement_in_one_line = true -ij_java_keep_first_column_comment = true -ij_java_keep_indents_on_empty_lines = false -ij_java_keep_line_breaks = true -ij_java_keep_multiple_expressions_in_one_line = false -ij_java_keep_simple_blocks_in_one_line = false -ij_java_keep_simple_classes_in_one_line = false -ij_java_keep_simple_lambdas_in_one_line = true -ij_java_keep_simple_methods_in_one_line = false -ij_java_label_indent_absolute = false -ij_java_label_indent_size = 0 -ij_java_lambda_brace_style = end_of_line -ij_java_layout_static_imports_separately = true -ij_java_line_comment_add_space = false -ij_java_line_comment_at_first_column = true -ij_java_method_annotation_wrap = split_into_lines -ij_java_method_brace_style = next_line -ij_java_method_call_chain_wrap = off -ij_java_method_parameters_new_line_after_left_paren = false -ij_java_method_parameters_right_paren_on_new_line = false -ij_java_method_parameters_wrap = off -ij_java_modifier_list_wrap = false -ij_java_names_count_to_use_import_on_demand = 99 -ij_java_new_line_after_lparen_in_record_header = false -ij_java_parameter_annotation_wrap = off -ij_java_parentheses_expression_new_line_after_left_paren = false -ij_java_parentheses_expression_right_paren_on_new_line = false -ij_java_place_assignment_sign_on_next_line = false -ij_java_prefer_longer_names = true -ij_java_prefer_parameters_wrap = false -ij_java_record_components_wrap = normal -ij_java_repeat_synchronized = true -ij_java_replace_instanceof_and_cast = false -ij_java_replace_null_check = true -ij_java_replace_sum_lambda_with_method_ref = true -ij_java_resource_list_new_line_after_left_paren = false -ij_java_resource_list_right_paren_on_new_line = false -ij_java_resource_list_wrap = off -ij_java_rparen_on_new_line_in_record_header = false -ij_java_space_after_closing_angle_bracket_in_type_argument = false -ij_java_space_after_colon = true -ij_java_space_after_comma = true -ij_java_space_after_comma_in_type_arguments = true -ij_java_space_after_for_semicolon = true -ij_java_space_after_quest = true -ij_java_space_after_type_cast = true -ij_java_space_before_annotation_array_initializer_left_brace = false -ij_java_space_before_annotation_parameter_list = false -ij_java_space_before_array_initializer_left_brace = false -ij_java_space_before_catch_keyword = true -ij_java_space_before_catch_left_brace = true -ij_java_space_before_catch_parentheses = true -ij_java_space_before_class_left_brace = true -ij_java_space_before_colon = true -ij_java_space_before_colon_in_foreach = true -ij_java_space_before_comma = false -ij_java_space_before_do_left_brace = true -ij_java_space_before_else_keyword = true -ij_java_space_before_else_left_brace = true -ij_java_space_before_finally_keyword = true -ij_java_space_before_finally_left_brace = true -ij_java_space_before_for_left_brace = true -ij_java_space_before_for_parentheses = true -ij_java_space_before_for_semicolon = false -ij_java_space_before_if_left_brace = true -ij_java_space_before_if_parentheses = true -ij_java_space_before_method_call_parentheses = false -ij_java_space_before_method_left_brace = true -ij_java_space_before_method_parentheses = false -ij_java_space_before_opening_angle_bracket_in_type_parameter = false -ij_java_space_before_quest = true -ij_java_space_before_switch_left_brace = true -ij_java_space_before_switch_parentheses = true -ij_java_space_before_synchronized_left_brace = true -ij_java_space_before_synchronized_parentheses = true -ij_java_space_before_try_left_brace = true -ij_java_space_before_try_parentheses = true -ij_java_space_before_type_parameter_list = false -ij_java_space_before_while_keyword = true -ij_java_space_before_while_left_brace = true -ij_java_space_before_while_parentheses = true -ij_java_space_inside_one_line_enum_braces = false -ij_java_space_within_empty_array_initializer_braces = false -ij_java_space_within_empty_method_call_parentheses = false -ij_java_space_within_empty_method_parentheses = false -ij_java_spaces_around_additive_operators = true -ij_java_spaces_around_assignment_operators = true -ij_java_spaces_around_bitwise_operators = true -ij_java_spaces_around_equality_operators = true -ij_java_spaces_around_lambda_arrow = true -ij_java_spaces_around_logical_operators = true -ij_java_spaces_around_method_ref_dbl_colon = false -ij_java_spaces_around_multiplicative_operators = true -ij_java_spaces_around_relational_operators = true -ij_java_spaces_around_shift_operators = true -ij_java_spaces_around_type_bounds_in_type_parameters = true -ij_java_spaces_around_unary_operator = false -ij_java_spaces_within_angle_brackets = false -ij_java_spaces_within_annotation_parentheses = false -ij_java_spaces_within_array_initializer_braces = false -ij_java_spaces_within_braces = false -ij_java_spaces_within_brackets = false -ij_java_spaces_within_cast_parentheses = false -ij_java_spaces_within_catch_parentheses = false -ij_java_spaces_within_for_parentheses = false -ij_java_spaces_within_if_parentheses = false -ij_java_spaces_within_method_call_parentheses = false -ij_java_spaces_within_method_parentheses = false -ij_java_spaces_within_parentheses = false -ij_java_spaces_within_record_header = false -ij_java_spaces_within_switch_parentheses = false -ij_java_spaces_within_synchronized_parentheses = false -ij_java_spaces_within_try_parentheses = false -ij_java_spaces_within_while_parentheses = false -ij_java_special_else_if_treatment = true -ij_java_subclass_name_suffix = Impl -ij_java_ternary_operation_signs_on_next_line = false -ij_java_ternary_operation_wrap = off -ij_java_test_name_suffix = Test -ij_java_throws_keyword_wrap = off -ij_java_throws_list_wrap = off -ij_java_use_external_annotations = false -ij_java_use_fq_class_names = false -ij_java_use_relative_indents = false -ij_java_use_single_class_imports = true -ij_java_variable_annotation_wrap = off -ij_java_visibility = public -ij_java_while_brace_force = never -ij_java_while_on_new_line = true -ij_java_wrap_comments = false -ij_java_wrap_first_method_in_call_chain = false -ij_java_wrap_long_lines = false - -[*.properties] -ij_properties_align_group_field_declarations = false -ij_properties_keep_blank_lines = false -ij_properties_key_value_delimiter = equals -ij_properties_spaces_around_key_value_delimiter = false - -[.editorconfig] -ij_editorconfig_align_group_field_declarations = false -ij_editorconfig_space_after_colon = false -ij_editorconfig_space_after_comma = true -ij_editorconfig_space_before_colon = false -ij_editorconfig_space_before_comma = false -ij_editorconfig_spaces_around_assignment_operators = true - -[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}] -ij_continuation_indent_size = 4 -ij_xml_align_attributes = false -ij_xml_align_text = false -ij_xml_attribute_wrap = normal -ij_xml_block_comment_at_first_column = true -ij_xml_keep_blank_lines = 2 -ij_xml_keep_indents_on_empty_lines = false -ij_xml_keep_line_breaks = false -ij_xml_keep_line_breaks_in_text = true -ij_xml_keep_whitespaces = false -ij_xml_keep_whitespaces_around_cdata = preserve -ij_xml_keep_whitespaces_inside_cdata = false -ij_xml_line_comment_at_first_column = true -ij_xml_space_after_tag_name = false -ij_xml_space_around_equals_in_attribute = false -ij_xml_space_inside_empty_tag = true -ij_xml_text_wrap = normal -ij_xml_use_custom_settings = true - -[{*.bash,*.sh,*.zsh}] -indent_size = 2 -tab_width = 2 -ij_shell_binary_ops_start_line = false -ij_shell_keep_column_alignment_padding = false -ij_shell_minify_program = false -ij_shell_redirect_followed_by_space = false -ij_shell_switch_cases_indented = false -ij_shell_use_unix_line_separator = true - -[{*.c,*.c++,*.cc,*.cp,*.cpp,*.cu,*.cuh,*.cxx,*.h,*.h++,*.hh,*.hp,*.hpp,*.hxx,*.i,*.icc,*.ii,*.inl,*.ino,*.ipp,*.m,*.mm,*.pch,*.tcc,*.tpp}] -ij_c_add_brief_tag = false -ij_c_add_getter_prefix = true -ij_c_add_setter_prefix = true -ij_c_align_dictionary_pair_values = false -ij_c_align_group_field_declarations = false -ij_c_align_init_list_in_columns = true -ij_c_align_multiline_array_initializer_expression = true -ij_c_align_multiline_assignment = true -ij_c_align_multiline_binary_operation = true -ij_c_align_multiline_chained_methods = false -ij_c_align_multiline_for = true -ij_c_align_multiline_ternary_operation = true -ij_c_array_initializer_comma_on_next_line = false -ij_c_array_initializer_new_line_after_left_brace = false -ij_c_array_initializer_right_brace_on_new_line = false -ij_c_array_initializer_wrap = normal -ij_c_assignment_wrap = off -ij_c_binary_operation_sign_on_next_line = false -ij_c_binary_operation_wrap = normal -ij_c_blank_lines_after_class_header = 0 -ij_c_blank_lines_after_imports = 1 -ij_c_blank_lines_around_class = 1 -ij_c_blank_lines_around_field = 0 -ij_c_blank_lines_around_field_in_interface = 0 -ij_c_blank_lines_around_method = 1 -ij_c_blank_lines_around_method_in_interface = 1 -ij_c_blank_lines_around_namespace = 0 -ij_c_blank_lines_around_properties_in_declaration = 0 -ij_c_blank_lines_around_properties_in_interface = 0 -ij_c_blank_lines_before_imports = 1 -ij_c_blank_lines_before_method_body = 0 -ij_c_block_brace_placement = end_of_line -ij_c_block_brace_style = end_of_line -ij_c_block_comment_at_first_column = true -ij_c_catch_on_new_line = false -ij_c_class_brace_style = end_of_line -ij_c_class_constructor_init_list_align_multiline = true -ij_c_class_constructor_init_list_comma_on_next_line = false -ij_c_class_constructor_init_list_new_line_after_colon = never -ij_c_class_constructor_init_list_new_line_before_colon = if_long -ij_c_class_constructor_init_list_wrap = normal -ij_c_copy_is_deep = false -ij_c_create_interface_for_categories = true -ij_c_declare_generated_methods = true -ij_c_description_include_member_names = true -ij_c_discharged_short_ternary_operator = false -ij_c_do_not_add_breaks = false -ij_c_do_while_brace_force = never -ij_c_else_on_new_line = false -ij_c_enum_constants_comma_on_next_line = false -ij_c_enum_constants_wrap = on_every_item -ij_c_for_brace_force = never -ij_c_for_statement_new_line_after_left_paren = false -ij_c_for_statement_right_paren_on_new_line = false -ij_c_for_statement_wrap = off -ij_c_function_brace_placement = end_of_line -ij_c_function_call_arguments_align_multiline = true -ij_c_function_call_arguments_align_multiline_pars = false -ij_c_function_call_arguments_comma_on_next_line = false -ij_c_function_call_arguments_new_line_after_lpar = false -ij_c_function_call_arguments_new_line_before_rpar = false -ij_c_function_call_arguments_wrap = normal -ij_c_function_non_top_after_return_type_wrap = normal -ij_c_function_parameters_align_multiline = true -ij_c_function_parameters_align_multiline_pars = false -ij_c_function_parameters_comma_on_next_line = false -ij_c_function_parameters_new_line_after_lpar = false -ij_c_function_parameters_new_line_before_rpar = false -ij_c_function_parameters_wrap = normal -ij_c_function_top_after_return_type_wrap = normal -ij_c_generate_additional_eq_operators = true -ij_c_generate_additional_rel_operators = true -ij_c_generate_class_constructor = true -ij_c_generate_comparison_operators_use_std_tie = false -ij_c_generate_instance_variables_for_properties = ask -ij_c_generate_operators_as_members = true -ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT} -ij_c_if_brace_force = never -ij_c_in_line_short_ternary_operator = true -ij_c_indent_block_comment = true -ij_c_indent_c_struct_members = 4 -ij_c_indent_case_from_switch = true -ij_c_indent_class_members = 4 -ij_c_indent_directive_as_code = false -ij_c_indent_implementation_members = 0 -ij_c_indent_inside_code_block = 4 -ij_c_indent_interface_members = 0 -ij_c_indent_interface_members_except_ivars_block = false -ij_c_indent_namespace_members = 4 -ij_c_indent_preprocessor_directive = 0 -ij_c_indent_visibility_keywords = 0 -ij_c_insert_override = true -ij_c_insert_virtual_with_override = false -ij_c_introduce_auto_vars = false -ij_c_introduce_const_params = false -ij_c_introduce_const_vars = false -ij_c_introduce_generate_property = false -ij_c_introduce_generate_synthesize = true -ij_c_introduce_globals_to_header = true -ij_c_introduce_prop_to_private_category = false -ij_c_introduce_static_consts = true -ij_c_introduce_use_ns_types = false -ij_c_ivars_prefix = _ -ij_c_keep_blank_lines_before_end = 2 -ij_c_keep_blank_lines_before_right_brace = 2 -ij_c_keep_blank_lines_in_code = 2 -ij_c_keep_blank_lines_in_declarations = 2 -ij_c_keep_case_expressions_in_one_line = false -ij_c_keep_control_statement_in_one_line = true -ij_c_keep_directive_at_first_column = true -ij_c_keep_first_column_comment = true -ij_c_keep_line_breaks = true -ij_c_keep_nested_namespaces_in_one_line = false -ij_c_keep_simple_blocks_in_one_line = true -ij_c_keep_simple_methods_in_one_line = true -ij_c_keep_structures_in_one_line = false -ij_c_lambda_capture_list_align_multiline = false -ij_c_lambda_capture_list_align_multiline_bracket = false -ij_c_lambda_capture_list_comma_on_next_line = false -ij_c_lambda_capture_list_new_line_after_lbracket = false -ij_c_lambda_capture_list_new_line_before_rbracket = false -ij_c_lambda_capture_list_wrap = off -ij_c_line_comment_add_space = false -ij_c_line_comment_at_first_column = true -ij_c_method_brace_placement = end_of_line -ij_c_method_call_arguments_align_by_colons = true -ij_c_method_call_arguments_align_multiline = false -ij_c_method_call_arguments_special_dictionary_pairs_treatment = true -ij_c_method_call_arguments_wrap = off -ij_c_method_call_chain_wrap = off -ij_c_method_parameters_align_by_colons = true -ij_c_method_parameters_align_multiline = false -ij_c_method_parameters_wrap = off -ij_c_namespace_brace_placement = end_of_line -ij_c_parentheses_expression_new_line_after_left_paren = false -ij_c_parentheses_expression_right_paren_on_new_line = false -ij_c_place_assignment_sign_on_next_line = false -ij_c_property_nonatomic = true -ij_c_put_ivars_to_implementation = true -ij_c_refactor_compatibility_aliases_and_classes = true -ij_c_refactor_properties_and_ivars = true -ij_c_release_style = ivar -ij_c_retain_object_parameters_in_constructor = true -ij_c_semicolon_after_method_signature = false -ij_c_shift_operation_align_multiline = true -ij_c_shift_operation_wrap = normal -ij_c_show_non_virtual_functions = false -ij_c_space_after_colon = true -ij_c_space_after_colon_in_selector = false -ij_c_space_after_comma = true -ij_c_space_after_cup_in_blocks = false -ij_c_space_after_dictionary_literal_colon = true -ij_c_space_after_for_semicolon = true -ij_c_space_after_init_list_colon = true -ij_c_space_after_method_parameter_type_parentheses = false -ij_c_space_after_method_return_type_parentheses = false -ij_c_space_after_pointer_in_declaration = false -ij_c_space_after_quest = true -ij_c_space_after_reference_in_declaration = false -ij_c_space_after_reference_in_rvalue = false -ij_c_space_after_structures_rbrace = true -ij_c_space_after_superclass_colon = true -ij_c_space_after_type_cast = true -ij_c_space_after_visibility_sign_in_method_declaration = true -ij_c_space_before_autorelease_pool_lbrace = true -ij_c_space_before_catch_keyword = true -ij_c_space_before_catch_left_brace = true -ij_c_space_before_catch_parentheses = true -ij_c_space_before_category_parentheses = true -ij_c_space_before_chained_send_message = true -ij_c_space_before_class_left_brace = true -ij_c_space_before_colon = true -ij_c_space_before_comma = false -ij_c_space_before_dictionary_literal_colon = false -ij_c_space_before_do_left_brace = true -ij_c_space_before_else_keyword = true -ij_c_space_before_else_left_brace = true -ij_c_space_before_for_left_brace = true -ij_c_space_before_for_parentheses = true -ij_c_space_before_for_semicolon = false -ij_c_space_before_if_left_brace = true -ij_c_space_before_if_parentheses = true -ij_c_space_before_init_list = false -ij_c_space_before_init_list_colon = true -ij_c_space_before_method_call_parentheses = false -ij_c_space_before_method_left_brace = true -ij_c_space_before_method_parentheses = false -ij_c_space_before_namespace_lbrace = true -ij_c_space_before_pointer_in_declaration = true -ij_c_space_before_property_attributes_parentheses = false -ij_c_space_before_protocols_brackets = true -ij_c_space_before_quest = true -ij_c_space_before_reference_in_declaration = true -ij_c_space_before_superclass_colon = true -ij_c_space_before_switch_left_brace = true -ij_c_space_before_switch_parentheses = true -ij_c_space_before_template_call_lt = false -ij_c_space_before_template_declaration_lt = false -ij_c_space_before_try_left_brace = true -ij_c_space_before_while_keyword = true -ij_c_space_before_while_left_brace = true -ij_c_space_before_while_parentheses = true -ij_c_space_between_adjacent_brackets = false -ij_c_space_between_operator_and_punctuator = false -ij_c_space_within_empty_array_initializer_braces = false -ij_c_spaces_around_additive_operators = true -ij_c_spaces_around_assignment_operators = true -ij_c_spaces_around_bitwise_operators = true -ij_c_spaces_around_equality_operators = true -ij_c_spaces_around_lambda_arrow = true -ij_c_spaces_around_logical_operators = true -ij_c_spaces_around_multiplicative_operators = true -ij_c_spaces_around_pm_operators = false -ij_c_spaces_around_relational_operators = true -ij_c_spaces_around_shift_operators = true -ij_c_spaces_around_unary_operator = false -ij_c_spaces_within_array_initializer_braces = false -ij_c_spaces_within_braces = true -ij_c_spaces_within_brackets = false -ij_c_spaces_within_cast_parentheses = false -ij_c_spaces_within_catch_parentheses = false -ij_c_spaces_within_category_parentheses = false -ij_c_spaces_within_empty_braces = false -ij_c_spaces_within_empty_function_call_parentheses = false -ij_c_spaces_within_empty_function_declaration_parentheses = false -ij_c_spaces_within_empty_lambda_capture_list_bracket = false -ij_c_spaces_within_empty_template_call_ltgt = false -ij_c_spaces_within_empty_template_declaration_ltgt = false -ij_c_spaces_within_for_parentheses = false -ij_c_spaces_within_function_call_parentheses = false -ij_c_spaces_within_function_declaration_parentheses = false -ij_c_spaces_within_if_parentheses = false -ij_c_spaces_within_lambda_capture_list_bracket = false -ij_c_spaces_within_method_parameter_type_parentheses = false -ij_c_spaces_within_method_return_type_parentheses = false -ij_c_spaces_within_parentheses = false -ij_c_spaces_within_property_attributes_parentheses = false -ij_c_spaces_within_protocols_brackets = false -ij_c_spaces_within_send_message_brackets = false -ij_c_spaces_within_switch_parentheses = false -ij_c_spaces_within_template_call_ltgt = false -ij_c_spaces_within_template_declaration_ltgt = false -ij_c_spaces_within_template_double_gt = true -ij_c_spaces_within_while_parentheses = false -ij_c_special_else_if_treatment = true -ij_c_superclass_list_after_colon = never -ij_c_superclass_list_align_multiline = true -ij_c_superclass_list_before_colon = if_long -ij_c_superclass_list_comma_on_next_line = false -ij_c_superclass_list_wrap = on_every_item -ij_c_tag_prefix_of_block_comment = at -ij_c_tag_prefix_of_line_comment = back_slash -ij_c_template_call_arguments_align_multiline = false -ij_c_template_call_arguments_align_multiline_pars = false -ij_c_template_call_arguments_comma_on_next_line = false -ij_c_template_call_arguments_new_line_after_lt = false -ij_c_template_call_arguments_new_line_before_gt = false -ij_c_template_call_arguments_wrap = off -ij_c_template_declaration_function_body_indent = false -ij_c_template_declaration_function_wrap = split_into_lines -ij_c_template_declaration_struct_body_indent = false -ij_c_template_declaration_struct_wrap = split_into_lines -ij_c_template_parameters_align_multiline = false -ij_c_template_parameters_align_multiline_pars = false -ij_c_template_parameters_comma_on_next_line = false -ij_c_template_parameters_new_line_after_lt = false -ij_c_template_parameters_new_line_before_gt = false -ij_c_template_parameters_wrap = off -ij_c_ternary_operation_signs_on_next_line = true -ij_c_ternary_operation_wrap = normal -ij_c_type_qualifiers_placement = before -ij_c_use_modern_casts = true -ij_c_use_setters_in_constructor = true -ij_c_while_brace_force = never -ij_c_while_on_new_line = false -ij_c_wrap_property_declaration = off - -[{*.cmake,CMakeLists.txt}] -ij_cmake_align_multiline_parameters_in_calls = false -ij_cmake_force_commands_case = 2 -ij_cmake_keep_blank_lines_in_code = 2 -ij_cmake_space_before_for_parentheses = true -ij_cmake_space_before_if_parentheses = true -ij_cmake_space_before_method_call_parentheses = false -ij_cmake_space_before_method_parentheses = false -ij_cmake_space_before_while_parentheses = true -ij_cmake_spaces_within_for_parentheses = false -ij_cmake_spaces_within_if_parentheses = false -ij_cmake_spaces_within_method_call_parentheses = false -ij_cmake_spaces_within_method_parentheses = false -ij_cmake_spaces_within_while_parentheses = false - -[{*.gant,*.gradle,*.groovy,*.gy}] -ij_groovy_align_group_field_declarations = false -ij_groovy_align_multiline_array_initializer_expression = false -ij_groovy_align_multiline_assignment = false -ij_groovy_align_multiline_binary_operation = false -ij_groovy_align_multiline_chained_methods = false -ij_groovy_align_multiline_extends_list = false -ij_groovy_align_multiline_for = true -ij_groovy_align_multiline_list_or_map = true -ij_groovy_align_multiline_method_parentheses = false -ij_groovy_align_multiline_parameters = true -ij_groovy_align_multiline_parameters_in_calls = false -ij_groovy_align_multiline_resources = true -ij_groovy_align_multiline_ternary_operation = false -ij_groovy_align_multiline_throws_list = false -ij_groovy_align_named_args_in_map = true -ij_groovy_align_throws_keyword = false -ij_groovy_array_initializer_new_line_after_left_brace = false -ij_groovy_array_initializer_right_brace_on_new_line = false -ij_groovy_array_initializer_wrap = off -ij_groovy_assert_statement_wrap = off -ij_groovy_assignment_wrap = off -ij_groovy_binary_operation_wrap = off -ij_groovy_blank_lines_after_class_header = 0 -ij_groovy_blank_lines_after_imports = 1 -ij_groovy_blank_lines_after_package = 1 -ij_groovy_blank_lines_around_class = 1 -ij_groovy_blank_lines_around_field = 0 -ij_groovy_blank_lines_around_field_in_interface = 0 -ij_groovy_blank_lines_around_method = 1 -ij_groovy_blank_lines_around_method_in_interface = 1 -ij_groovy_blank_lines_before_imports = 1 -ij_groovy_blank_lines_before_method_body = 0 -ij_groovy_blank_lines_before_package = 0 -ij_groovy_block_brace_style = end_of_line -ij_groovy_block_comment_at_first_column = true -ij_groovy_call_parameters_new_line_after_left_paren = false -ij_groovy_call_parameters_right_paren_on_new_line = false -ij_groovy_call_parameters_wrap = off -ij_groovy_catch_on_new_line = false -ij_groovy_class_annotation_wrap = split_into_lines -ij_groovy_class_brace_style = end_of_line -ij_groovy_class_count_to_use_import_on_demand = 5 -ij_groovy_do_while_brace_force = never -ij_groovy_else_on_new_line = false -ij_groovy_enum_constants_wrap = off -ij_groovy_extends_keyword_wrap = off -ij_groovy_extends_list_wrap = off -ij_groovy_field_annotation_wrap = split_into_lines -ij_groovy_finally_on_new_line = false -ij_groovy_for_brace_force = never -ij_groovy_for_statement_new_line_after_left_paren = false -ij_groovy_for_statement_right_paren_on_new_line = false -ij_groovy_for_statement_wrap = off -ij_groovy_if_brace_force = never -ij_groovy_import_annotation_wrap = 2 -ij_groovy_imports_layout = *,|,javax.**,java.**,|,$* -ij_groovy_indent_case_from_switch = true -ij_groovy_indent_label_blocks = true -ij_groovy_insert_inner_class_imports = false -ij_groovy_keep_blank_lines_before_right_brace = 2 -ij_groovy_keep_blank_lines_in_code = 2 -ij_groovy_keep_blank_lines_in_declarations = 2 -ij_groovy_keep_control_statement_in_one_line = true -ij_groovy_keep_first_column_comment = true -ij_groovy_keep_indents_on_empty_lines = false -ij_groovy_keep_line_breaks = true -ij_groovy_keep_multiple_expressions_in_one_line = false -ij_groovy_keep_simple_blocks_in_one_line = false -ij_groovy_keep_simple_classes_in_one_line = true -ij_groovy_keep_simple_lambdas_in_one_line = true -ij_groovy_keep_simple_methods_in_one_line = true -ij_groovy_label_indent_absolute = false -ij_groovy_label_indent_size = 0 -ij_groovy_lambda_brace_style = end_of_line -ij_groovy_layout_static_imports_separately = true -ij_groovy_line_comment_add_space = false -ij_groovy_line_comment_at_first_column = true -ij_groovy_method_annotation_wrap = split_into_lines -ij_groovy_method_brace_style = end_of_line -ij_groovy_method_call_chain_wrap = off -ij_groovy_method_parameters_new_line_after_left_paren = false -ij_groovy_method_parameters_right_paren_on_new_line = false -ij_groovy_method_parameters_wrap = off -ij_groovy_modifier_list_wrap = false -ij_groovy_names_count_to_use_import_on_demand = 3 -ij_groovy_parameter_annotation_wrap = off -ij_groovy_parentheses_expression_new_line_after_left_paren = false -ij_groovy_parentheses_expression_right_paren_on_new_line = false -ij_groovy_prefer_parameters_wrap = false -ij_groovy_resource_list_new_line_after_left_paren = false -ij_groovy_resource_list_right_paren_on_new_line = false -ij_groovy_resource_list_wrap = off -ij_groovy_space_after_assert_separator = true -ij_groovy_space_after_colon = true -ij_groovy_space_after_comma = true -ij_groovy_space_after_comma_in_type_arguments = true -ij_groovy_space_after_for_semicolon = true -ij_groovy_space_after_quest = true -ij_groovy_space_after_type_cast = true -ij_groovy_space_before_annotation_parameter_list = false -ij_groovy_space_before_array_initializer_left_brace = false -ij_groovy_space_before_assert_separator = false -ij_groovy_space_before_catch_keyword = true -ij_groovy_space_before_catch_left_brace = true -ij_groovy_space_before_catch_parentheses = true -ij_groovy_space_before_class_left_brace = true -ij_groovy_space_before_closure_left_brace = true -ij_groovy_space_before_colon = true -ij_groovy_space_before_comma = false -ij_groovy_space_before_do_left_brace = true -ij_groovy_space_before_else_keyword = true -ij_groovy_space_before_else_left_brace = true -ij_groovy_space_before_finally_keyword = true -ij_groovy_space_before_finally_left_brace = true -ij_groovy_space_before_for_left_brace = true -ij_groovy_space_before_for_parentheses = true -ij_groovy_space_before_for_semicolon = false -ij_groovy_space_before_if_left_brace = true -ij_groovy_space_before_if_parentheses = true -ij_groovy_space_before_method_call_parentheses = false -ij_groovy_space_before_method_left_brace = true -ij_groovy_space_before_method_parentheses = false -ij_groovy_space_before_quest = true -ij_groovy_space_before_switch_left_brace = true -ij_groovy_space_before_switch_parentheses = true -ij_groovy_space_before_synchronized_left_brace = true -ij_groovy_space_before_synchronized_parentheses = true -ij_groovy_space_before_try_left_brace = true -ij_groovy_space_before_try_parentheses = true -ij_groovy_space_before_while_keyword = true -ij_groovy_space_before_while_left_brace = true -ij_groovy_space_before_while_parentheses = true -ij_groovy_space_in_named_argument = true -ij_groovy_space_in_named_argument_before_colon = false -ij_groovy_space_within_empty_array_initializer_braces = false -ij_groovy_space_within_empty_method_call_parentheses = false -ij_groovy_spaces_around_additive_operators = true -ij_groovy_spaces_around_assignment_operators = true -ij_groovy_spaces_around_bitwise_operators = true -ij_groovy_spaces_around_equality_operators = true -ij_groovy_spaces_around_lambda_arrow = true -ij_groovy_spaces_around_logical_operators = true -ij_groovy_spaces_around_multiplicative_operators = true -ij_groovy_spaces_around_regex_operators = true -ij_groovy_spaces_around_relational_operators = true -ij_groovy_spaces_around_shift_operators = true -ij_groovy_spaces_within_annotation_parentheses = false -ij_groovy_spaces_within_array_initializer_braces = false -ij_groovy_spaces_within_braces = true -ij_groovy_spaces_within_brackets = false -ij_groovy_spaces_within_cast_parentheses = false -ij_groovy_spaces_within_catch_parentheses = false -ij_groovy_spaces_within_for_parentheses = false -ij_groovy_spaces_within_gstring_injection_braces = false -ij_groovy_spaces_within_if_parentheses = false -ij_groovy_spaces_within_list_or_map = false -ij_groovy_spaces_within_method_call_parentheses = false -ij_groovy_spaces_within_method_parentheses = false -ij_groovy_spaces_within_parentheses = false -ij_groovy_spaces_within_switch_parentheses = false -ij_groovy_spaces_within_synchronized_parentheses = false -ij_groovy_spaces_within_try_parentheses = false -ij_groovy_spaces_within_tuple_expression = false -ij_groovy_spaces_within_while_parentheses = false -ij_groovy_special_else_if_treatment = true -ij_groovy_ternary_operation_wrap = off -ij_groovy_throws_keyword_wrap = off -ij_groovy_throws_list_wrap = off -ij_groovy_use_flying_geese_braces = false -ij_groovy_use_fq_class_names = false -ij_groovy_use_fq_class_names_in_javadoc = true -ij_groovy_use_relative_indents = false -ij_groovy_use_single_class_imports = true -ij_groovy_variable_annotation_wrap = off -ij_groovy_while_brace_force = never -ij_groovy_while_on_new_line = false -ij_groovy_wrap_long_lines = false - -[{*.gradle.kts,*.kt,*.kts,*.main.kts}] -ij_kotlin_align_in_columns_case_branch = false -ij_kotlin_align_multiline_binary_operation = false -ij_kotlin_align_multiline_extends_list = false -ij_kotlin_align_multiline_method_parentheses = false -ij_kotlin_align_multiline_parameters = true -ij_kotlin_align_multiline_parameters_in_calls = false -ij_kotlin_allow_trailing_comma = false -ij_kotlin_allow_trailing_comma_on_call_site = false -ij_kotlin_assignment_wrap = normal -ij_kotlin_blank_lines_after_class_header = 0 -ij_kotlin_blank_lines_around_block_when_branches = 0 -ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1 -ij_kotlin_block_comment_at_first_column = true -ij_kotlin_call_parameters_new_line_after_left_paren = true -ij_kotlin_call_parameters_right_paren_on_new_line = true -ij_kotlin_call_parameters_wrap = on_every_item -ij_kotlin_catch_on_new_line = false -ij_kotlin_class_annotation_wrap = split_into_lines -ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL -ij_kotlin_continuation_indent_for_chained_calls = false -ij_kotlin_continuation_indent_for_expression_bodies = false -ij_kotlin_continuation_indent_in_argument_lists = false -ij_kotlin_continuation_indent_in_elvis = false -ij_kotlin_continuation_indent_in_if_conditions = false -ij_kotlin_continuation_indent_in_parameter_lists = false -ij_kotlin_continuation_indent_in_supertype_lists = false -ij_kotlin_else_on_new_line = false -ij_kotlin_enum_constants_wrap = off -ij_kotlin_extends_list_wrap = normal -ij_kotlin_field_annotation_wrap = split_into_lines -ij_kotlin_finally_on_new_line = false -ij_kotlin_if_rparen_on_new_line = true -ij_kotlin_import_nested_classes = false -ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^ -ij_kotlin_insert_whitespaces_in_simple_one_line_method = true -ij_kotlin_keep_blank_lines_before_right_brace = 2 -ij_kotlin_keep_blank_lines_in_code = 2 -ij_kotlin_keep_blank_lines_in_declarations = 2 -ij_kotlin_keep_first_column_comment = true -ij_kotlin_keep_indents_on_empty_lines = false -ij_kotlin_keep_line_breaks = true -ij_kotlin_lbrace_on_next_line = false -ij_kotlin_line_comment_add_space = false -ij_kotlin_line_comment_at_first_column = true -ij_kotlin_method_annotation_wrap = split_into_lines -ij_kotlin_method_call_chain_wrap = normal -ij_kotlin_method_parameters_new_line_after_left_paren = true -ij_kotlin_method_parameters_right_paren_on_new_line = true -ij_kotlin_method_parameters_wrap = on_every_item -ij_kotlin_name_count_to_use_star_import = 5 -ij_kotlin_name_count_to_use_star_import_for_members = 3 -ij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlinx.android.synthetic.**,io.ktor.** -ij_kotlin_parameter_annotation_wrap = off -ij_kotlin_space_after_comma = true -ij_kotlin_space_after_extend_colon = true -ij_kotlin_space_after_type_colon = true -ij_kotlin_space_before_catch_parentheses = true -ij_kotlin_space_before_comma = false -ij_kotlin_space_before_extend_colon = true -ij_kotlin_space_before_for_parentheses = true -ij_kotlin_space_before_if_parentheses = true -ij_kotlin_space_before_lambda_arrow = true -ij_kotlin_space_before_type_colon = false -ij_kotlin_space_before_when_parentheses = true -ij_kotlin_space_before_while_parentheses = true -ij_kotlin_spaces_around_additive_operators = true -ij_kotlin_spaces_around_assignment_operators = true -ij_kotlin_spaces_around_equality_operators = true -ij_kotlin_spaces_around_function_type_arrow = true -ij_kotlin_spaces_around_logical_operators = true -ij_kotlin_spaces_around_multiplicative_operators = true -ij_kotlin_spaces_around_range = false -ij_kotlin_spaces_around_relational_operators = true -ij_kotlin_spaces_around_unary_operator = false -ij_kotlin_spaces_around_when_arrow = true -ij_kotlin_use_custom_formatting_for_modifiers = true -ij_kotlin_variable_annotation_wrap = off -ij_kotlin_while_on_new_line = false -ij_kotlin_wrap_elvis_expressions = 1 -ij_kotlin_wrap_expression_body_functions = 1 -ij_kotlin_wrap_first_method_in_call_chain = false - -[{*.har,*.json}] -indent_size = 2 -ij_json_keep_blank_lines_in_code = 0 -ij_json_keep_indents_on_empty_lines = false -ij_json_keep_line_breaks = true -ij_json_space_after_colon = true -ij_json_space_after_comma = true -ij_json_space_before_colon = true -ij_json_space_before_comma = false -ij_json_spaces_within_braces = false -ij_json_spaces_within_brackets = false -ij_json_wrap_long_lines = false - -[{*.htm,*.html,*.sht,*.shtm,*.shtml}] -ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3 -ij_html_align_attributes = true -ij_html_align_text = false -ij_html_attribute_wrap = normal -ij_html_block_comment_at_first_column = true -ij_html_do_not_align_children_of_min_lines = 0 -ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p -ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot -ij_html_enforce_quotes = false -ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var -ij_html_keep_blank_lines = 2 -ij_html_keep_indents_on_empty_lines = false -ij_html_keep_line_breaks = true -ij_html_keep_line_breaks_in_text = true -ij_html_keep_whitespaces = false -ij_html_keep_whitespaces_inside = span,pre,textarea -ij_html_line_comment_at_first_column = true -ij_html_new_line_after_last_attribute = never -ij_html_new_line_before_first_attribute = never -ij_html_quote_style = double -ij_html_remove_new_line_before_tags = br -ij_html_space_after_tag_name = false -ij_html_space_around_equality_in_attribute = false -ij_html_space_inside_empty_tag = false -ij_html_text_wrap = normal -ij_html_uniform_ident = false - -[{*.markdown,*.md}] -ij_markdown_force_one_space_after_blockquote_symbol = true -ij_markdown_force_one_space_after_header_symbol = true -ij_markdown_force_one_space_after_list_bullet = true -ij_markdown_force_one_space_between_words = true -ij_markdown_keep_indents_on_empty_lines = false -ij_markdown_max_lines_around_block_elements = 1 -ij_markdown_max_lines_around_header = 1 -ij_markdown_max_lines_between_paragraphs = 1 -ij_markdown_min_lines_around_block_elements = 1 -ij_markdown_min_lines_around_header = 1 -ij_markdown_min_lines_between_paragraphs = 1 - -[{*.yaml,*.yml}] -indent_size = 2 -ij_yaml_align_values_properties = do_not_align -ij_yaml_autoinsert_sequence_marker = true -ij_yaml_block_mapping_on_new_line = false -ij_yaml_indent_sequence_value = true -ij_yaml_keep_indents_on_empty_lines = false -ij_yaml_keep_line_breaks = true -ij_yaml_sequence_on_new_line = false -ij_yaml_space_before_colon = false -ij_yaml_spaces_within_braces = true -ij_yaml_spaces_within_brackets = true diff --git a/.github/checkstyle-rules.xml b/.github/checkstyle-rules.xml index 3f97635791..4234051d17 100644 --- a/.github/checkstyle-rules.xml +++ b/.github/checkstyle-rules.xml @@ -235,14 +235,14 @@ - - - - - - - - + + + + + + + + diff --git a/app/src/main/java/com/alphawallet/app/entity/ActionSheetInterface.java b/app/src/main/java/com/alphawallet/app/entity/ActionSheetInterface.java index 6fe68d9a68..28690c775f 100644 --- a/app/src/main/java/com/alphawallet/app/entity/ActionSheetInterface.java +++ b/app/src/main/java/com/alphawallet/app/entity/ActionSheetInterface.java @@ -1,5 +1,11 @@ package com.alphawallet.app.entity; +import androidx.activity.result.ActivityResult; + +import com.alphawallet.app.web3.entity.Web3Transaction; + +import java.math.BigInteger; + /** * Created by JB on 16/01/2021. */ @@ -7,4 +13,49 @@ public interface ActionSheetInterface { void lockDragging(boolean shouldLock); void fullExpand(); + + default void success() + { + } + + default void setURL(String url) + { + } + + default void setGasEstimate(BigInteger estimate) + { + } + + default void completeSignRequest(Boolean gotAuth) + { + } + + default void setSigningWallet(String account) + { + } + + default void setIcon(String icon) + { + } + + default void transactionWritten(String hash) + { + } + + default void updateChain(long chainId) + { + } + + default Web3Transaction getTransaction() + { + throw new RuntimeException("Implement getTransaction"); + } + + default void setSignOnly() + { + } + + default void setCurrentGasIndex(ActivityResult result) + { + } } diff --git a/app/src/main/java/com/alphawallet/app/entity/SignAuthenticationCallback.java b/app/src/main/java/com/alphawallet/app/entity/SignAuthenticationCallback.java index cc8ae9e2f8..440998c77e 100644 --- a/app/src/main/java/com/alphawallet/app/entity/SignAuthenticationCallback.java +++ b/app/src/main/java/com/alphawallet/app/entity/SignAuthenticationCallback.java @@ -1,7 +1,5 @@ package com.alphawallet.app.entity; -import com.alphawallet.token.entity.Signable; - /** * Created by James on 21/07/2019. * Stormbird in Sydney @@ -9,8 +7,7 @@ public interface SignAuthenticationCallback { void gotAuthorisation(boolean gotAuth); - default void gotAuthorisationForSigning(boolean gotAuth, Signable messageToSign) { } //if you implement message signing default void createdKey(String keyAddress) { } void cancelAuthentication(); -} \ No newline at end of file +} diff --git a/app/src/main/java/com/alphawallet/app/interact/CreateTransactionInteract.java b/app/src/main/java/com/alphawallet/app/interact/CreateTransactionInteract.java index 99d94e91d8..c24bd876f7 100644 --- a/app/src/main/java/com/alphawallet/app/interact/CreateTransactionInteract.java +++ b/app/src/main/java/com/alphawallet/app/interact/CreateTransactionInteract.java @@ -28,15 +28,15 @@ public CreateTransactionInteract(TransactionRepositoryType transactionRepository this.transactionRepository = transactionRepository; } - public Single sign(Wallet wallet, MessagePair messagePair, long chainId) + public Single sign(Wallet wallet, MessagePair messagePair) { - return transactionRepository.getSignature(wallet, messagePair, chainId) + return transactionRepository.getSignature(wallet, messagePair) .map(sig -> new SignaturePair(messagePair.selection, sig.signature, messagePair.message)); } - public Single sign(Wallet wallet, Signable message, long chainId) + public Single sign(Wallet wallet, Signable message) { - return transactionRepository.getSignature(wallet, message, chainId); + return transactionRepository.getSignature(wallet, message); } public Single create(Wallet from, String to, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, byte[] data, long chainId) @@ -117,4 +117,4 @@ public Single signTransaction(Wallet from, Web3Transaction web3 web3Tx.gasPrice, web3Tx.gasLimit, web3Tx.nonce, !TextUtils.isEmpty(web3Tx.payload) ? Numeric.hexStringToByteArray(web3Tx.payload) : new byte[0], chainId); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/alphawallet/app/interact/GenericWalletInteract.java b/app/src/main/java/com/alphawallet/app/interact/GenericWalletInteract.java index 2be594ab6f..4e40c949bc 100644 --- a/app/src/main/java/com/alphawallet/app/interact/GenericWalletInteract.java +++ b/app/src/main/java/com/alphawallet/app/interact/GenericWalletInteract.java @@ -3,9 +3,6 @@ import static com.alphawallet.app.C.ETHER_DECIMALS; import static com.alphawallet.app.entity.tokens.Token.TOKEN_BALANCE_PRECISION; -import android.util.Log; - -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.repository.WalletItem; import com.alphawallet.app.repository.WalletRepositoryType; @@ -33,6 +30,13 @@ public Single find() { .observeOn(AndroidSchedulers.mainThread()); } + public Single findWallet(String account) + { + return walletRepository.findWallet(account) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + /** * Called when wallet marked as backed up. * Update the wallet date diff --git a/app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java b/app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java index 645ff1cf44..3ebe2b06fd 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TransactionRepository.java @@ -24,263 +24,282 @@ import io.reactivex.schedulers.Schedulers; import io.realm.Realm; -public class TransactionRepository implements TransactionRepositoryType { +public class TransactionRepository implements TransactionRepositoryType +{ - private final String TAG = "TREPO"; - private final EthereumNetworkRepositoryType networkRepository; - private final AccountKeystoreService accountKeystoreService; + private final String TAG = "TREPO"; + private final EthereumNetworkRepositoryType networkRepository; + private final AccountKeystoreService accountKeystoreService; private final TransactionLocalSource inDiskCache; private final TransactionsService transactionsService; - public TransactionRepository( - EthereumNetworkRepositoryType networkRepository, - AccountKeystoreService accountKeystoreService, - TransactionLocalSource inDiskCache, - TransactionsService transactionsService) { - this.networkRepository = networkRepository; - this.accountKeystoreService = accountKeystoreService; - this.inDiskCache = inDiskCache; - this.transactionsService = transactionsService; - } - - @Override - public Transaction fetchCachedTransaction(String walletAddr, String hash) - { - Wallet wallet = new Wallet(walletAddr); - return inDiskCache.fetchTransaction(wallet, hash); - } - - @Override - public long fetchTxCompletionTime(String walletAddr, String hash) - { - Wallet wallet = new Wallet(walletAddr); - return inDiskCache.fetchTxCompletionTime(wallet, hash); - } - - @Override - public Single resendTransaction(Wallet from, String to, BigInteger subunitAmount, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, byte[] data, long chainId) - { - final Web3j web3j = getWeb3jService(chainId); - final BigInteger useGasPrice = gasPriceForNode(chainId, gasPrice); - - return accountKeystoreService.signTransaction(from, to, subunitAmount, useGasPrice, gasLimit, nonce.longValue(), data, chainId) - .flatMap(signedMessage -> Single.fromCallable( () -> { - if (signedMessage.sigType != SignatureReturnType.SIGNATURE_GENERATED) - { - throw new Exception(signedMessage.failMessage); - } - EthSendTransaction raw = web3j - .ethSendRawTransaction(Numeric.toHexString(signedMessage.signature)) - .send(); - if (raw.hasError()) - { - throw new Exception(raw.getError().getMessage()); - } - return raw.getTransactionHash(); - })) - .flatMap(txHash -> storeUnconfirmedTransaction(from, txHash, to, subunitAmount, nonce, useGasPrice, gasLimit, chainId, data != null ? Numeric.toHexString(data) : "0x")) - .subscribeOn(Schedulers.io()); - } - - @Override - public Single create1559TransactionWithSig(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasLimit, BigInteger maxFeePerGas, BigInteger maxPriorityFee, long nonce, byte[] data, long chainId) { - final Web3j web3j = getWeb3jService(chainId); - - TransactionData txData = new TransactionData(); - - return getNonceForTransaction(web3j, from.address, nonce) - .flatMap(txNonce -> { - txData.nonce = txNonce; - return accountKeystoreService.signTransactionEIP1559(from, toAddress, subunitAmount, gasLimit, maxFeePerGas, maxPriorityFee, txNonce.longValue(), data, chainId); - }) - .flatMap(signedMessage -> Single.fromCallable( () -> { - if (signedMessage.sigType != SignatureReturnType.SIGNATURE_GENERATED) - { - throw new Exception(signedMessage.failMessage); - } - txData.signature = Numeric.toHexString(signedMessage.signature); - EthSendTransaction raw = web3j - .ethSendRawTransaction(Numeric.toHexString(signedMessage.signature)) - .send(); - if (raw.hasError()) { - throw new Exception(raw.getError().getMessage()); - } - txData.txHash = raw.getTransactionHash(); - return txData; - })) - .flatMap(tx -> storeUnconfirmedTransaction(from, tx, toAddress, subunitAmount, tx.nonce, maxFeePerGas, maxPriorityFee, gasLimit, chainId, data != null ? Numeric.toHexString(data) : "0x", "")) - .subscribeOn(Schedulers.io()); - } - - @Override - public Single createTransactionWithSig(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId) { - final Web3j web3j = getWeb3jService(chainId); - final BigInteger useGasPrice = gasPriceForNode(chainId, gasPrice); - - TransactionData txData = new TransactionData(); - - return getNonceForTransaction(web3j, from.address, nonce) - .flatMap(txNonce -> { - txData.nonce = txNonce; - return accountKeystoreService.signTransaction(from, toAddress, subunitAmount, useGasPrice, gasLimit, txNonce.longValue(), data, chainId); - }) - .flatMap(signedMessage -> Single.fromCallable( () -> { - if (signedMessage.sigType != SignatureReturnType.SIGNATURE_GENERATED) - { - throw new Exception(signedMessage.failMessage); - } - txData.signature = Numeric.toHexString(signedMessage.signature); - EthSendTransaction raw = web3j - .ethSendRawTransaction(Numeric.toHexString(signedMessage.signature)) - .send(); - if (raw.hasError()) { - throw new Exception(raw.getError().getMessage()); - } - txData.txHash = raw.getTransactionHash(); - return txData; - })) - .flatMap(tx -> storeUnconfirmedTransaction(from, tx, toAddress, subunitAmount, tx.nonce, useGasPrice, gasLimit, chainId, data != null ? Numeric.toHexString(data) : "0x", "")) - .subscribeOn(Schedulers.io()); - } - - /** - * * Given a Web3Transaction, return a signature. Note that we can't fix up nonce, gas price or limit; - * * This is a request to sign a transaction from an external source - - * * presumably that external source will broadcast the transaction; together with this signature - * - * @param from - * @param toAddress - * @param subunitAmount - * @param gasPrice - * @param gasLimit - * @param nonce - * @param data - * @param chainId - * @return - */ - @Override - public Single getSignatureForTransaction(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId) { - final Web3j web3j = getWeb3jService(chainId); - final BigInteger useGasPrice = gasPriceForNode(chainId, gasPrice); - TransactionData txData = new TransactionData(); - - return getNonceForTransaction(web3j, from.address, nonce) - .flatMap(txNonce -> { - txData.nonce = txNonce; - return accountKeystoreService.signTransaction(from, toAddress, subunitAmount, useGasPrice, gasLimit, txNonce.longValue(), data, chainId); - }) - .flatMap(signedMessage -> Single.fromCallable( () -> { - if (signedMessage.sigType != SignatureReturnType.SIGNATURE_GENERATED) - { - throw new Exception(signedMessage.failMessage); - } - txData.signature = Numeric.toHexString(signedMessage.signature); - return txData; - })); - } - - private BigInteger gasPriceForNode(long chainId, BigInteger gasPrice) - { - if (EthereumNetworkRepository.hasGasOverride(chainId)) return EthereumNetworkRepository.gasOverrideValue(chainId); - else return gasPrice; - } - - //EIP1559 - private Single storeUnconfirmedTransaction(Wallet from, TransactionData txData, String toAddress, BigInteger value, BigInteger nonce, BigInteger maxFeePerGas, BigInteger maxPriorityFee, BigInteger gasLimit, long chainId, String data, String contractAddr) - { - return Single.fromCallable(() -> { - Transaction newTx = new Transaction(txData.txHash, "0", "0", System.currentTimeMillis()/1000, nonce.intValue(), from.address, toAddress, value.toString(10), "0", "0", maxFeePerGas.toString(10), - maxPriorityFee.toString(10), data, - gasLimit.toString(10), chainId, contractAddr); - inDiskCache.putTransaction(from, newTx); - transactionsService.markPending(newTx); - - return txData; - }); - } - - private Single storeUnconfirmedTransaction(Wallet from, TransactionData txData, String toAddress, BigInteger value, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, long chainId, String data, String contractAddr) - { - return Single.fromCallable(() -> { - Transaction newTx = new Transaction(txData.txHash, "0", "0", System.currentTimeMillis()/1000, nonce.intValue(), from.address, toAddress, value.toString(10), "0", gasPrice.toString(10), data, - gasLimit.toString(10), chainId, contractAddr); - //newTx.completeSetup(from.address); - inDiskCache.putTransaction(from, newTx); - transactionsService.markPending(newTx); - - return txData; - }); - } - - private Single storeUnconfirmedTransaction(Wallet from, String txHash, String toAddress, BigInteger value, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, long chainId, String data) - { - return Single.fromCallable(() -> { - - Transaction newTx = new Transaction(txHash, "0", "0", System.currentTimeMillis()/1000, nonce.intValue(), from.address, toAddress, value.toString(10), "0", gasPrice.toString(10), data, - gasLimit.toString(10), chainId, ""); - //newTx.completeSetup(from.address); - inDiskCache.putTransaction(from, newTx); - transactionsService.markPending(newTx); - - return txHash; - }); - } - - @Override - public Single getSignature(Wallet wallet, Signable message, long chainId) { - return accountKeystoreService.signMessage(wallet, message, chainId); - } - - @Override - public Single getSignatureFast(Wallet wallet, String password, byte[] message, long chainId) { - return accountKeystoreService.signTransactionFast(wallet, password, message, chainId); - } - - @Override - public Single fetchCachedTransactionMetas(Wallet wallet, List networkFilters, long fetchTime, int fetchLimit) - { - return inDiskCache.fetchActivityMetas(wallet, networkFilters, fetchTime, fetchLimit); - } - - @Override - public Single fetchCachedTransactionMetas(Wallet wallet, long chainId, String tokenAddress, int historyCount) - { - return inDiskCache.fetchActivityMetas(wallet, chainId, tokenAddress, historyCount); - } - - @Override - public Single fetchEventMetas(Wallet wallet, List networkFilters) - { - return inDiskCache.fetchEventMetas(wallet, networkFilters); - } - - @Override - public Realm getRealmInstance(Wallet wallet) - { - return inDiskCache.getRealmInstance(wallet); - } - - @Override - public RealmAuxData fetchCachedEvent(String walletAddress, String eventKey) - { - return inDiskCache.fetchEvent(walletAddress, eventKey); - } - - @Override - public void restartService() - { - transactionsService.startUpdateCycle(); - } - - private Single getNonceForTransaction(Web3j web3j, String wallet, long nonce) - { - if (nonce != -1) //use supplied nonce - { - return Single.fromCallable(() -> BigInteger.valueOf(nonce)); - } - else - { - return networkRepository.getLastTransactionNonce(web3j, wallet); - } - } + public TransactionRepository( + EthereumNetworkRepositoryType networkRepository, + AccountKeystoreService accountKeystoreService, + TransactionLocalSource inDiskCache, + TransactionsService transactionsService) + { + this.networkRepository = networkRepository; + this.accountKeystoreService = accountKeystoreService; + this.inDiskCache = inDiskCache; + this.transactionsService = transactionsService; + } + + @Override + public Transaction fetchCachedTransaction(String walletAddr, String hash) + { + Wallet wallet = new Wallet(walletAddr); + return inDiskCache.fetchTransaction(wallet, hash); + } + + @Override + public long fetchTxCompletionTime(String walletAddr, String hash) + { + Wallet wallet = new Wallet(walletAddr); + return inDiskCache.fetchTxCompletionTime(wallet, hash); + } + + @Override + public Single resendTransaction(Wallet from, String to, BigInteger subunitAmount, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, byte[] data, long chainId) + { + final Web3j web3j = getWeb3jService(chainId); + final BigInteger useGasPrice = gasPriceForNode(chainId, gasPrice); + + return accountKeystoreService.signTransaction(from, to, subunitAmount, useGasPrice, gasLimit, nonce.longValue(), data, chainId) + .flatMap(signedMessage -> Single.fromCallable(() -> { + if (signedMessage.sigType != SignatureReturnType.SIGNATURE_GENERATED) + { + throw new Exception(signedMessage.failMessage); + } + EthSendTransaction raw = web3j + .ethSendRawTransaction(Numeric.toHexString(signedMessage.signature)) + .send(); + if (raw.hasError()) + { + throw new Exception(raw.getError().getMessage()); + } + return raw.getTransactionHash(); + })) + .flatMap(txHash -> storeUnconfirmedTransaction(from, txHash, to, subunitAmount, nonce, useGasPrice, gasLimit, chainId, data != null ? Numeric.toHexString(data) : "0x")) + .subscribeOn(Schedulers.io()); + } + + @Override + public Single create1559TransactionWithSig(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasLimit, BigInteger maxFeePerGas, + BigInteger maxPriorityFee, long nonce, byte[] data, long chainId) + { + final Web3j web3j = getWeb3jService(chainId); + + TransactionData txData = new TransactionData(); + + return getNonceForTransaction(web3j, from.address, nonce) + .flatMap(txNonce -> { + txData.nonce = txNonce; + return accountKeystoreService.signTransactionEIP1559(from, toAddress, subunitAmount, gasLimit, maxFeePerGas, maxPriorityFee, txNonce.longValue(), data, chainId); + }) + .flatMap(signedMessage -> Single.fromCallable(() -> { + if (signedMessage.sigType != SignatureReturnType.SIGNATURE_GENERATED) + { + throw new Exception(signedMessage.failMessage); + } + txData.signature = Numeric.toHexString(signedMessage.signature); + EthSendTransaction raw = web3j + .ethSendRawTransaction(Numeric.toHexString(signedMessage.signature)) + .send(); + if (raw.hasError()) + { + throw new Exception(raw.getError().getMessage()); + } + txData.txHash = raw.getTransactionHash(); + return txData; + })) + .flatMap(tx -> storeUnconfirmedTransaction(from, tx, toAddress, subunitAmount, tx.nonce, maxFeePerGas, maxPriorityFee, gasLimit, chainId, + data != null ? Numeric.toHexString(data) : "0x", "")) + .subscribeOn(Schedulers.io()); + } + + @Override + public Single createTransactionWithSig(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId) + { + final Web3j web3j = getWeb3jService(chainId); + final BigInteger useGasPrice = gasPriceForNode(chainId, gasPrice); + + TransactionData txData = new TransactionData(); + + return getNonceForTransaction(web3j, from.address, nonce) + .flatMap(txNonce -> { + txData.nonce = txNonce; + return accountKeystoreService.signTransaction(from, toAddress, subunitAmount, useGasPrice, gasLimit, txNonce.longValue(), data, chainId); + }) + .flatMap(signedMessage -> Single.fromCallable(() -> { + if (signedMessage.sigType != SignatureReturnType.SIGNATURE_GENERATED) + { + throw new Exception(signedMessage.failMessage); + } + txData.signature = Numeric.toHexString(signedMessage.signature); + EthSendTransaction raw = web3j + .ethSendRawTransaction(Numeric.toHexString(signedMessage.signature)) + .send(); + if (raw.hasError()) + { + throw new Exception(raw.getError().getMessage()); + } + txData.txHash = raw.getTransactionHash(); + return txData; + })) + .flatMap(tx -> storeUnconfirmedTransaction(from, tx, toAddress, subunitAmount, tx.nonce, useGasPrice, gasLimit, chainId, + data != null ? Numeric.toHexString(data) : "0x", "")) + .subscribeOn(Schedulers.io()); + } + + /** + * * Given a Web3Transaction, return a signature. Note that we can't fix up nonce, gas price or limit; + * * This is a request to sign a transaction from an external source - + * * presumably that external source will broadcast the transaction; together with this signature + * + * @param from + * @param toAddress + * @param subunitAmount + * @param gasPrice + * @param gasLimit + * @param nonce + * @param data + * @param chainId + * @return + */ + @Override + public Single getSignatureForTransaction(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, long nonce, + byte[] data, long chainId) + { + final Web3j web3j = getWeb3jService(chainId); + final BigInteger useGasPrice = gasPriceForNode(chainId, gasPrice); + TransactionData txData = new TransactionData(); + + return getNonceForTransaction(web3j, from.address, nonce) + .flatMap(txNonce -> { + txData.nonce = txNonce; + return accountKeystoreService.signTransaction(from, toAddress, subunitAmount, useGasPrice, gasLimit, txNonce.longValue(), data, chainId); + }) + .flatMap(signedMessage -> Single.fromCallable(() -> { + if (signedMessage.sigType != SignatureReturnType.SIGNATURE_GENERATED) + { + throw new Exception(signedMessage.failMessage); + } + txData.signature = Numeric.toHexString(signedMessage.signature); + return txData; + })); + } + + private BigInteger gasPriceForNode(long chainId, BigInteger gasPrice) + { + if (EthereumNetworkRepository.hasGasOverride(chainId)) return EthereumNetworkRepository.gasOverrideValue(chainId); + else return gasPrice; + } + + //EIP1559 + private Single storeUnconfirmedTransaction(Wallet from, TransactionData txData, String toAddress, BigInteger value, BigInteger nonce, BigInteger maxFeePerGas, + BigInteger maxPriorityFee, BigInteger gasLimit, long chainId, String data, String contractAddr) + { + return Single.fromCallable(() -> { + Transaction newTx = new Transaction(txData.txHash, "0", "0", System.currentTimeMillis() / 1000, nonce.intValue(), from.address, toAddress, + value.toString(10), "0", "0", maxFeePerGas.toString(10), + maxPriorityFee.toString(10), data, + gasLimit.toString(10), chainId, contractAddr); + inDiskCache.putTransaction(from, newTx); + transactionsService.markPending(newTx); + + return txData; + }); + } + + private Single storeUnconfirmedTransaction(Wallet from, TransactionData txData, String toAddress, BigInteger value, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, + long chainId, String data, String contractAddr) + { + return Single.fromCallable(() -> { + Transaction newTx = new Transaction(txData.txHash, "0", "0", System.currentTimeMillis() / 1000, nonce.intValue(), from.address, toAddress, + value.toString(10), "0", gasPrice.toString(10), data, + gasLimit.toString(10), chainId, contractAddr); + //newTx.completeSetup(from.address); + inDiskCache.putTransaction(from, newTx); + transactionsService.markPending(newTx); + + return txData; + }); + } + + private Single storeUnconfirmedTransaction(Wallet from, String txHash, String toAddress, BigInteger value, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, + long chainId, String data) + { + return Single.fromCallable(() -> { + + Transaction newTx = new Transaction(txHash, "0", "0", System.currentTimeMillis() / 1000, nonce.intValue(), from.address, + toAddress, value.toString(10), "0", gasPrice.toString(10), data, + gasLimit.toString(10), chainId, ""); + //newTx.completeSetup(from.address); + inDiskCache.putTransaction(from, newTx); + transactionsService.markPending(newTx); + + return txHash; + }); + } + + @Override + public Single getSignature(Wallet wallet, Signable message) + { + return accountKeystoreService.signMessage(wallet, message); + } + + @Override + public Single getSignatureFast(Wallet wallet, String password, byte[] message) + { + return accountKeystoreService.signMessageFast(wallet, password, message); + } + + @Override + public Single fetchCachedTransactionMetas(Wallet wallet, List networkFilters, long fetchTime, int fetchLimit) + { + return inDiskCache.fetchActivityMetas(wallet, networkFilters, fetchTime, fetchLimit); + } + + @Override + public Single fetchCachedTransactionMetas(Wallet wallet, long chainId, String tokenAddress, int historyCount) + { + return inDiskCache.fetchActivityMetas(wallet, chainId, tokenAddress, historyCount); + } + + @Override + public Single fetchEventMetas(Wallet wallet, List networkFilters) + { + return inDiskCache.fetchEventMetas(wallet, networkFilters); + } + + @Override + public Realm getRealmInstance(Wallet wallet) + { + return inDiskCache.getRealmInstance(wallet); + } + + @Override + public RealmAuxData fetchCachedEvent(String walletAddress, String eventKey) + { + return inDiskCache.fetchEvent(walletAddress, eventKey); + } + + @Override + public void restartService() + { + transactionsService.startUpdateCycle(); + } + + private Single getNonceForTransaction(Web3j web3j, String wallet, long nonce) + { + if (nonce != -1) //use supplied nonce + { + return Single.fromCallable(() -> BigInteger.valueOf(nonce)); + } + else + { + return networkRepository.getLastTransactionNonce(web3j, wallet); + } + } } diff --git a/app/src/main/java/com/alphawallet/app/repository/TransactionRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/TransactionRepositoryType.java index 9cc3abfe0c..957f0ca404 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TransactionRepositoryType.java +++ b/app/src/main/java/com/alphawallet/app/repository/TransactionRepositoryType.java @@ -14,26 +14,33 @@ import io.reactivex.Single; import io.realm.Realm; -public interface TransactionRepositoryType { - Single createTransactionWithSig(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId); - Single create1559TransactionWithSig(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasLimit, BigInteger maxFeePerGas, BigInteger maxPriorityFee, long nonce, byte[] data, long chainId); - Single getSignatureForTransaction(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId); +public interface TransactionRepositoryType +{ + Single createTransactionWithSig(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId); - Single getSignature(Wallet wallet, Signable message, long chainId); - Single getSignatureFast(Wallet wallet, String password, byte[] message, long chainId); + Single create1559TransactionWithSig(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasLimit, BigInteger maxFeePerGas, BigInteger maxPriorityFee, long nonce, byte[] data, long chainId); + + Single getSignatureForTransaction(Wallet from, String toAddress, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId); + + Single getSignature(Wallet wallet, Signable message); + + Single getSignatureFast(Wallet wallet, String password, byte[] message); Transaction fetchCachedTransaction(String walletAddr, String hash); - long fetchTxCompletionTime(String walletAddr, String hash); - Single resendTransaction(Wallet from, String to, BigInteger subunitAmount, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, byte[] data, long chainId); + long fetchTxCompletionTime(String walletAddr, String hash); + + Single resendTransaction(Wallet from, String to, BigInteger subunitAmount, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, byte[] data, long chainId); Single fetchCachedTransactionMetas(Wallet wallet, List networkFilters, long fetchTime, int fetchLimit); - Single fetchCachedTransactionMetas(Wallet wallet, long chainId, String tokenAddress, int historyCount); - Single fetchEventMetas(Wallet wallet, List networkFilters); - Realm getRealmInstance(Wallet wallet); + Single fetchCachedTransactionMetas(Wallet wallet, long chainId, String tokenAddress, int historyCount); + + Single fetchEventMetas(Wallet wallet, List networkFilters); + + Realm getRealmInstance(Wallet wallet); - RealmAuxData fetchCachedEvent(String walletAddress, String eventKey); + RealmAuxData fetchCachedEvent(String walletAddress, String eventKey); void restartService(); } diff --git a/app/src/main/java/com/alphawallet/app/service/AccountKeystoreService.java b/app/src/main/java/com/alphawallet/app/service/AccountKeystoreService.java index 5fdae0a9f3..cf35e7e936 100644 --- a/app/src/main/java/com/alphawallet/app/service/AccountKeystoreService.java +++ b/app/src/main/java/com/alphawallet/app/service/AccountKeystoreService.java @@ -79,14 +79,12 @@ Single signTransactionEIP1559( Single signMessage( Wallet signer, - Signable message, - long chainId); + Signable messaged); - Single signTransactionFast( + Single signMessageFast( Wallet signer, String password, - byte[] message, - long chainId); + byte[] message); /** * Check if there is an address in the keystore diff --git a/app/src/main/java/com/alphawallet/app/service/KeystoreAccountService.java b/app/src/main/java/com/alphawallet/app/service/KeystoreAccountService.java index fa494e0af4..c18ffa7030 100644 --- a/app/src/main/java/com/alphawallet/app/service/KeystoreAccountService.java +++ b/app/src/main/java/com/alphawallet/app/service/KeystoreAccountService.java @@ -58,7 +58,8 @@ public class KeystoreAccountService implements AccountKeystoreService private final KeyService keyService; private static final ObjectMapper objectMapper = new ObjectMapper(); - public KeystoreAccountService(File keyStoreFile, File baseFile, KeyService keyService) { + public KeystoreAccountService(File keyStoreFile, File baseFile, KeyService keyService) + { keyFolder = keyStoreFile; databaseFolder = baseFile; this.keyService = keyService; @@ -74,35 +75,40 @@ public KeystoreAccountService(File keyStoreFile, File baseFile, KeyService keySe /** * No longer used; keep for testing + * * @param password account password * @return */ @Override - public Single createAccount(String password) { + public Single createAccount(String password) + { return Single.fromCallable(() -> { - ECKeyPair ecKeyPair = Keys.createEcKeyPair(); - WalletFile walletFile = org.web3j.crypto.Wallet.createLight(password, ecKeyPair); - return objectMapper.writeValueAsString(walletFile); - }).compose(upstream -> importKeystore(upstream.blockingGet(), password, password)) - .subscribeOn(Schedulers.io()); + ECKeyPair ecKeyPair = Keys.createEcKeyPair(); + WalletFile walletFile = org.web3j.crypto.Wallet.createLight(password, ecKeyPair); + return objectMapper.writeValueAsString(walletFile); + }).compose(upstream -> importKeystore(upstream.blockingGet(), password, password)) + .subscribeOn(Schedulers.io()); } /** * Import Keystore - * @param store store to include - * @param password store password + * + * @param store store to include + * @param password store password * @param newPassword * @return */ @Override - public Single importKeystore(String store, String password, String newPassword) { + public Single importKeystore(String store, String password, String newPassword) + { return Single.fromCallable(() -> { String address = extractAddressFromStore(store); Wallet wallet; //delete old account files - these have had their password overwritten. If present user chose to refresh key deleteAccountFiles(address); - try { + try + { WalletFile walletFile = objectMapper.readValue(store, WalletFile.class); ECKeyPair kp = org.web3j.crypto.Wallet.decrypt(password, walletFile); Credentials credentials = Credentials.create(kp); @@ -118,7 +124,9 @@ public Single importKeystore(String store, String password, String newPa wallet = new Wallet(credentials.getAddress()); wallet.setWalletType(WalletType.KEYSTORE); - } catch (Exception ex) { + } + catch (Exception ex) + { // We need to make sure that we do not have a broken account deleteAccount(address, newPassword).subscribe(() -> {}, t -> {}).isDisposed(); throw ex; @@ -128,11 +136,15 @@ public Single importKeystore(String store, String password, String newPa }).subscribeOn(Schedulers.io()); } - private String extractAddressFromStore(String store) throws Exception { - try { + private String extractAddressFromStore(String store) throws Exception + { + try + { JSONObject jsonObject = new JSONObject(store); return "0x" + Numeric.cleanHexPrefix(jsonObject.getString("address")); - } catch (JSONException ex) { + } + catch (JSONException ex) + { throw new Exception("Invalid keystore"); } } @@ -145,7 +157,8 @@ private String extractAddressFromStore(String store) throws Exception { * @return */ @Override - public Single importPrivateKey(String privateKey, String newPassword) { + public Single importPrivateKey(String privateKey, String newPassword) + { return Single.fromCallable(() -> { BigInteger key = new BigInteger(privateKey, PRIVATE_KEY_RADIX); ECKeyPair keypair = ECKeyPair.create(key); @@ -155,7 +168,8 @@ public Single importPrivateKey(String privateKey, String newPassword) { } @Override - public Single exportAccount(Wallet wallet, String password, String newPassword) { + public Single exportAccount(Wallet wallet, String password, String newPassword) + { return Single .fromCallable(() -> getCredentials(keyFolder, wallet.address, password)) .map(credentials -> org.web3j.crypto.Wallet.createLight(newPassword, credentials.getEcKeyPair())) @@ -166,12 +180,14 @@ public Single exportAccount(Wallet wallet, String password, String newPa /** * Delete 'geth' keystore file then ensure password encrypted bytes and keys in Android keystore * are deleted - * @param address account address + * + * @param address account address * @param password account password * @return */ @Override - public Completable deleteAccount(String address, String password) { + public Completable deleteAccount(String address, String password) + { return Completable.fromAction(() -> { String cleanedAddr = Numeric.cleanHexPrefix(address).toLowerCase(); deleteAccountFiles(cleanedAddr); @@ -192,7 +208,7 @@ public Completable deleteAccount(String address, String password) { //Now delete all traces of the key in Android keystore, encrypted bytes and iv file in private data area keyService.deleteKey(address); - } ); + }); } private void deleteAccountFiles(String address) @@ -219,7 +235,9 @@ private void deleteRecursive(File fp) if (contents != null) { for (File child : contents) + { deleteRecursive(child); + } } } @@ -227,22 +245,23 @@ private void deleteRecursive(File fp) } @Override - public Single signTransaction(Wallet signer, String toAddress, BigInteger amount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId) { + public Single signTransaction(Wallet signer, String toAddress, BigInteger amount, BigInteger gasPrice, BigInteger gasLimit, long nonce, byte[] data, long chainId) + { return Single.fromCallable(() -> { - RawTransaction rtx = formatRawTransaction(toAddress, amount, gasPrice, gasLimit, nonce, data); - byte[] signData = TransactionEncoder.encode(rtx, chainId); - SignatureFromKey returnSig = keyService.signData(signer, signData); - Sign.SignatureData sigData = sigFromByteArray(returnSig.signature); - if (sigData == null) - { - returnSig.sigType = SignatureReturnType.KEY_CIPHER_ERROR; - returnSig.failMessage = "Incorrect signature length"; //should never see this message - } - else sigData = TransactionEncoder.createEip155SignatureData(sigData, chainId); - returnSig.signature = encode(rtx, sigData); - return returnSig; - }) - .subscribeOn(Schedulers.io()); + RawTransaction rtx = formatRawTransaction(toAddress, amount, gasPrice, gasLimit, nonce, data); + byte[] signData = TransactionEncoder.encode(rtx, chainId); + SignatureFromKey returnSig = keyService.signData(signer, signData); + Sign.SignatureData sigData = sigFromByteArray(returnSig.signature); + if (sigData == null) + { + returnSig.sigType = SignatureReturnType.KEY_CIPHER_ERROR; + returnSig.failMessage = "Incorrect signature length"; //should never see this message + } + else sigData = TransactionEncoder.createEip155SignatureData(sigData, chainId); + returnSig.signature = encode(rtx, sigData); + return returnSig; + }) + .subscribeOn(Schedulers.io()); } @Override @@ -268,7 +287,8 @@ public Single signTransactionEIP1559(Wallet signer, String toA SignatureFromKey returnSig = keyService.signData(signer, signData); sigData = sigFromByteArray(returnSig.signature); - if (sigData == null) { + if (sigData == null) + { returnSig.sigType = SignatureReturnType.KEY_CIPHER_ERROR; returnSig.failMessage = "Incorrect signature length"; //should never see this message } @@ -277,11 +297,13 @@ public Single signTransactionEIP1559(Wallet signer, String toA }).subscribeOn(Schedulers.io()); } - private static byte[] encode(RawTransaction rawTransaction, Sign.SignatureData signatureData) { + private static byte[] encode(RawTransaction rawTransaction, Sign.SignatureData signatureData) + { List values = TransactionEncoder.asRlpValues(rawTransaction, signatureData); RlpList rlpList = new RlpList(values); byte[] encoded = RlpEncoder.encode(rlpList); - if (!rawTransaction.getType().equals(TransactionType.LEGACY)) { + if (!rawTransaction.getType().equals(TransactionType.LEGACY)) + { return ByteBuffer.allocate(encoded.length + 1) .put(rawTransaction.getType().getRlpType()) .put(encoded) @@ -292,6 +314,7 @@ private static byte[] encode(RawTransaction rawTransaction, Sign.SignatureData s /** * Get web3j credentials + * * @param keyFolder KeyStore Folder * @param address * @param password @@ -343,7 +366,8 @@ public static Credentials getCredentialsWithThrow(File keyFolder, String address } @Override - public Single signTransactionFast(Wallet signer, String signerPassword, byte[] message, long chainId) { + public Single signMessageFast(Wallet signer, String signerPassword, byte[] message) + { return Single.fromCallable(() -> { Credentials credentials = getCredentials(keyFolder, signer.address, signerPassword); Sign.SignatureData signatureData = Sign.signMessage( @@ -355,10 +379,9 @@ public Single signTransactionFast(Wallet signer, String signerPassword, } @Override - public Single signMessage(Wallet signer, Signable message, long chainId) + public Single signMessage(Wallet signer, Signable message) { return Single.fromCallable(() -> { - //byte[] messageHash = Hash.sha3(message); SignatureFromKey returnSig = keyService.signData(signer, message.getPrehash()); returnSig.signature = patchSignatureVComponent(returnSig.signature); return returnSig; @@ -366,7 +389,8 @@ public Single signMessage(Wallet signer, Signable message, lon } @Override - public boolean hasAccount(String address) { + public boolean hasAccount(String address) + { address = Numeric.cleanHexPrefix(address); File[] contents = keyFolder.listFiles(); if (contents == null) return false; @@ -382,44 +406,45 @@ public boolean hasAccount(String address) { } @Override - public Single fetchAccounts() { + public Single fetchAccounts() + { return Single.fromCallable(() -> { - File[] contents = keyFolder.listFiles(); - List fileDates = new ArrayList<>(); - Map walletMap = new HashMap<>(); - List wallets = new ArrayList<>(); - if (contents == null || contents.length == 0) return new Wallet[0]; - //Wallet[] result = new Wallet[contents.length]; - for (File f : contents) - { - String fName = f.getName(); - int index = fName.lastIndexOf("-"); - String address = "0x" + fName.substring(index + 1); - if (Utils.isAddressValid(address)) - { - String d = fName.substring(5, index-1).replace("T", " ").substring(0, 23); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss.SSS", Locale.ROOT); - Date date = simpleDateFormat.parse(d); - fileDates.add(date); - walletMap.put(date, address); - } - } + File[] contents = keyFolder.listFiles(); + List fileDates = new ArrayList<>(); + Map walletMap = new HashMap<>(); + List wallets = new ArrayList<>(); + if (contents == null || contents.length == 0) return new Wallet[0]; + //Wallet[] result = new Wallet[contents.length]; + for (File f : contents) + { + String fName = f.getName(); + int index = fName.lastIndexOf("-"); + String address = "0x" + fName.substring(index + 1); + if (Utils.isAddressValid(address)) + { + String d = fName.substring(5, index - 1).replace("T", " ").substring(0, 23); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss.SSS", Locale.ROOT); + Date date = simpleDateFormat.parse(d); + fileDates.add(date); + walletMap.put(date, address); + } + } - Collections.sort(fileDates); + Collections.sort(fileDates); - //now build a date sorted array: - for (Date d : fileDates) - { - String address = walletMap.get(d); - Wallet wallet = new Wallet(address); - wallet.type = WalletType.KEYSTORE; - wallet.walletCreationTime = d.getTime(); - wallets.add(wallet); - } + //now build a date sorted array: + for (Date d : fileDates) + { + String address = walletMap.get(d); + Wallet wallet = new Wallet(address); + wallet.type = WalletType.KEYSTORE; + wallet.walletCreationTime = d.getTime(); + wallets.add(wallet); + } - return wallets.toArray(new Wallet[0]); - }) - .subscribeOn(Schedulers.io()); + return wallets.toArray(new Wallet[0]); + }) + .subscribeOn(Schedulers.io()); } /** @@ -437,7 +462,7 @@ private byte[] patchSignatureVComponent(byte[] signature) { if (signature != null && signature.length == 65 && signature[64] < 27) { - signature[64] = (byte)(signature[64] + (byte)0x1b); + signature[64] = (byte) (signature[64] + (byte) 0x1b); } return signature; diff --git a/app/src/main/java/com/alphawallet/app/ui/AssetDisplayActivity.java b/app/src/main/java/com/alphawallet/app/ui/AssetDisplayActivity.java index 4fcbddb0a0..333f7e16a6 100644 --- a/app/src/main/java/com/alphawallet/app/ui/AssetDisplayActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/AssetDisplayActivity.java @@ -1,5 +1,8 @@ package com.alphawallet.app.ui; +import static com.alphawallet.app.C.Key.WALLET; +import static com.alphawallet.app.widget.AWalletAlertDialog.WARNING; + import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -48,15 +51,10 @@ import java.util.List; import java.util.Map; -import javax.inject.Inject; - import dagger.hilt.android.AndroidEntryPoint; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; -import static com.alphawallet.app.C.Key.WALLET; -import static com.alphawallet.app.widget.AWalletAlertDialog.WARNING; - /** * Created by James on 22/01/2018. */ @@ -441,7 +439,7 @@ private void displayTokens() { handler.removeCallbacks(this); progressView.setVisibility(View.GONE); - adapter = new NonFungibleTokenAdapter(functionBar, token, viewModel.getAssetDefinitionService(), viewModel.getOpenseaService(), this); + adapter = new NonFungibleTokenAdapter(functionBar, token, viewModel.getAssetDefinitionService(), viewModel.getOpenseaService()); functionBar.setupFunctions(this, viewModel.getAssetDefinitionService(), token, adapter, token.getArrayBalance()); functionBar.setWalletType(wallet.type); tokenView.setAdapter(adapter); diff --git a/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java b/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java index 3b446adab7..5e91a90bef 100644 --- a/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/BaseActivity.java @@ -5,20 +5,23 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.DrawableRes; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; + import com.alphawallet.app.R; +import com.alphawallet.app.entity.AuthenticationCallback; import com.alphawallet.app.entity.AuthenticationFailType; import com.alphawallet.app.entity.Operation; -import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.alphawallet.app.viewmodel.BaseViewModel; import com.alphawallet.app.widget.SignTransactionDialog; -import androidx.annotation.DrawableRes; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; - public abstract class BaseActivity extends AppCompatActivity { + public static AuthenticationCallback authCallback; // Note: This static is only for signing callbacks + // which won't occur between wallet sessions - do not repeat this pattern + // for other code protected Toolbar toolbar() { @@ -139,7 +142,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) //Interpret the return code; if it's within the range of values possible to return from PIN confirmation then separate out //the task code from the return value. We have to do it this way because there's no way to send a bundle across the PIN dialog //and out through the PIN dialog's return back to here - if (AWWalletConnectClient.authCallback == null) + if (authCallback == null) { return; } @@ -149,12 +152,14 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) Operation taskCode = Operation.values()[requestCode - SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS]; if (resultCode == RESULT_OK) { - AWWalletConnectClient.authCallback.authenticatePass(taskCode); + authCallback.authenticatePass(taskCode); } else { - AWWalletConnectClient.authCallback.authenticateFail("", AuthenticationFailType.PIN_FAILED, taskCode); + authCallback.authenticateFail("", AuthenticationFailType.PIN_FAILED, taskCode); } + + authCallback = null; } } } diff --git a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java index 1f241c52ae..3162e176cc 100644 --- a/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java @@ -2,11 +2,9 @@ import static com.alphawallet.app.C.ETHER_DECIMALS; import static com.alphawallet.app.C.RESET_TOOLBAR; -import static com.alphawallet.app.entity.Operation.SIGN_DATA; import static com.alphawallet.app.entity.tokens.Token.TOKEN_BALANCE_PRECISION; import static com.alphawallet.app.ui.HomeActivity.RESET_TOKEN_SERVICE; import static com.alphawallet.app.ui.MyAddressActivity.KEY_ADDRESS; -import static com.alphawallet.app.util.KeyboardUtils.showKeyboard; import static com.alphawallet.app.util.Utils.isValidUrl; import static com.alphawallet.app.widget.AWalletAlertDialog.ERROR; import static com.alphawallet.app.widget.AWalletAlertDialog.WARNING; @@ -65,7 +63,6 @@ import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.DApp; -import com.alphawallet.app.entity.DAppFunction; import com.alphawallet.app.entity.FragmentMessenger; import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.entity.QRResult; @@ -76,6 +73,7 @@ import com.alphawallet.app.entity.WalletConnectActions; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.analytics.ActionSheetSource; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.TokenRepository; @@ -107,7 +105,9 @@ import com.alphawallet.app.web3.entity.Web3Call; import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; +import com.alphawallet.app.widget.ActionSheet; import com.alphawallet.app.widget.ActionSheetDialog; +import com.alphawallet.app.widget.ActionSheetSignDialog; import com.alphawallet.app.widget.AddressBar; import com.alphawallet.app.widget.AddressBarListener; import com.alphawallet.app.widget.TestNetDialog; @@ -183,7 +183,7 @@ public void onActivityResult(Uri uri) private WebChromeClient.FileChooserParams fileChooserParams; private RealmResults realmUpdate; private Realm realm = null; - private ActionSheetDialog confirmationDialog; + private ActionSheet confirmationDialog; ActivityResultLauncher getGasSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> confirmationDialog.setCurrentGasIndex(result)); private DappBrowserViewModel viewModel; @@ -267,7 +267,6 @@ else if (heightDifference == 0 && layoutParams.bottomMargin != navBarHeight) // Some multi-chain Dapps have a watchdog thread that checks the chain // This thread stays in operation until a new page load is complete. private String loadUrlAfterReload; - private DAppFunction dAppFunction; @Override public void onCreate(@Nullable Bundle savedInstanceState) @@ -1155,35 +1154,29 @@ private void showChainChangeDialog(long callbackId, NetworkInfo newNetwork) private void handleSignMessage(Signable message) { - dAppFunction = new DAppFunction() - { - @Override - public void DAppError(Throwable error, Signable message) - { - web3.onSignCancel(message.getCallbackId()); - confirmationDialog.dismiss(); - } - - @Override - public void DAppReturn(byte[] data, Signable message) - { - String signHex = Numeric.toHexString(data); - Timber.d("Initial Msg: %s", message.getMessage()); - web3.onSignMessageSuccessful(message, signHex); - - confirmationDialog.success(); - } - }; - if (confirmationDialog == null || !confirmationDialog.isShowing()) { - confirmationDialog = new ActionSheetDialog(requireActivity(), this, this, message); - confirmationDialog.setCanceledOnTouchOutside(false); + confirmationDialog = new ActionSheetSignDialog(requireActivity(), this, message); confirmationDialog.show(); - confirmationDialog.fullExpand(); } } + @Override + public void signingComplete(SignatureFromKey signature, Signable message) + { + String signHex = Numeric.toHexString(signature.signature); + Timber.d("Initial Msg: %s", message.getMessage()); + confirmationDialog.success(); + web3.onSignMessageSuccessful(message, signHex); + } + + @Override + public void signingFailed(Throwable error, Signable message) + { + web3.onSignCancel(message.getCallbackId()); + confirmationDialog.dismiss(); + } + @Override public void onSignTransaction(Web3Transaction transaction, String url) { @@ -1811,34 +1804,6 @@ public void gotAuthorisation(boolean gotAuth) } } - @Override - public void gotAuthorisationForSigning(boolean gotAuth, Signable messageToSign) - { - if (gotAuth) - { - viewModel.completeAuthentication(SIGN_DATA); - viewModel.signMessage(messageToSign, dAppFunction); - } - else - { - web3.onSignCancel(messageToSign.getCallbackId()); - } - } - - /** - * Endpoint from PIN/Swipe authorisation - * - * @param gotAuth - */ - @Override - public void pinAuthorisation(boolean gotAuth) - { - if (confirmationDialog != null && confirmationDialog.isShowing()) - { - confirmationDialog.completeSignRequest(gotAuth); - } - } - @Override public void buttonClick(long callbackId, Token baseToken) { 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 0876ed35ce..6679bafe59 100644 --- a/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java @@ -18,7 +18,6 @@ import android.view.View; import android.webkit.WebView; import android.widget.LinearLayout; -import android.widget.ProgressBar; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; @@ -29,10 +28,10 @@ import com.alphawallet.app.C; import com.alphawallet.app.R; import com.alphawallet.app.entity.DApp; -import com.alphawallet.app.entity.DAppFunction; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.TransactionData; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokenscript.TokenScriptRenderCallback; import com.alphawallet.app.entity.tokenscript.WebCompletionCallback; @@ -49,7 +48,9 @@ import com.alphawallet.app.web3.entity.PageReadyCallback; import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; +import com.alphawallet.app.widget.ActionSheet; import com.alphawallet.app.widget.ActionSheetDialog; +import com.alphawallet.app.widget.ActionSheetSignDialog; import com.alphawallet.app.widget.FunctionButtonBar; import com.alphawallet.app.widget.SignTransactionDialog; import com.alphawallet.ethereum.EthereumNetworkBase; @@ -103,7 +104,7 @@ public class FunctionActivity extends BaseActivity implements FunctionCallback, private int parsePass = 0; private int resolveInputCheckCount; private TSAction action; - private ActionSheetDialog confirmationDialog; + private ActionSheet confirmationDialog; private void initViews() { actionMethod = getIntent().getStringExtra(C.EXTRA_STATE); @@ -135,9 +136,6 @@ private void initViews() { viewModel.startGasPriceUpdate(token.tokenInfo.chainId); viewModel.getCurrentWallet(); parsePass = 0; - - ProgressBar loadSpinner = findViewById(R.id.ticket_load_spinner); - handler.postDelayed(() -> loadSpinner.setVisibility(View.GONE), 2500); } private void displayFunction(String tokenAttrs) @@ -549,12 +547,6 @@ private void showTransactionError() alertDialog.show(); } - @Override - public void signMessage(Signable message, DAppFunction dAppFunction) - { - viewModel.signMessage(message, dAppFunction, token.tokenInfo.chainId); - } - @Override public void functionSuccess() { @@ -638,8 +630,7 @@ public void onRestoreInstanceState(Bundle savedInstanceState) public void onSignPersonalMessage(EthereumMessage message) { //pop open the actionsheet - confirmationDialog = new ActionSheetDialog(this, this, this, message); - confirmationDialog.setCanceledOnTouchOutside(false); + confirmationDialog = new ActionSheetSignDialog(this, this, message); //new ActionSheetDialog(this, this, this, message); confirmationDialog.show(); confirmationDialog.fullExpand(); } @@ -785,39 +776,19 @@ public void gotAuthorisation(boolean gotAuth) } @Override - public void gotAuthorisationForSigning(boolean gotAuth, Signable messageToSign) + public void signingComplete(SignatureFromKey signature, Signable message) { - viewModel.completeAuthentication(SIGN_DATA); - - DAppFunction dAppFunction = new DAppFunction() - { - @Override - public void DAppError(Throwable error, Signable message) - { - confirmationDialog.dismiss(); - tokenView.onSignCancel(message); - functionFailed(); - } - - @Override - public void DAppReturn(byte[] data, Signable message) - { - String signHex = Numeric.toHexString(data); - signHex = Numeric.cleanHexPrefix(signHex); - tokenView.onSignPersonalMessageSuccessful(message, signHex); - testRecoverAddressFromSignature(message.getMessage(), signHex); - confirmationDialog.success(); - } - }; + String signHex = Numeric.toHexString(signature.signature); + signHex = Numeric.cleanHexPrefix(signHex); + tokenView.onSignPersonalMessageSuccessful(message, signHex); + testRecoverAddressFromSignature(message.getMessage(), signHex); + } - if (gotAuth) - { - signMessage(messageToSign, dAppFunction); - } - else - { - confirmationDialog.dismiss(); - } + @Override + public void signingFailed(Throwable error, Signable message) + { + tokenView.onSignCancel(message); + functionFailed(); } @Override diff --git a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java index 2c073ede66..92d24aa0af 100644 --- a/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/HomeActivity.java @@ -55,7 +55,6 @@ import com.alphawallet.app.R; import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.api.v1.entity.request.ApiV1Request; -import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.CustomViewSettings; @@ -66,21 +65,27 @@ import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletPage; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.router.ImportTokenRouter; import com.alphawallet.app.service.NotificationService; import com.alphawallet.app.service.PriceAlertsService; +import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.ui.widget.entity.PagerCallback; import com.alphawallet.app.util.LocaleUtils; import com.alphawallet.app.util.UpdateUtils; import com.alphawallet.app.util.Utils; import com.alphawallet.app.viewmodel.BaseNavigationActivity; import com.alphawallet.app.viewmodel.HomeViewModel; +import com.alphawallet.app.viewmodel.WalletConnectViewModel; +import com.alphawallet.app.walletconnect.AWWalletConnectClient; import com.alphawallet.app.walletconnect.WCSession; +import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.AWalletConfirmationDialog; -import com.alphawallet.app.widget.SignTransactionDialog; import com.alphawallet.token.entity.SalesOrderMalformed; +import com.alphawallet.token.entity.Signable; +import com.alphawallet.token.tools.Numeric; import com.alphawallet.token.tools.ParseMagicLink; import com.github.florent37.tutoshowcase.TutoShowcase; @@ -90,13 +95,18 @@ import java.net.URLDecoder; import java.util.List; +import javax.inject.Inject; + import dagger.hilt.android.AndroidEntryPoint; import timber.log.Timber; @AndroidEntryPoint public class HomeActivity extends BaseNavigationActivity implements View.OnClickListener, HomeCommsInterface, - FragmentMessenger, Runnable, SignAuthenticationCallback, LifecycleObserver, PagerCallback + FragmentMessenger, Runnable, SignAuthenticationCallback, ActionSheetCallback, LifecycleObserver, PagerCallback { + @Inject + AWWalletConnectClient awWalletConnectClient; + public static final int RC_ASSET_EXTERNAL_WRITE_PERM = 223; public static final int RC_ASSET_NOTIFICATION_PERM = 224; public static final int DAPP_BARCODE_READER_REQUEST_CODE = 1; @@ -111,6 +121,7 @@ public class HomeActivity extends BaseNavigationActivity implements View.OnClick result -> getSupportFragmentManager().setFragmentResult(RESET_TOKEN_SERVICE, new Bundle())); private HomeViewModel viewModel; + private WalletConnectViewModel viewModelWC; private Dialog dialog; private ViewPager2 viewPager; private LinearLayout successOverlay; @@ -197,11 +208,15 @@ protected void onCreate(@Nullable Bundle savedInstanceState) LocaleUtils.setActiveLocale(this); getLifecycle().addObserver(this); isForeground = true; + setWCConnect(); if (getSupportActionBar() != null) getSupportActionBar().hide(); viewModel = new ViewModelProvider(this) .get(HomeViewModel.class); + viewModelWC = new ViewModelProvider(this) + .get(WalletConnectViewModel.class); + viewModel.identify(); viewModel.setWalletStartup(); viewModel.setCurrencyAndLocale(this); @@ -305,6 +320,18 @@ public void onPageScrollStateChanged(int state) startService(i); } + private void setWCConnect() + { + try + { + awWalletConnectClient.init(this); + } + catch (Exception e) + { + Timber.tag("WalletConnect").e(e); + } + } + private void onDefaultWallet(Wallet wallet) { if (viewModel.checkNewWallet(wallet.address)) @@ -500,6 +527,7 @@ private void onError(ErrorEnvelope errorEnvelope) protected void onResume() { super.onResume(); + setWCConnect(); viewModel.prepare(this); viewModel.getWalletName(this); viewModel.setErrorCallback(this); @@ -926,11 +954,7 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode >= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS && requestCode <= SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + 10) - { - requestCode = SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS; - } + super.onActivityResult(requestCode, resultCode, data); // intercept return intent from PIN/Swipe authentications switch (requestCode) { @@ -945,16 +969,6 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) if (resultCode == RESULT_OK) backupWalletSuccess(keyBackup); else backupWalletFail(keyBackup, noLockScreen); break; - case SignTransactionDialog.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS: - switch (getSelectedItem()) - { - case DAPP_BROWSER: - getFragment(DAPP_BROWSER).pinAuthorisation(resultCode == RESULT_OK); - break; - default: - break; - } - break; case C.REQUEST_UNIVERSAL_SCAN: if (data != null && resultCode == Activity.RESULT_OK) { @@ -1150,6 +1164,58 @@ else if (importPath != null) } } + @Override + public void signingComplete(SignatureFromKey signature, Signable message) + { + String signHex = Numeric.toHexString(signature.signature); + Timber.d("Initial Msg: %s", message.getMessage()); + awWalletConnectClient.signComplete(signature, message); + } + + @Override + public void signingFailed(Throwable error, Signable message) + { + awWalletConnectClient.signFail(error.getMessage(), message); + } + + @Override + public void getAuthorisation(SignAuthenticationCallback callback) + { + viewModelWC.getAuthenticationForSignature(viewModel.defaultWallet().getValue(), this, callback); + } + + @Override + public void sendTransaction(Web3Transaction tx) + { + + } + + @Override + public void dismissed(String txHash, long callbackId, boolean actionCompleted) + { + if (!actionCompleted) + { + awWalletConnectClient.dismissed(callbackId); + } + } + + @Override + public void notifyConfirm(String mode) + { + + } + + //TODO: Implement when passing transactions through here + ActivityResultLauncher getGasSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + result -> { //awWalletConnectClient.setCurrentGasIndex(result)); + }); + + @Override + public ActivityResultLauncher gasSelectLauncher() + { + return getGasSettings; + } + private static class ScreenSlidePagerAdapter extends FragmentStateAdapter { public ScreenSlidePagerAdapter(@NonNull FragmentActivity fragmentActivity) @@ -1188,4 +1254,4 @@ public int getItemCount() return WalletPage.values().length; } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java index 09b02fb5f7..a3f168a5b4 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java @@ -164,7 +164,7 @@ private void initAndAttachAdapter(boolean isGridView) if (hasTokenScriptOverride(token)) { searchLayout.setVisibility(View.GONE); - adapter = new NonFungibleTokenAdapter(this, token, viewModel.getAssetDefinitionService(), viewModel.getOpenseaService(), getActivity(), isGridView); + adapter = new NonFungibleTokenAdapter(this, token, viewModel.getAssetDefinitionService(), viewModel.getOpenseaService(), isGridView); } else { diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java index b51293b3f3..1694952526 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectActivity.java @@ -40,6 +40,7 @@ import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.analytics.ActionSheetSource; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.walletconnect.WCRequest; import com.alphawallet.app.repository.EthereumNetworkBase; @@ -58,7 +59,9 @@ import com.alphawallet.app.web3.entity.WalletAddEthereumChainObject; import com.alphawallet.app.web3.entity.Web3Transaction; import com.alphawallet.app.widget.AWalletAlertDialog; +import com.alphawallet.app.widget.ActionSheet; import com.alphawallet.app.widget.ActionSheetDialog; +import com.alphawallet.app.widget.ActionSheetSignDialog; import com.alphawallet.app.widget.ChainName; import com.alphawallet.app.widget.FunctionButtonBar; import com.alphawallet.app.widget.SignTransactionDialog; @@ -101,7 +104,7 @@ public class WalletConnectActivity extends BaseActivity implements ActionSheetCa private WCSession session; private WCPeerMeta peerMeta; private WCPeerMeta remotePeerMeta; - private ActionSheetDialog confirmationDialog; + private ActionSheet confirmationDialog; ActivityResultLauncher getGasSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> confirmationDialog.setCurrentGasIndex(result)); private AddEthereumChainPrompt addEthereumChainPrompt; @@ -840,80 +843,39 @@ private void onFailure(@NonNull Throwable throwable) private void doSignMessage(final Signable signable) { - final DAppFunction dappFunction = new DAppFunction() - { - @Override - public void DAppError(Throwable error, Signable message) - { - showErrorDialog(error.getMessage()); - confirmationDialog.dismiss(); - if (fromDappBrowser) switchToDappBrowser(); - requestId = 0; - lastId = 0; - signData = null; - } - - @Override - public void DAppReturn(byte[] data, Signable message) - { - //store sign - viewModel.recordSign(signable, getSessionId(), () -> { - viewModel.approveRequest(getApplication(), getSessionId(), message.getCallbackId(), Numeric.toHexString(data)); - confirmationDialog.success(); - if (fromDappBrowser) - { - confirmationDialog.forceDismiss(); - switchToDappBrowser(); - } - requestId = 0; - lastId = 0; - signData = null; - updateSignCount(); - }); - } - }; - - signCallback = new SignAuthenticationCallback() - { - @Override - public void gotAuthorisation(boolean gotAuth) - { - viewModel.signMessage( - signable, - dappFunction); - } + confirmationDialog = new ActionSheetSignDialog(this, this, signable); + confirmationDialog.show(); - @Override - public void gotAuthorisationForSigning(boolean gotAuth, Signable messageToSign) - { - if (gotAuth) - { - viewModel.signMessage( - signable, - dappFunction); - } - else - { - cancelAuthentication(); - } - } + viewModel.track(Analytics.Action.WALLET_CONNECT_SIGN_MESSAGE_REQUEST); + } - @Override - public void cancelAuthentication() + @Override + public void signingComplete(SignatureFromKey signature, Signable signable) + { + viewModel.recordSign(signable, getSessionId(), () -> { + viewModel.approveRequest(getApplication(), getSessionId(), signable.getCallbackId(), Numeric.toHexString(signature.signature)); + confirmationDialog.success(); + if (fromDappBrowser) { - requestId = 0; - showErrorDialogCancel(getString(R.string.title_dialog_error), getString(R.string.message_authentication_failed)); - viewModel.rejectRequest(getApplication(), getSessionId(), lastId, getString(R.string.message_authentication_failed)); - confirmationDialog.dismiss(); - if (fromDappBrowser) switchToDappBrowser(); + confirmationDialog.forceDismiss(); + switchToDappBrowser(); } - }; - - confirmationDialog = new ActionSheetDialog(this, this, signCallback, signable); - confirmationDialog.setCanceledOnTouchOutside(false); - confirmationDialog.show(); + requestId = 0; + lastId = 0; + signData = null; + updateSignCount(); + }); + } - viewModel.track(Analytics.Action.WALLET_CONNECT_SIGN_MESSAGE_REQUEST); + @Override + public void signingFailed(Throwable error, Signable message) + { + showErrorDialog(error.getMessage()); + confirmationDialog.dismiss(); + if (fromDappBrowser) switchToDappBrowser(); + requestId = 0; + lastId = 0; + signData = null; } private void onEthSignTransaction(Long id, WCEthereumTransaction transaction, long chainId) diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NonFungibleTokenAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NonFungibleTokenAdapter.java index 129324d9c1..49a9bfe842 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NonFungibleTokenAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NonFungibleTokenAdapter.java @@ -1,6 +1,7 @@ package com.alphawallet.app.ui.widget.adapter; -import android.app.Activity; +import static com.alphawallet.app.service.AssetDefinitionService.ASSET_SUMMARY_VIEW_NAME; + import android.content.Context; import android.util.Pair; import android.view.ViewGroup; @@ -29,10 +30,10 @@ import com.alphawallet.app.ui.widget.holder.BinderViewHolder; import com.alphawallet.app.ui.widget.holder.NFTAssetHolder; import com.alphawallet.app.ui.widget.holder.QuantitySelectorHolder; +import com.alphawallet.app.ui.widget.holder.TextHolder; import com.alphawallet.app.ui.widget.holder.TicketHolder; import com.alphawallet.app.ui.widget.holder.TokenDescriptionHolder; import com.alphawallet.app.ui.widget.holder.TotalBalanceHolder; -import com.alphawallet.app.web3.entity.FunctionCallback; import com.alphawallet.token.entity.TicketRange; import com.bumptech.glide.Glide; @@ -47,8 +48,6 @@ import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static com.alphawallet.app.service.AssetDefinitionService.ASSET_SUMMARY_VIEW_NAME; - /** * Created by James on 9/02/2018. */ @@ -60,29 +59,27 @@ public class NonFungibleTokenAdapter extends TokensAdapter implements NonFungibl protected final OpenSeaService openseaService; private final boolean clickThrough; protected int assetCount; - private FunctionCallback functionCallback; - private final Activity activity; private boolean isGrid; public NonFungibleTokenAdapter(TokensAdapterCallback tokenClickListener, Token t, AssetDefinitionService service, - OpenSeaService opensea, Activity activity) { + OpenSeaService opensea) + { super(tokenClickListener, service); assetCount = 0; token = t; clickThrough = true; openseaService = opensea; setToken(t); - this.activity = activity; } public NonFungibleTokenAdapter(TokensAdapterCallback tokenClickListener, Token t, AssetDefinitionService service, - OpenSeaService opensea, Activity activity, boolean isGrid) { + OpenSeaService opensea, boolean isGrid) + { super(tokenClickListener, service); assetCount = 0; token = t; clickThrough = true; openseaService = opensea; - this.activity = activity; this.isGrid = isGrid; setToken(t); } @@ -96,7 +93,6 @@ public NonFungibleTokenAdapter(TokensAdapterCallback tokenClickListener, Token t clickThrough = false; openseaService = null; setTokenRange(token, tokenSelection); - this.activity = null; } public NonFungibleTokenAdapter(TokensAdapterCallback tokenClickListener, Token t, ArrayList> assetSelection, @@ -108,7 +104,6 @@ public NonFungibleTokenAdapter(TokensAdapterCallback tokenClickListener, Token t clickThrough = false; openseaService = null; setAssetSelection(token, assetSelection); - this.activity = null; } private void setAssetSelection(Token token, List> selection) @@ -118,9 +113,11 @@ private void setAssetSelection(Token token, List> sel @NotNull @Override - public BinderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + public BinderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) + { BinderViewHolder holder = null; - switch (viewType) { + switch (viewType) + { case TicketHolder.VIEW_TYPE: //Ticket holder now deprecated //TODO: remove holder = new TicketHolder(R.layout.item_ticket, parent, token, assetService); holder.setOnTokenClickListener(tokensAdapterCallback); @@ -141,14 +138,19 @@ public BinderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int vie case QuantitySelectorHolder.VIEW_TYPE: holder = new QuantitySelectorHolder(R.layout.item_quantity_selector, parent, assetCount, assetService); break; + default: + holder = new TextHolder(R.layout.item_standard_header, parent); + break; } return holder; } - public int getTicketRangeCount() { + public int getTicketRangeCount() + { int count = 0; - if (currentRange != null) { + if (currentRange != null) + { count = currentRange.tokenIds.size(); } return count; @@ -197,7 +199,7 @@ private void setAssetRange(Token t, List> selection) for (int i = 0; i < selection.size(); i++) { - items.add(new NFTSortedItem(selection.get(i), i+1)); + items.add(new NFTSortedItem(selection.get(i), i + 1)); } items.endBatchedUpdates(); @@ -256,7 +258,7 @@ protected SortedList addSortedItems(List sortedList, { currentRange = new TicketRange(e.id, t.getAddress()); final T item = generateType(currentRange, 10 + i, id); - items.add((SortedItem)item); + items.add((SortedItem) item); currentTime = e.time; } } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ActionSheetCallback.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ActionSheetCallback.java index 869bd2b3a1..00d76ab0e8 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/ActionSheetCallback.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/ActionSheetCallback.java @@ -1,14 +1,14 @@ package com.alphawallet.app.ui.widget.entity; -import android.app.Activity; import android.content.Intent; import androidx.activity.result.ActivityResultLauncher; import com.alphawallet.app.entity.SignAuthenticationCallback; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; import com.alphawallet.app.entity.tokens.Token; -import com.alphawallet.app.walletconnect.entity.WCPeerMeta; import com.alphawallet.app.web3.entity.Web3Transaction; +import com.alphawallet.token.entity.Signable; /** * Created by JB on 27/11/2020. @@ -16,16 +16,40 @@ public interface ActionSheetCallback { void getAuthorisation(SignAuthenticationCallback callback); + void sendTransaction(Web3Transaction tx); + void dismissed(String txHash, long callbackId, boolean actionCompleted); + void notifyConfirm(String mode); + ActivityResultLauncher gasSelectLauncher(); - default void signTransaction(Web3Transaction tx) { } // only WalletConnect uses this so far - default void buttonClick(long callbackId, Token baseToken) { }; //for message only actionsheet + default void signTransaction(Web3Transaction tx) + { + } // only WalletConnect uses this so far + + default void buttonClick(long callbackId, Token baseToken) + { + } + + default void notifyWalletConnectApproval(long chainId) + { + } + + default void denyWalletConnect() + { + } + + default void openChainSelection() + { + } + + default void signingComplete(SignatureFromKey signature, Signable message) + { + } - default void notifyWalletConnectApproval(long chainId) { }; // used by WalletConnectRequest - default void denyWalletConnect() { }; - default void openChainSelection() { }; // used by WalletConnectRequest - default void buttonClick(String action, int Id) { }; // for passing + default void signingFailed(Throwable error, Signable message) + { + } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/ApiV1ViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/ApiV1ViewModel.java index cfe4459856..3cb61df298 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/ApiV1ViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/ApiV1ViewModel.java @@ -1,8 +1,6 @@ package com.alphawallet.app.viewmodel; -import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; - import android.app.Activity; import android.net.Uri; import android.text.TextUtils; @@ -76,7 +74,7 @@ private void onDefaultWallet(final Wallet wallet) public void signMessage(Signable message) { - disposable = createTransactionInteract.sign(defaultWallet.getValue(), message, MAINNET_ID) + disposable = createTransactionInteract.sign(defaultWallet.getValue(), message) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::onSignSuccess, this::onSignError); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java index 1e08968eca..49408c2ffb 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java @@ -20,7 +20,6 @@ import com.alphawallet.app.R; import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.DApp; -import com.alphawallet.app.entity.DAppFunction; import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.QRResult; @@ -48,7 +47,6 @@ import com.alphawallet.app.walletconnect.util.WalletConnectHelper; import com.alphawallet.app.web3.entity.WalletAddEthereumChainObject; import com.alphawallet.app.web3.entity.Web3Transaction; -import com.alphawallet.token.entity.Signable; import org.web3j.utils.Numeric; @@ -61,7 +59,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel; import io.reactivex.Observable; import io.reactivex.Single; -import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import io.realm.Realm; @@ -154,16 +151,6 @@ private void checkBalance(final Wallet wallet) } } - public void signMessage(Signable message, DAppFunction dAppFunction) - { - disposable = createTransactionInteract.sign(defaultWallet.getValue(), message, - getActiveNetwork().chainId) - .subscribeOn(Schedulers.computation()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(sig -> dAppFunction.DAppReturn(sig.signature, message), - error -> dAppFunction.DAppError(error, message)); - } - public void setLastUrl(Context context, String url) { PreferenceManager.getDefaultSharedPreferences(context) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/RedeemSignatureDisplayModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/RedeemSignatureDisplayModel.java index 6653443b1b..f1cb0329d1 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/RedeemSignatureDisplayModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/RedeemSignatureDisplayModel.java @@ -289,7 +289,7 @@ private void onSignMessage(MessagePair pair, Wallet wallet) { //now run this guy through the signed message system if (pair != null) disposable = createTransactionInteract - .sign(wallet, pair, token.tokenInfo.chainId) + .sign(wallet, pair) .subscribe(this::onSignedMessage, this::onError); } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SellDetailViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SellDetailViewModel.java index ac276975bb..d4fbb66ccf 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SellDetailViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SellDetailViewModel.java @@ -1,21 +1,21 @@ package com.alphawallet.app.viewmodel; import android.app.Activity; +import android.content.Context; + import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import android.content.Context; import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.SignAuthenticationCallback; -import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; -import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; import com.alphawallet.app.entity.tokendata.TokenTicker; +import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.interact.CreateTransactionInteract; import com.alphawallet.app.interact.FindDefaultNetworkInteract; -import com.alphawallet.app.interact.GenericWalletInteract; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.router.SellDetailRouter; import com.alphawallet.app.service.AssetDefinitionService; @@ -130,7 +130,7 @@ public void generateUniversalLink(List ticketSendIndexList, String c //sign this link disposable = createTransactionInteract - .sign(defaultWallet().getValue(), tradeBytes, token.tokenInfo.chainId) + .sign(defaultWallet().getValue(), tradeBytes) .subscribe(this::gotSignature, this::onError); } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SignDialogViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SignDialogViewModel.java new file mode 100644 index 0000000000..329a4b9542 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SignDialogViewModel.java @@ -0,0 +1,86 @@ +package com.alphawallet.app.viewmodel; + +import android.app.Activity; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import com.alphawallet.app.entity.SignAuthenticationCallback; +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; +import com.alphawallet.app.interact.GenericWalletInteract; +import com.alphawallet.app.repository.TransactionRepositoryType; +import com.alphawallet.app.service.KeyService; +import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; +import com.alphawallet.token.entity.Signable; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by JB on 22/11/2022. + */ +@HiltViewModel +public class SignDialogViewModel extends BaseViewModel +{ + private final TransactionRepositoryType transactionRepositoryType; + private final KeyService keyService; + private final GenericWalletInteract walletInteract; + private final MutableLiveData completed = new MutableLiveData<>(false); + private Wallet wallet; + + @Inject + public SignDialogViewModel(GenericWalletInteract walletInteract, TransactionRepositoryType transactionRepositoryType, KeyService keyService) + { + this.transactionRepositoryType = transactionRepositoryType; + this.keyService = keyService; + this.walletInteract = walletInteract; + + disposable = walletInteract.find() + .observeOn(Schedulers.io()) + .subscribeOn(Schedulers.io()) + .subscribe(w -> wallet = w, this::onError); + } + + public void getAuthentication(Activity activity, SignAuthenticationCallback sCallback) + { + keyService.getAuthenticationForSignature(wallet, activity, sCallback); + } + + public void signMessage(Signable message, ActionSheetCallback aCallback) + { + disposable = transactionRepositoryType.getSignature(wallet, message) + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(sig -> signComplete(sig, message, aCallback), + error -> signFailed(error, message, aCallback)); + } + + private void signComplete(SignatureFromKey signature, Signable message, ActionSheetCallback aCallback) + { + aCallback.signingComplete(signature, message); + completed.postValue(true); + } + + private void signFailed(Throwable error, Signable message, ActionSheetCallback aCallback) + { + aCallback.signingFailed(error, message); + completed.postValue(false); + } + + public LiveData completed() + { + return completed; + } + + public void setSigningWallet(String account) + { + disposable = walletInteract.findWallet(account) + .observeOn(Schedulers.io()) + .subscribeOn(Schedulers.io()) + .subscribe(w -> wallet = w, this::onError); // TODO: If wallet not found then report error to user rather than trying to sign on default wallet + } +} 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 0f64665473..c1045f22ad 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java @@ -15,7 +15,6 @@ import com.alphawallet.app.R; import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.AnalyticsProperties; -import com.alphawallet.app.entity.DAppFunction; import com.alphawallet.app.entity.Operation; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.Transaction; @@ -55,7 +54,6 @@ import com.alphawallet.token.entity.FunctionDefinition; import com.alphawallet.token.entity.MethodArg; import com.alphawallet.token.entity.SigReturnType; -import com.alphawallet.token.entity.Signable; import com.alphawallet.token.entity.TSAction; import com.alphawallet.token.entity.TicketRange; import com.alphawallet.token.entity.TokenScriptResult; @@ -298,15 +296,6 @@ private void onSigCheckError(Throwable throwable) sig.postValue(failSig); } - public void signMessage(Signable message, DAppFunction dAppFunction, long chainId) - { - disposable = createTransactionInteract.sign(wallet, message, chainId) - .subscribeOn(Schedulers.computation()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(sig -> dAppFunction.DAppReturn(sig.signature, message), - error -> dAppFunction.DAppError(error, message)); - } - public String getTransactionBytes(Token token, BigInteger tokenId, FunctionDefinition def) { return assetDefinitionService.generateTransactionPayload(token, tokenId, def); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java index 9246b608a0..bb9a1e16ce 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/TransferTicketDetailViewModel.java @@ -173,7 +173,7 @@ public void generateUniversalLink(List ticketSendIndexList, String c //sign this link disposable = createTransactionInteract - .sign(defaultWallet().getValue(), tradeBytes, token.tokenInfo.chainId) + .sign(defaultWallet().getValue(), tradeBytes) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::gotSignature, this::onError); @@ -194,7 +194,7 @@ public void generateSpawnLink(List tokenIds, String contractAddress, //sign this link disposable = createTransactionInteract - .sign(defaultWallet().getValue(), tradeBytes, token.tokenInfo.chainId) + .sign(defaultWallet().getValue(), tradeBytes) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::gotSignature, this::onError); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java index 807510662e..d877ff36e3 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java @@ -15,7 +15,6 @@ import androidx.lifecycle.MutableLiveData; import com.alphawallet.app.C; -import com.alphawallet.app.entity.AnalyticsProperties; import com.alphawallet.app.entity.DAppFunction; import com.alphawallet.app.entity.GenericCallback; import com.alphawallet.app.entity.NetworkInfo; @@ -211,7 +210,7 @@ public void getAuthenticationForSignature(Wallet wallet, Activity activity, Sign public void signMessage(Signable message, DAppFunction dAppFunction) { resetSignDialog(); - disposable = createTransactionInteract.sign(defaultWallet.getValue(), message, MAINNET_ID) + disposable = createTransactionInteract.sign(defaultWallet.getValue(), message) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(sig -> dAppFunction.DAppReturn(sig.signature, message), diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/walletconnect/SignMethodDialogViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/walletconnect/SignMethodDialogViewModel.java deleted file mode 100644 index e6e4975340..0000000000 --- a/app/src/main/java/com/alphawallet/app/viewmodel/walletconnect/SignMethodDialogViewModel.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.alphawallet.app.viewmodel.walletconnect; - -import static com.alphawallet.app.entity.cryptokeys.SignatureReturnType.SIGNATURE_GENERATED; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.widget.Toast; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; - -import com.alphawallet.app.R; -import com.alphawallet.app.entity.Operation; -import com.alphawallet.app.entity.SignAuthenticationCallback; -import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; -import com.alphawallet.app.interact.FetchWalletsInteract; -import com.alphawallet.app.repository.TransactionRepositoryType; -import com.alphawallet.app.service.KeyService; -import com.alphawallet.app.viewmodel.BaseViewModel; -import com.alphawallet.app.walletconnect.AWWalletConnectClient; -import com.alphawallet.app.walletconnect.util.WalletConnectHelper; -import com.alphawallet.token.entity.Signable; -import com.alphawallet.token.tools.Numeric; -import com.walletconnect.sign.client.Sign; - -import java.util.Objects; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; - -import dagger.hilt.android.lifecycle.HiltViewModel; -import io.reactivex.Single; -import timber.log.Timber; - -@HiltViewModel -public class SignMethodDialogViewModel extends BaseViewModel -{ - private final AWWalletConnectClient awWalletConnectClient; - private final FetchWalletsInteract fetchWalletsInteract; - private final TransactionRepositoryType transactionRepositoryType; - private final KeyService keyService; - private final MutableLiveData completed = new MutableLiveData<>(false); - - @Inject - public SignMethodDialogViewModel(AWWalletConnectClient awWalletConnectClient, FetchWalletsInteract fetchWalletsInteract, TransactionRepositoryType transactionRepositoryType, KeyService keyService) - { - this.awWalletConnectClient = awWalletConnectClient; - this.fetchWalletsInteract = fetchWalletsInteract; - this.transactionRepositoryType = transactionRepositoryType; - this.keyService = keyService; - } - - public void sign(Activity activity, Wallet wallet, Sign.Model.SessionRequest sessionRequest, final Signable signable) - { - keyService.getAuthenticationForSignature(wallet, activity, new SignAuthenticationCallback() - { - @SuppressLint("CheckResult") - @Override - public void gotAuthorisation(boolean gotAuth) - { - if (gotAuth) - { - long chainId = WalletConnectHelper.getChainId(Objects.requireNonNull(sessionRequest.getChainId())); - Single signature = transactionRepositoryType.getSignature(wallet, signable, chainId); - signature - .delay(5, TimeUnit.SECONDS) // The WC connection shutdown when show biometric, when back to foreground, it will open new connection, so need delay to wait the connection opened - .subscribe(signatureFromKey -> onSuccess(signatureFromKey, sessionRequest), SignMethodDialogViewModel.this::onError); - } - else - { - Toast.makeText(activity, activity.getString(R.string.error_while_signing_transaction), Toast.LENGTH_SHORT).show(); - } - } - - @Override - public void cancelAuthentication() - { - Timber.i("cancelAuthentication"); - } - }); - } - - public void onError(Throwable throwable) - { - Timber.e(throwable); - } - - private void onSuccess(SignatureFromKey signatureFromKey, Sign.Model.SessionRequest sessionRequest) - { - if (signatureFromKey.sigType == SIGNATURE_GENERATED) - { - String result = Numeric.toHexString(signatureFromKey.signature); - awWalletConnectClient.approve(sessionRequest, result); - } - else - { - Timber.i("sign fail: %s", signatureFromKey.failMessage); - awWalletConnectClient.reject(sessionRequest, signatureFromKey.failMessage); - } - completed.postValue(true); - } - - public void completeAuthentication(Operation taskCode) - { - keyService.completeAuthentication(taskCode); - } - - public void failedAuthentication(Operation taskCode) - { - keyService.failedAuthentication(taskCode); - } - - public LiveData completed() - { - return completed; - } - - public void reject(Sign.Model.SessionRequest sessionRequest) - { - awWalletConnectClient.reject(sessionRequest); - } - - public Single findWallet(String walletAddress) - { - return fetchWalletsInteract.getWallet(walletAddress); - } -} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java b/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java index 06e90254a8..5bcd8a81c4 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java @@ -1,25 +1,23 @@ package com.alphawallet.app.walletconnect; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static com.alphawallet.app.entity.cryptokeys.SignatureReturnType.SIGNATURE_GENERATED; -import android.app.Activity; import android.app.Application; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Handler; import android.os.Looper; +import android.util.LongSparseArray; import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; import androidx.lifecycle.MutableLiveData; -import com.alphawallet.app.App; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.C; import com.alphawallet.app.R; -import com.alphawallet.app.entity.AuthenticationCallback; +import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; import com.alphawallet.app.entity.walletconnect.NamespaceParser; import com.alphawallet.app.entity.walletconnect.WalletConnectSessionItem; import com.alphawallet.app.entity.walletconnect.WalletConnectV2SessionItem; @@ -27,9 +25,11 @@ import com.alphawallet.app.repository.KeyProvider; import com.alphawallet.app.repository.KeyProviderFactory; import com.alphawallet.app.service.WalletConnectV2Service; +import com.alphawallet.app.ui.HomeActivity; import com.alphawallet.app.ui.WalletConnectV2Activity; -import com.alphawallet.app.viewmodel.walletconnect.SignMethodDialogViewModel; import com.alphawallet.app.walletconnect.util.WCMethodChecker; +import com.alphawallet.token.entity.Signable; +import com.alphawallet.token.tools.Numeric; import com.walletconnect.android.Core; import com.walletconnect.android.CoreClient; import com.walletconnect.android.relay.ConnectionType; @@ -51,19 +51,21 @@ public class AWWalletConnectClient implements SignInterface.WalletDelegate { private static final String TAG = AWWalletConnectClient.class.getName(); - public static AuthenticationCallback authCallback; private final WalletConnectInteract walletConnectInteract; public static Sign.Model.SessionProposal sessionProposal; - public static SignMethodDialogViewModel viewModel; private final Context context; private final MutableLiveData> sessionItemMutableLiveData = new MutableLiveData<>(Collections.emptyList()); private final KeyProvider keyProvider = KeyProviderFactory.get(); + private final LongSparseArray requestHandlers = new LongSparseArray<>(); + private HomeActivity activity; + private boolean hasConnection; public AWWalletConnectClient(Context context, WalletConnectInteract walletConnectInteract) { this.context = context; this.walletConnectInteract = walletConnectInteract; + hasConnection = false; } public void onSessionDelete(@NonNull Sign.Model.DeletedSession deletedSession) @@ -102,7 +104,6 @@ private boolean validChainId(List chains) return true; } - @RequiresApi(api = Build.VERSION_CODES.O) public void onSessionRequest(@NonNull Sign.Model.SessionRequest sessionRequest) { String method = sessionRequest.getRequest().getMethod(); @@ -115,9 +116,9 @@ public void onSessionRequest(@NonNull Sign.Model.SessionRequest sessionRequest) Sign.Model.Session settledSession = getSession(sessionRequest.getTopic()); - Activity topActivity = App.getInstance().getTopActivity(); - WalletConnectV2SessionRequestHandler handler = new WalletConnectV2SessionRequestHandler(sessionRequest, settledSession, topActivity, this); - handler.handle(method); + WalletConnectV2SessionRequestHandler handler = new WalletConnectV2SessionRequestHandler(sessionRequest, settledSession, activity, this); + handler.handle(method, activity); + requestHandlers.append(sessionRequest.getRequest().getId(), handler); } private Sign.Model.Session getSession(String topic) @@ -134,7 +135,6 @@ private Sign.Model.Session getSession(String topic) Timber.tag(TAG).e(e); } - for (Sign.Model.Session session : listOfSettledSessions) { if (session.getTopic().equals(topic)) @@ -285,6 +285,11 @@ private Unit onSessionRequestRejectError(Sign.Model.Error error) return null; } + public void init(HomeActivity homeActivity) + { + activity = homeActivity; + } + public void init(Application application) { Core.Model.AppMetaData appMetaData = getAppMetaData(application); @@ -327,6 +332,7 @@ public void shutdown() public void onConnectionStateChange(@NonNull Sign.Model.ConnectionState connectionState) { Timber.tag(TAG).i("onConnectionStateChange"); + hasConnection = connectionState.isAvailable(); } public void onSessionSettleResponse(@NonNull Sign.Model.SettledSessionResponse settledSessionResponse) @@ -344,6 +350,57 @@ public void onError(Sign.Model.Error error) Timber.e(error.getThrowable()); } + public void signComplete(SignatureFromKey signatureFromKey, Signable signable) + { + if (hasConnection) + { + onSign(signatureFromKey, getHandler(signable.getCallbackId())); //have valid connection, can send response + } + else + { + new Handler().postDelayed(() -> signComplete(signatureFromKey, signable), 1000); //Delay by 1 second and check again + } + } + + public void signFail(String error, Signable signable) + { + final WalletConnectV2SessionRequestHandler requestHandler = getHandler(signable.getCallbackId()); + + Timber.i("sign fail: %s", error); + reject(requestHandler.getSessionRequest(), error); + } + + //Sign Dialog (and later tx dialog) was dismissed + public void dismissed(long callbackId) + { + final WalletConnectV2SessionRequestHandler requestHandler = getHandler(callbackId); + if (requestHandler != null) + { + reject(requestHandler.getSessionRequest(), activity.getString(R.string.message_reject_request)); + } + } + + private WalletConnectV2SessionRequestHandler getHandler(long callbackId) + { + WalletConnectV2SessionRequestHandler handler = requestHandlers.get(callbackId); + requestHandlers.remove(callbackId); + return handler; + } + + private void onSign(SignatureFromKey signatureFromKey, WalletConnectV2SessionRequestHandler requestHandler) + { + if (signatureFromKey.sigType == SIGNATURE_GENERATED) + { + String result = Numeric.toHexString(signatureFromKey.signature); + approve(requestHandler.getSessionRequest(), result); + } + else + { + Timber.i("sign fail: %s", signatureFromKey.failMessage); + reject(requestHandler.getSessionRequest(), signatureFromKey.failMessage); + } + } + public interface WalletConnectV2Callback { default void onSessionProposalApproved() diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java b/app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java index a3c4bc3f9f..bbd0613211 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java @@ -1,18 +1,21 @@ package com.alphawallet.app.walletconnect; import android.app.Activity; -import android.app.Dialog; -import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.FragmentManager; +import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; import com.alphawallet.app.walletconnect.entity.BaseRequest; -import com.alphawallet.app.walletconnect.entity.SignPersonalMessageRequest; -import com.alphawallet.app.walletconnect.entity.SignTypedDataRequest; -import com.alphawallet.app.widget.SignMethodDialog; +import com.alphawallet.app.walletconnect.entity.EthSignRequest; +import com.alphawallet.app.widget.ActionSheet; +import com.alphawallet.app.widget.ActionSheetSignDialog; +import com.alphawallet.token.entity.Signable; import com.walletconnect.sign.client.Sign; +import java.util.List; +import java.util.Objects; + import timber.log.Timber; public class WalletConnectV2SessionRequestHandler @@ -30,14 +33,19 @@ public WalletConnectV2SessionRequestHandler(Sign.Model.SessionRequest sessionReq this.client = client; } - public void handle(String method) + public void handle(String method, ActionSheetCallback aCallback) { activity.runOnUiThread(() -> { - showDialog(method); + showDialog(method, aCallback); }); } - private void showDialog(String method) + public Sign.Model.SessionRequest getSessionRequest() + { + return sessionRequest; + } + + private void showDialog(String method, ActionSheetCallback aCallback) { boolean isSignTransaction = "eth_signTransaction".equals(method); boolean isSendTransaction = "eth_sendTransaction".equals(method); @@ -49,45 +57,22 @@ private void showDialog(String method) return; } - if ("personal_sign".equals(method)) + BaseRequest signRequest = EthSignRequest.getSignRequest(sessionRequest); + if (signRequest != null) { - personalSign().show(); - return; + Signable signable = signRequest.getSignable(sessionRequest.getRequest().getId(), settledSession.getMetaData().getUrl()); + ActionSheet actionSheet = new ActionSheetSignDialog(activity, aCallback, signable); + actionSheet.setSigningWallet(signRequest.getWalletAddress()); + List icons = Objects.requireNonNull(settledSession.getMetaData()).getIcons(); + if (!icons.isEmpty()) + { + actionSheet.setIcon(icons.get(0)); + } + actionSheet.show(); } - - if ("eth_sign".equals(method)) + else { - ethSign().show(); - return; - } - - if ("eth_signTypedData".equals(method)) - { - ethSignTypedData().show(); - return; + Timber.e("Method %s not supported.", method); } - - Timber.e("Method %s not support.", method); - } - - private Dialog ethSign() - { - BaseRequest request = new SignRequest(sessionRequest.getRequest().getParams()); - return new SignMethodDialog(activity, sessionRequest, request, settledSession.getMetaData()); } - - @NonNull - private SignMethodDialog ethSignTypedData() - { - BaseRequest request = new SignTypedDataRequest(sessionRequest.getRequest().getParams()); - return new SignMethodDialog(activity, sessionRequest, request, settledSession.getMetaData()); - } - - @NonNull - private SignMethodDialog personalSign() - { - BaseRequest request = new SignPersonalMessageRequest(sessionRequest.getRequest().getParams()); - return new SignMethodDialog(activity, sessionRequest, request, settledSession.getMetaData()); - } - } diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/entity/BaseRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/BaseRequest.java index 9df6a1d91e..a4acdb9142 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/entity/BaseRequest.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/BaseRequest.java @@ -50,5 +50,10 @@ protected String getMessage() public abstract Signable getSignable(); + public Signable getSignable(long callbackId, String origin) + { + return null; + } + public abstract String getWalletAddress(); } diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/entity/EthSignRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/EthSignRequest.java new file mode 100644 index 0000000000..904b2c420a --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/EthSignRequest.java @@ -0,0 +1,33 @@ +package com.alphawallet.app.walletconnect.entity; + +import com.walletconnect.sign.client.Sign; + +/** + * Created by JB on 21/11/2022. + */ +public abstract class EthSignRequest +{ + public static BaseRequest getSignRequest(Sign.Model.SessionRequest sessionRequest) + { + BaseRequest signRequest = null; + + switch (sessionRequest.getRequest().getMethod()) + { + case "eth_sign": + // see https://docs.walletconnect.org/json-rpc-api-methods/ethereum + // WalletConnect shouldn't provide access to deprecated eth_sign, as it can be used to scam people + signRequest = new SignRequest(sessionRequest.getRequest().getParams()); + break; + case "personal_sign": + signRequest = new SignPersonalMessageRequest(sessionRequest.getRequest().getParams()); + break; + case "eth_signTypedData": + signRequest = new SignTypedDataRequest(sessionRequest.getRequest().getParams()); + break; + default: + break; + } + + return signRequest; + } +} diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequest.java index f8dc3c7f69..e70f1af78e 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequest.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignPersonalMessageRequest.java @@ -17,6 +17,12 @@ public Signable getSignable() return new EthereumMessage(getMessage(), "", 0, SignMessageType.SIGN_PERSONAL_MESSAGE); } + @Override + public Signable getSignable(long callbackId, String origin) + { + return new EthereumMessage(getMessage(), origin, callbackId, SignMessageType.SIGN_PERSONAL_MESSAGE); + } + @Override public String getWalletAddress() { diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/SignRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignRequest.java similarity index 69% rename from app/src/main/java/com/alphawallet/app/walletconnect/SignRequest.java rename to app/src/main/java/com/alphawallet/app/walletconnect/entity/SignRequest.java index a5dcaf920c..35edc28261 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/SignRequest.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignRequest.java @@ -1,7 +1,5 @@ -package com.alphawallet.app.walletconnect; +package com.alphawallet.app.walletconnect.entity; -import com.alphawallet.app.walletconnect.entity.BaseRequest; -import com.alphawallet.app.walletconnect.entity.WCEthereumSignMessage; import com.alphawallet.token.entity.EthereumMessage; import com.alphawallet.token.entity.SignMessageType; import com.alphawallet.token.entity.Signable; @@ -19,6 +17,12 @@ public Signable getSignable() return new EthereumMessage(getMessage(), "", 0, SignMessageType.SIGN_MESSAGE); } + @Override + public Signable getSignable(long callbackId, String origin) + { + return new EthereumMessage(getMessage(), origin, callbackId, SignMessageType.SIGN_MESSAGE); + } + @Override public String getWalletAddress() { diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequest.java index 54c55ff1bd..215a3ba074 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequest.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/SignTypedDataRequest.java @@ -20,4 +20,10 @@ public Signable getSignable() { return new EthereumTypedMessage(getMessage(), "", 0, new CryptoFunctions()); } + + @Override + public Signable getSignable(long callbackId, String origin) + { + return new EthereumTypedMessage(getMessage(), origin, callbackId, new CryptoFunctions()); + } } diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/util/WCMethodChecker.java b/app/src/main/java/com/alphawallet/app/walletconnect/util/WCMethodChecker.java index bb0ec1f85e..329e8ef504 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/util/WCMethodChecker.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/util/WCMethodChecker.java @@ -1,6 +1,5 @@ package com.alphawallet.app.walletconnect.util; -import com.alphawallet.app.entity.TokensMapping; import com.alphawallet.app.walletconnect.entity.WCMethod; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/util/WalletConnectHelper.java b/app/src/main/java/com/alphawallet/app/walletconnect/util/WalletConnectHelper.java index 5c3fd6f8d8..ec33eb0949 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/util/WalletConnectHelper.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/util/WalletConnectHelper.java @@ -1,6 +1,6 @@ package com.alphawallet.app.walletconnect.util; -public class WalletConnectHelper +public abstract class WalletConnectHelper { public static boolean isWalletConnectV1(String text) { 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 f48d1f2192..f9e8bb95c0 100644 --- a/app/src/main/java/com/alphawallet/app/web3/Web3TokenView.java +++ b/app/src/main/java/com/alphawallet/app/web3/Web3TokenView.java @@ -2,21 +2,16 @@ import static androidx.webkit.WebSettingsCompat.FORCE_DARK_OFF; import static androidx.webkit.WebSettingsCompat.FORCE_DARK_ON; +import static com.alphawallet.app.service.AssetDefinitionService.ASSET_DETAIL_VIEW_NAME; +import static com.alphawallet.app.service.AssetDefinitionService.ASSET_SUMMARY_VIEW_NAME; +import static com.alphawallet.token.tools.TokenDefinition.TOKENSCRIPT_ERROR; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Configuration; -import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.webkit.WebSettingsCompat; -import androidx.webkit.WebViewFeature; - import android.text.TextUtils; -import android.text.format.DateUtils; import android.util.AttributeSet; import android.util.Base64; -import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.webkit.ConsoleMessage; @@ -30,6 +25,11 @@ import android.widget.LinearLayout; import android.widget.RelativeLayout; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.webkit.WebSettingsCompat; +import androidx.webkit.WebViewFeature; + import com.alphawallet.app.BuildConfig; import com.alphawallet.app.R; import com.alphawallet.app.entity.tokens.Token; @@ -51,7 +51,6 @@ import org.jetbrains.annotations.NotNull; -import java.io.IOException; import java.io.LineNumberReader; import java.io.StringReader; import java.math.BigInteger; @@ -64,10 +63,6 @@ import io.realm.RealmResults; import timber.log.Timber; -import static com.alphawallet.app.service.AssetDefinitionService.ASSET_DETAIL_VIEW_NAME; -import static com.alphawallet.app.service.AssetDefinitionService.ASSET_SUMMARY_VIEW_NAME; -import static com.alphawallet.token.tools.TokenDefinition.TOKENSCRIPT_ERROR; - /** * Created by James on 3/04/2019. * Stormbird in Singapore diff --git a/app/src/main/java/com/alphawallet/app/web3/entity/FunctionCallback.java b/app/src/main/java/com/alphawallet/app/web3/entity/FunctionCallback.java index 203a8853c0..97e5ad4ebb 100644 --- a/app/src/main/java/com/alphawallet/app/web3/entity/FunctionCallback.java +++ b/app/src/main/java/com/alphawallet/app/web3/entity/FunctionCallback.java @@ -1,15 +1,11 @@ package com.alphawallet.app.web3.entity; -import com.alphawallet.app.entity.DAppFunction; -import com.alphawallet.token.entity.Signable; - /** * Created by James on 6/04/2019. * Stormbird in Singapore */ public interface FunctionCallback { - void signMessage(Signable sign, DAppFunction dAppFunction); void functionSuccess(); void functionFailed(); } diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheet.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheet.java new file mode 100644 index 0000000000..11a3d05e83 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/widget/ActionSheet.java @@ -0,0 +1,53 @@ +package com.alphawallet.app.widget; + +import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED; + +import android.content.Context; +import android.widget.FrameLayout; + +import androidx.activity.result.ActivityResult; +import androidx.annotation.NonNull; + +import com.alphawallet.app.entity.ActionSheetInterface; +import com.alphawallet.app.web3.entity.Web3Transaction; +import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.google.android.material.bottomsheet.BottomSheetDialog; + +import java.math.BigInteger; + +/** + * Created by JB on 20/11/2022. + */ +public abstract class ActionSheet extends BottomSheetDialog implements ActionSheetInterface +{ + public ActionSheet(@NonNull Context context) + { + super(context); + } + + public void forceDismiss() + { + setOnDismissListener(v -> { + // Do nothing + }); + dismiss(); + } + + public void fullExpand() + { + FrameLayout bottomSheet = findViewById(com.google.android.material.R.id.design_bottom_sheet); + if (bottomSheet != null) BottomSheetBehavior.from(bottomSheet).setState(STATE_EXPANDED); + } + + public void lockDragging(boolean lock) + { + getBehavior().setDraggable(!lock); + + //ensure view fully expanded when locking scroll. Otherwise we may not be able to see our expanded view + if (lock) + { + FrameLayout bottomSheet = findViewById(com.google.android.material.R.id.design_bottom_sheet); + if (bottomSheet != null) BottomSheetBehavior.from(bottomSheet).setState(STATE_EXPANDED); + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java index d7a4d9e7da..c5769d1c1c 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java @@ -7,8 +7,6 @@ import android.content.SharedPreferences; import android.text.TextUtils; import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; import androidx.activity.result.ActivityResult; import androidx.annotation.NonNull; @@ -38,9 +36,7 @@ import com.alphawallet.app.util.Utils; import com.alphawallet.app.walletconnect.entity.WCPeerMeta; import com.alphawallet.app.web3.entity.Web3Transaction; -import com.alphawallet.token.entity.Signable; import com.google.android.material.bottomsheet.BottomSheetBehavior; -import com.google.android.material.bottomsheet.BottomSheetDialog; import java.math.BigDecimal; import java.math.BigInteger; @@ -53,7 +49,7 @@ /** * Created by JB on 17/11/2020. */ -public class ActionSheetDialog extends BottomSheetDialog implements StandardFunctionInterface, ActionSheetInterface +public class ActionSheetDialog extends ActionSheet implements StandardFunctionInterface, ActionSheetInterface { private final BottomSheetToolbarView toolbar; private final GasWidget2 gasWidget; @@ -173,86 +169,6 @@ else if (activity instanceof WalletConnectActivity) setupCancelListeners(); } - public ActionSheetDialog(@NonNull Activity activity, ActionSheetCallback aCallback, SignAuthenticationCallback sCallback, Signable message) - { - super(activity); - setContentView(R.layout.dialog_action_sheet_sign); - - toolbar = findViewById(R.id.bottom_sheet_toolbar); - gasWidget = findViewById(R.id.gas_widgetx); - gasWidgetLegacy = findViewById(R.id.gas_widget_legacy); - balanceDisplay = findViewById(R.id.balance); - networkDisplay = findViewById(R.id.network_display_widget); - confirmationWidget = findViewById(R.id.confirmation_view); - addressDetail = findViewById(R.id.requester); - amountDisplay = findViewById(R.id.amount_display); - assetDetailView = findViewById(R.id.asset_detail); - functionBar = findViewById(R.id.layoutButtons); - detailWidget = null; - mode = ActionSheetMode.SIGN_MESSAGE; - callbackId = message.getCallbackId(); - this.activity = activity; - - actionSheetCallback = aCallback; - signCallback = sCallback; - - token = null; - tokensService = null; - candidateTransaction = null; - actionCompleted = false; - walletConnectRequestWidget = null; - gasWidgetInterface = null; - - addressDetail.setupRequester(message.getOrigin()); - SignDataWidget signWidget = findViewById(R.id.sign_widget); - signWidget.setupSignData(message); - signWidget.setLockCallback(this); - - toolbar.setTitle(Utils.getSigningTitle(message)); - - functionBar.setupFunctions(this, new ArrayList<>(Collections.singletonList(R.string.action_confirm))); - functionBar.revealButtons(); - setupCancelListeners(); - } - - public ActionSheetDialog(@NonNull Activity activity, ActionSheetCallback aCallback, int titleId, String message, int buttonTextId, - long cId, Token baseToken) - { - super(activity); - setContentView(R.layout.dialog_action_sheet_message); - - toolbar = findViewById(R.id.bottom_sheet_toolbar); - TextView messageView = findViewById(R.id.text_message); - functionBar = findViewById(R.id.layoutButtons); - this.activity = activity; - - actionSheetCallback = aCallback; - mode = ActionSheetMode.MESSAGE; - - toolbar.setTitle(titleId); - messageView.setText(message); - - gasWidget = null; - balanceDisplay = null; - networkDisplay = null; - confirmationWidget = null; - addressDetail = null; - amountDisplay = null; - assetDetailView = null; - detailWidget = null; - callbackId = cId; - token = baseToken; - tokensService = null; - candidateTransaction = null; - walletConnectRequestWidget = null; - gasWidgetLegacy = null; - gasWidgetInterface = null; - - functionBar.setupFunctions(this, new ArrayList<>(Collections.singletonList(buttonTextId))); - functionBar.revealButtons(); - setupCancelListeners(); - } - // wallet connect request public ActionSheetDialog(Activity activity, WCPeerMeta wcPeerMeta, long chainIdOverride, String iconUrl, ActionSheetCallback actionSheetCallback) { @@ -337,30 +253,6 @@ public ActionSheetDialog(Activity activity, ActionSheetCallback aCallback, int t setupCancelListeners(); } - private GasWidgetInterface setupGasWidget() - { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); - boolean canUse1559Transactions = prefs.getBoolean(SharedPreferenceRepository.EXPERIMENTAL_1559_TX, false); - - use1559Transactions = canUse1559Transactions && has1559Gas() //1559 Transactions toggled on in settings and this chain supports 1559 - && !(token.isEthereum() && candidateTransaction.leafPosition == -2) //User not sweeping wallet (if so we need to use legacy tx) - && !tokensService.hasLockedGas(token.tokenInfo.chainId) //Service has locked gas, can only use legacy (eg Optimism). - && !candidateTransaction.isConstructor(); //Currently cannot use EIP1559 for constructors due to gas calculation issues - - if (use1559Transactions) - { - gasWidget.setupWidget(tokensService, token, candidateTransaction, actionSheetCallback.gasSelectLauncher()); - return gasWidget; - } - else - { - gasWidget.setVisibility(View.GONE); - gasWidgetLegacy.setVisibility(View.VISIBLE); - gasWidgetLegacy.setupWidget(tokensService, token, candidateTransaction, this, actionSheetCallback.gasSelectLauncher()); - return gasWidgetLegacy; - } - } - public ActionSheetDialog(Activity activity, ActionSheetMode mode) { super(activity); @@ -390,6 +282,30 @@ public ActionSheetDialog(Activity activity, ActionSheetMode mode) callbackId = 0; } + private GasWidgetInterface setupGasWidget() + { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + boolean canUse1559Transactions = prefs.getBoolean(SharedPreferenceRepository.EXPERIMENTAL_1559_TX, false); + + use1559Transactions = canUse1559Transactions && has1559Gas() //1559 Transactions toggled on in settings and this chain supports 1559 + && !(token.isEthereum() && candidateTransaction.leafPosition == -2) //User not sweeping wallet (if so we need to use legacy tx) + && !tokensService.hasLockedGas(token.tokenInfo.chainId) //Service has locked gas, can only use legacy (eg Optimism). + && !candidateTransaction.isConstructor(); //Currently cannot use EIP1559 for constructors due to gas calculation issues + + if (use1559Transactions) + { + gasWidget.setupWidget(tokensService, token, candidateTransaction, actionSheetCallback.gasSelectLauncher()); + return gasWidget; + } + else + { + gasWidget.setVisibility(View.GONE); + gasWidgetLegacy.setVisibility(View.VISIBLE); + gasWidgetLegacy.setupWidget(tokensService, token, candidateTransaction, this, actionSheetCallback.gasSelectLauncher()); + return gasWidgetLegacy; + } + } + public void setSignOnly() { //sign only, and return signature to process @@ -439,6 +355,7 @@ private void setupTransactionDetails() } } + @Override public void setCurrentGasIndex(ActivityResult result) { if (result == null || result.getData() == null) return; @@ -495,9 +412,6 @@ public void handleClick(String action, int id) sendTransaction(); } break; - case SIGN_MESSAGE: - signMessage(); - break; case SIGN_TRANSACTION: signTransaction(); break; @@ -543,44 +457,6 @@ private String getERC721TokenId() return token.getTransferValueRaw(transaction.transactionInput).toString(); } - private void signMessage() - { - //get authentication - functionBar.setVisibility(View.GONE); - - //authentication screen - SignAuthenticationCallback localSignCallback = new SignAuthenticationCallback() - { - final SignDataWidget signWidget = findViewById(R.id.sign_widget); - - @Override - public void gotAuthorisation(boolean gotAuth) - { - actionCompleted = true; - //display success and hand back to calling function - if (gotAuth) - { - confirmationWidget.startProgressCycle(1); - signCallback.gotAuthorisationForSigning(gotAuth, signWidget.getSignable()); - actionSheetCallback.notifyConfirm(mode.getValue()); - } - else - { - cancelAuthentication(); - } - } - - @Override - public void cancelAuthentication() - { - confirmationWidget.hide(); - signCallback.gotAuthorisationForSigning(false, signWidget.getSignable()); - } - }; - - actionSheetCallback.getAuthorisation(localSignCallback); - } - /** * Popup a dialogbox to ask user if they really want to try to send this transaction, * as we calculate it will fail due to insufficient gas. User knows best though. @@ -799,26 +675,6 @@ public void cancelAuthentication() actionSheetCallback.getAuthorisation(signCallback); } - @Override - public void lockDragging(boolean lock) - { - getBehavior().setDraggable(!lock); - - //ensure view fully expanded when locking scroll. Otherwise we may not be able to see our expanded view - if (lock) - { - FrameLayout bottomSheet = findViewById(com.google.android.material.R.id.design_bottom_sheet); - if (bottomSheet != null) BottomSheetBehavior.from(bottomSheet).setState(STATE_EXPANDED); - } - } - - @Override - public void fullExpand() - { - FrameLayout bottomSheet = findViewById(com.google.android.material.R.id.design_bottom_sheet); - if (bottomSheet != null) BottomSheetBehavior.from(bottomSheet).setState(STATE_EXPANDED); - } - //Takes gas estimate from calling activity (eg WalletConnectActivity) and updates dialog public void setGasEstimate(BigInteger estimate) { @@ -843,14 +699,6 @@ public void success() } } - public void forceDismiss() - { - setOnDismissListener(v -> { - // Do nothing - }); - dismiss(); - } - public void waitForEstimate() { functionBar.setPrimaryButtonWaiting(); @@ -887,8 +735,3 @@ private boolean has1559Gas() return false; } } - -interface OnGasSelectedCallback -{ - void onSelected(); -} diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheetSignDialog.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheetSignDialog.java new file mode 100644 index 0000000000..4af5bc6838 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/widget/ActionSheetSignDialog.java @@ -0,0 +1,157 @@ +package com.alphawallet.app.widget; + +import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED; + +import android.app.Activity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.ViewModelProvider; +import androidx.lifecycle.ViewModelStoreOwner; + +import com.alphawallet.app.R; +import com.alphawallet.app.entity.SignAuthenticationCallback; +import com.alphawallet.app.entity.StandardFunctionInterface; +import com.alphawallet.app.entity.analytics.ActionSheetMode; +import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; +import com.alphawallet.app.util.Utils; +import com.alphawallet.app.viewmodel.SignDialogViewModel; +import com.alphawallet.token.entity.Signable; +import com.bumptech.glide.Glide; +import com.google.android.material.bottomsheet.BottomSheetBehavior; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * Created by JB on 20/11/2022. + */ +public class ActionSheetSignDialog extends ActionSheet implements StandardFunctionInterface, SignAuthenticationCallback +{ + private final SignDialogViewModel viewModel; + private final BottomSheetToolbarView toolbar; + private final ConfirmationWidget confirmationWidget; + private final AddressDetailView addressDetail; + private final FunctionButtonBar functionBar; + private final ActionSheetCallback actionSheetCallback; + private final Activity activity; + private final long callbackId; + private boolean actionCompleted; + + public ActionSheetSignDialog(@NonNull Activity callingActivity, ActionSheetCallback aCallback, Signable message) + { + super(callingActivity); + View view = LayoutInflater.from(callingActivity).inflate(R.layout.dialog_action_sheet_sign, null); + setContentView(view); + + toolbar = findViewById(R.id.bottom_sheet_toolbar); + confirmationWidget = findViewById(R.id.confirmation_view); + addressDetail = findViewById(R.id.requester); + functionBar = findViewById(R.id.layoutButtons); + callbackId = message.getCallbackId(); + activity = callingActivity; + + actionSheetCallback = aCallback; + + addressDetail.setupRequester(message.getOrigin()); + SignDataWidget signWidget = findViewById(R.id.sign_widget); + signWidget.setupSignData(message); + + toolbar.setTitle(Utils.getSigningTitle(message)); + + functionBar.setupFunctions(this, new ArrayList<>(Collections.singletonList(R.string.action_confirm))); + functionBar.revealButtons(); + setupCancelListeners(); + actionCompleted = false; + + //ensure view fully expanded when locking scroll. Otherwise we may not be able to see our expanded view + fullExpand(); + + viewModel = new ViewModelProvider((ViewModelStoreOwner) activity).get(SignDialogViewModel.class); + viewModel.completed().observe((LifecycleOwner) activity, this::signComplete); + setCanceledOnTouchOutside(false); + } + + @Override + public void setIcon(String icon) + { + ImageView iconView = findViewById(R.id.logo); + Glide.with(activity) + .load(icon) + .circleCrop() + .into(iconView); + } + + @Override + public void handleClick(String action, int id) + { + //get authentication + functionBar.setVisibility(View.GONE); + viewModel.getAuthentication(activity, this); + } + + // Set for locked signing account, which WalletConnect v2 requires + @Override + public void setSigningWallet(String account) + { + viewModel.setSigningWallet(account); + } + + public void success() + { + if (isShowing() && confirmationWidget != null && confirmationWidget.isShown()) + { + confirmationWidget.completeProgressMessage(".", this::dismiss); + } + } + + private void setupCancelListeners() + { + toolbar.setCloseListener(v -> dismiss()); + + setOnDismissListener(v -> { + actionSheetCallback.dismissed("", callbackId, actionCompleted); + }); + } + + @Override + public void gotAuthorisation(boolean gotAuth) + { + final SignDataWidget signWidget = findViewById(R.id.sign_widget); + if (gotAuth) + { + //start animation + confirmationWidget.startProgressCycle(1); + actionSheetCallback.notifyConfirm(ActionSheetMode.SIGN_MESSAGE.getValue()); + viewModel.signMessage(signWidget.getSignable(), actionSheetCallback); + } + else + { + Toast.makeText(activity, activity.getString(R.string.error_while_signing_transaction), Toast.LENGTH_SHORT).show(); + cancelAuthentication(); + } + } + + @Override + public void cancelAuthentication() + { + dismiss(); + } + + private void signComplete(Boolean success) + { + if (success) + { + actionCompleted = true; + success(); + } + else + { + dismiss(); + } + } +} diff --git a/app/src/main/java/com/alphawallet/app/widget/ConfirmationWidget.java b/app/src/main/java/com/alphawallet/app/widget/ConfirmationWidget.java index 38804d0f49..f9ef088699 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ConfirmationWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/ConfirmationWidget.java @@ -3,6 +3,7 @@ import android.animation.Animator; import android.content.Context; import android.os.Handler; +import android.os.Looper; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; @@ -27,7 +28,7 @@ public class ConfirmationWidget extends RelativeLayout private final TextView hashText; private final RelativeLayout progressLayout; private RealmResults realmTransactionUpdates; - private final Handler handler = new Handler(); + private final Handler handler = new Handler(Looper.getMainLooper()); public ConfirmationWidget(Context context, AttributeSet attrs) { @@ -56,9 +57,11 @@ public void startAnimate(long expectedTransactionTime, Realm transactionRealm, S public void startProgressCycle(int cycleTime) { - progress.setVisibility(View.VISIBLE); - progressLayout.setVisibility(View.VISIBLE); - progress.startAnimation(cycleTime); + handler.post(() -> { + progress.setVisibility(View.VISIBLE); + progressLayout.setVisibility(View.VISIBLE); + progress.startAnimation(cycleTime); + }); } public void completeProgressMessage(String message, final ProgressCompleteCallback callback) @@ -78,27 +81,29 @@ public void onAnimationCancel(Animator animation) { } public void onAnimationRepeat(Animator animation) { } }; - if (!TextUtils.isEmpty(message)) - { - completeProgressSuccess(true); - hashText.setVisibility(View.VISIBLE); - hashText.setAlpha(1.0f); - if (message.length() > 1) hashText.setText(message); - - hashText.animate() - .alpha(0.0f) - .setDuration(1500) - .setListener(animatorListener); - } - else - { - completeProgressSuccess(false); - hashText.setVisibility(View.GONE); - hashText.animate() - .alpha(0.0f) - .setDuration(1500) - .setListener(animatorListener); - } + handler.post(() -> { + if (!TextUtils.isEmpty(message)) + { + completeProgressSuccess(true); + hashText.setVisibility(View.VISIBLE); + hashText.setAlpha(1.0f); + if (message.length() > 1) hashText.setText(message); + + hashText.animate() + .alpha(0.0f) + .setDuration(1500) + .setListener(animatorListener); + } + else + { + completeProgressSuccess(false); + hashText.setVisibility(View.GONE); + hashText.animate() + .alpha(0.0f) + .setDuration(1500) + .setListener(animatorListener); + } + }); } //listen for transaction completion diff --git a/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java b/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java index ca9329ccad..1a137c2e4b 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java @@ -12,7 +12,6 @@ import androidx.annotation.Nullable; import com.alphawallet.app.R; -import com.alphawallet.app.entity.ActionSheetInterface; import com.alphawallet.token.entity.Signable; /** @@ -26,7 +25,6 @@ public class SignDataWidget extends LinearLayout private final ImageView moreArrow; private final ScrollView scrollView; private final TextView messageTitle; - private ActionSheetInterface sheetInterface; private Signable signable; public SignDataWidget(Context context, @Nullable AttributeSet attrs) @@ -72,7 +70,6 @@ public void setupSignData(Signable message) scrollView.setVisibility(View.VISIBLE); messageTitle.setVisibility(View.GONE); moreArrow.setImageResource(R.drawable.ic_expand_less_black); - if (sheetInterface != null) sheetInterface.lockDragging(true); } else { @@ -80,16 +77,10 @@ public void setupSignData(Signable message) messageTitle.setVisibility(View.VISIBLE); scrollView.setVisibility(View.GONE); moreArrow.setImageResource(R.drawable.ic_expand_more); - if (sheetInterface != null) sheetInterface.lockDragging(false); } }); } - public void setLockCallback(ActionSheetInterface asIf) - { - sheetInterface = asIf; - } - public Signable getSignable() { return signable; diff --git a/app/src/main/java/com/alphawallet/app/widget/SignMethodDialog.java b/app/src/main/java/com/alphawallet/app/widget/SignMethodDialog.java deleted file mode 100644 index 7d6aa6bec5..0000000000 --- a/app/src/main/java/com/alphawallet/app/widget/SignMethodDialog.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.alphawallet.app.widget; - -import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.lifecycle.LifecycleOwner; -import androidx.lifecycle.ViewModelProvider; -import androidx.lifecycle.ViewModelStoreOwner; - -import com.alphawallet.app.R; -import com.alphawallet.app.entity.StandardFunctionInterface; -import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.repository.EthereumNetworkRepository; -import com.alphawallet.app.util.Hex; -import com.alphawallet.app.viewmodel.walletconnect.SignMethodDialogViewModel; -import com.alphawallet.app.walletconnect.AWWalletConnectClient; -import com.alphawallet.app.walletconnect.entity.BaseRequest; -import com.alphawallet.app.walletconnect.util.WalletConnectHelper; -import com.alphawallet.token.entity.SignMessageType; -import com.alphawallet.token.entity.Signable; -import com.bumptech.glide.Glide; -import com.google.android.material.bottomsheet.BottomSheetBehavior; -import com.google.android.material.bottomsheet.BottomSheetDialog; -import com.walletconnect.android.Core; -import com.walletconnect.sign.client.Sign; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; - -public class SignMethodDialog extends BottomSheetDialog -{ - private FunctionButtonBar functionBar; - private TextView dAppName; - private ImageView logo; - private TextView url; - private TextView walletTv; - private TextView message; - private ImageView networkIcon; - private ChainName networkName; - private final Activity activity; - private ImageView closeButton; - private final Sign.Model.SessionRequest sessionRequest; - private final BaseRequest request; - private String walletAddress; - private SignMethodDialogViewModel viewModel; - private final Signable signable; - private SignDataWidget signDataWidget; - private final Core.Model.AppMetaData metaData; - - public SignMethodDialog(@NonNull Activity activity, Sign.Model.SessionRequest sessionRequest, BaseRequest request, Core.Model.AppMetaData metaData) - { - super(activity); - this.activity = activity; - this.metaData = metaData; - this.sessionRequest = sessionRequest; - this.request = request; - this.signable = request.getSignable(); - View view = LayoutInflater.from(activity).inflate(R.layout.dialog_sign_method, null); - setContentView(view); - initViewModel(); - - BottomSheetBehavior behavior = BottomSheetBehavior.from((View) view.getParent()); - behavior.setState(STATE_EXPANDED); - behavior.setSkipCollapsed(true); - setCancelable(false); - - initViews(); - bindData(); - } - - private void bindData() - { - List icons = Objects.requireNonNull(metaData).getIcons(); - - if (icons.isEmpty()) - { - logo.setImageResource(R.drawable.ic_coin_eth_small); - } - else - { - Glide.with(activity) - .load(icons.get(0)) - .circleCrop() - .into(logo); - } - dAppName.setText(metaData.getName()); - url.setText(metaData.getUrl()); - walletAddress = request.getWalletAddress(); - walletTv.setText(walletAddress); - - long chainID = WalletConnectHelper.getChainId(Objects.requireNonNull(sessionRequest.getChainId())); - networkIcon.setImageResource(EthereumNetworkRepository.getChainLogo(chainID)); - networkName.setChainID(chainID); - functionBar.setupFunctions(new StandardFunctionInterface() - { - @Override - public void handleClick(String action, int actionId) - { - if (actionId == R.string.action_confirm) - { - approve(); - } - } - }, Collections.singletonList(R.string.action_confirm)); - - closeButton.setOnClickListener(v -> - { - viewModel.reject(sessionRequest); - dismiss(); - }); - - if (signable.getMessageType() == SignMessageType.SIGN_PERSONAL_MESSAGE - || signable.getMessageType() == SignMessageType.SIGN_MESSAGE) - { - message.setText(Hex.hexToUtf8(signable.getMessage())); - } - else - { - message.setVisibility(View.GONE); - signDataWidget.setVisibility(View.VISIBLE); - signDataWidget.setupSignData(request.getSignable()); - } - } - - private void initViews() - { - logo = findViewById(R.id.logo); - dAppName = findViewById(R.id.dapp_name); - url = findViewById(R.id.url); - walletTv = findViewById(R.id.wallet); - message = findViewById(R.id.message); - networkIcon = findViewById(R.id.network_icon); - networkName = findViewById(R.id.network_name); - functionBar = findViewById(R.id.layoutButtons); - closeButton = findViewById(R.id.image_close); - signDataWidget = findViewById(R.id.sign_widget); - } - - private void initViewModel() - { - viewModel = new ViewModelProvider((ViewModelStoreOwner) activity).get(SignMethodDialogViewModel.class); - } - - @SuppressLint("CheckResult") - private void approve() - { - AWWalletConnectClient.viewModel = viewModel; - viewModel.completed().observe((LifecycleOwner) activity, completed -> - { - if (completed) - { - dismiss(); - AWWalletConnectClient.viewModel = null; - } - }); - - viewModel.findWallet(walletAddress) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::onWalletFound); - } - - private void onWalletFound(Wallet wallet) - { - // The method find may return the first wallet if the specified wallet not found - if (!wallet.address.equals(walletAddress) || wallet.watchOnly()) - { - Toast.makeText(getContext(), activity.getString(R.string.wc_wallet_not_match), Toast.LENGTH_SHORT).show(); - } - else - { - functionBar.setPrimaryButtonWaiting(); - viewModel.sign(activity, wallet, sessionRequest, signable); - } - } -} diff --git a/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java b/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java index 03ccd000a3..3f60a5c579 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/SignTransactionDialog.java @@ -22,7 +22,7 @@ import com.alphawallet.app.entity.AuthenticationCallback; import com.alphawallet.app.entity.AuthenticationFailType; import com.alphawallet.app.entity.Operation; -import com.alphawallet.app.walletconnect.AWWalletConnectClient; +import com.alphawallet.app.ui.BaseActivity; import java.security.ProviderException; import java.util.concurrent.Executor; @@ -182,7 +182,7 @@ else if (km != null) else { intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - AWWalletConnectClient.authCallback = authCallback; + BaseActivity.authCallback = authCallback; activity.startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS + callBackId.ordinal()); } } @@ -206,4 +206,4 @@ public void close() } } } -} \ No newline at end of file +} diff --git a/app/src/main/res/layout/activity_wallet_connect_v2.xml b/app/src/main/res/layout/activity_wallet_connect_v2.xml index 8e095ce0fb..2a4c35b0e4 100644 --- a/app/src/main/res/layout/activity_wallet_connect_v2.xml +++ b/app/src/main/res/layout/activity_wallet_connect_v2.xml @@ -23,7 +23,7 @@ android:layout_gravity="center_horizontal" android:layout_marginTop="@dimen/dp5" android:layout_marginBottom="@dimen/dp5" - android:src="@mipmap/ic_alpha" /> + android:src="@mipmap/ic_launcher" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/dialog_action_sheet_message.xml b/app/src/main/res/layout/dialog_action_sheet_message.xml deleted file mode 100644 index 95c2912bed..0000000000 --- a/app/src/main/res/layout/dialog_action_sheet_message.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_action_sheet_sign.xml b/app/src/main/res/layout/dialog_action_sheet_sign.xml index 7a30b4187b..f9a07a5177 100644 --- a/app/src/main/res/layout/dialog_action_sheet_sign.xml +++ b/app/src/main/res/layout/dialog_action_sheet_sign.xml @@ -17,11 +17,6 @@ android:layout_height="wrap_content" custom:label="@string/requester_url" /> - - - \ No newline at end of file + diff --git a/app/src/main/res/layout/item_ticket.xml b/app/src/main/res/layout/item_ticket.xml index 720006da98..934a8adf7c 100644 --- a/app/src/main/res/layout/item_ticket.xml +++ b/app/src/main/res/layout/item_ticket.xml @@ -13,13 +13,6 @@ android:minHeight="100dp" android:paddingHorizontal="@dimen/tiny_8"> - - getSignatureForTransaction(Wallet from, String to } @Override - public Single getSignature(Wallet wallet, Signable sign, long chainId) + public Single getSignature(Wallet wallet, Signable sign) { return null; } @Override - public Single getSignatureFast(Wallet wallet, String pass, byte[] message, long chainId) + public Single getSignatureFast(Wallet wallet, String pass, byte[] message) { return Single.fromCallable(() -> { //sign using the local key @@ -222,7 +222,7 @@ public Single getMessage(List indexList, String contrac .getMessage(qr.indices, CONTRACT_ADDR, ContractType.ERC875).blockingGet(); byte[] sig = transactionRepository - .getSignatureFast(null, "hackintosh", messagePair.message.getBytes(), 1).blockingGet(); + .getSignatureFast(null, "hackintosh", messagePair.message.getBytes()).blockingGet(); qr.sigPair = new SignaturePair(messagePair.selection, sig, messagePair.message); } diff --git a/app/src/test/java/com/alphawallet/app/walletconnect/SignRequestTest.java b/app/src/test/java/com/alphawallet/app/walletconnect/SignRequestTest.java index 4011a51f2a..ab4d61ac54 100644 --- a/app/src/test/java/com/alphawallet/app/walletconnect/SignRequestTest.java +++ b/app/src/test/java/com/alphawallet/app/walletconnect/SignRequestTest.java @@ -1,13 +1,14 @@ package com.alphawallet.app.walletconnect; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import com.alphawallet.app.walletconnect.entity.SignRequest; import com.alphawallet.token.entity.SignMessageType; import org.junit.Before; import org.junit.Test; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; - public class SignRequestTest { private SignRequest signRequest; @@ -30,4 +31,4 @@ public void testGetSignable() assertThat(signRequest.getSignable().getMessage(), equalTo("0x4d7920656d61696c206973206a6f686e40646f652e636f6d202d2031363437323235383333333539")); assertThat(signRequest.getSignable().getMessageType(), equalTo(SignMessageType.SIGN_MESSAGE)); } -} \ No newline at end of file +} From 714bbd0dfb6d0d7eb3cc85ccf9da590247b53560 Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 28 Nov 2022 12:21:32 +1100 Subject: [PATCH 155/183] Batch up NFT balance updates (#2975) --- .../com/alphawallet/app/entity/EventSync.java | 77 +++++-- .../app/entity/tokens/ERC721Token.java | 208 ++++++++++++++---- .../app/repository/EthereumNetworkBase.java | 45 ++++ 3 files changed, 274 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/entity/EventSync.java b/app/src/main/java/com/alphawallet/app/entity/EventSync.java index 1d600a7617..8a37935b9c 100644 --- a/app/src/main/java/com/alphawallet/app/entity/EventSync.java +++ b/app/src/main/java/com/alphawallet/app/entity/EventSync.java @@ -13,6 +13,7 @@ import org.web3j.abi.datatypes.Type; import org.web3j.abi.datatypes.generated.Uint256; import org.web3j.protocol.Web3j; +import org.web3j.protocol.core.BatchResponse; import org.web3j.protocol.core.DefaultBlockParameter; import org.web3j.protocol.core.Response; import org.web3j.protocol.core.methods.request.EthFilter; @@ -37,6 +38,8 @@ public class EventSync private final Token token; + private boolean batchProcessingError = false; + public EventSync(Token token) { this.token = token; @@ -375,26 +378,18 @@ public Pair, HashSet>> processTran EthFilter receiveFilter = token.getReceiveBalanceFilter(transferEvent, startBlock, endBlock); EthFilter sendFilter = token.getSendBalanceFilter(transferEvent, startBlock, endBlock); - EthLog receiveLogs = web3j.ethGetLogs(receiveFilter).send(); - if (receiveLogs.hasError()) - { - throw new LogOverflowException(receiveLogs.getError()); - } + Pair ethLogs = getTxLogs(web3j, receiveFilter, sendFilter); + + EthLog receiveLogs = ethLogs.first; + EthLog sendLogs = ethLogs.second; int eventCount = receiveLogs.getLogs().size(); HashSet rcvTokenIds = new HashSet<>(token.processLogsAndStoreTransferEvents(receiveLogs, transferEvent, txHashes, realm)); - EthLog sentLogs = web3j.ethGetLogs(sendFilter).send(); - - if (sentLogs.hasError()) - { - throw new LogOverflowException(receiveLogs.getError()); - } - - if (sentLogs.getLogs().size() > eventCount) eventCount = sentLogs.getLogs().size(); + if (sendLogs.getLogs().size() > eventCount) eventCount = sendLogs.getLogs().size(); - HashSet sendTokenIds = token.processLogsAndStoreTransferEvents(sentLogs, transferEvent, txHashes, realm); + HashSet sendTokenIds = token.processLogsAndStoreTransferEvents(sendLogs, transferEvent, txHashes, realm); //register Transaction fetches for (String txHash : txHashes) @@ -405,6 +400,60 @@ public Pair, HashSet>> processTran return new Pair<>(eventCount, new Pair<>(rcvTokenIds, sendTokenIds)); } + private Pair getTxLogs(Web3j web3j, EthFilter receiveFilter, EthFilter sendFilter) throws LogOverflowException, IOException + { + if (EthereumNetworkBase.getBatchProcessingLimit(token.tokenInfo.chainId) > 0 && !batchProcessingError) + { + return getBatchTxLogs(web3j, receiveFilter, sendFilter); + } + else + { + EthLog receiveLogs = web3j.ethGetLogs(receiveFilter).send(); + + if (receiveLogs.hasError()) + { + throw new LogOverflowException(receiveLogs.getError()); + } + + EthLog sentLogs = web3j.ethGetLogs(sendFilter).send(); + + if (sentLogs.hasError()) + { + throw new LogOverflowException(sentLogs.getError()); + } + + return new Pair<>(receiveLogs, sentLogs); + } + } + + private Pair getBatchTxLogs(Web3j web3j, EthFilter receiveFilter, EthFilter sendFilter) throws LogOverflowException, IOException + { + BatchResponse rsp = web3j.newBatch() + .add(web3j.ethGetLogs(receiveFilter)) + .add(web3j.ethGetLogs(sendFilter)) + .send(); + + if (rsp.getResponses().size() != 2) + { + batchProcessingError = true; + return getTxLogs(web3j, receiveFilter, sendFilter); + } + + EthLog receiveLogs = (EthLog) rsp.getResponses().get(0); + EthLog sendLogs = (EthLog) rsp.getResponses().get(1); + + if (receiveLogs.hasError()) + { + throw new LogOverflowException(receiveLogs.getError()); + } + else if (sendLogs.hasError()) + { + throw new LogOverflowException(sendLogs.getError()); + } + + return new Pair<>(receiveLogs, sendLogs); + } + public String getActivityName(String toAddress) { String activityName = ""; diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java index 780840a40a..e646171d67 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java @@ -1,11 +1,13 @@ package com.alphawallet.app.entity.tokens; +import static com.alphawallet.app.repository.TokenRepository.callSmartContractFunction; import static com.alphawallet.app.repository.TokensRealmSource.databaseKey; import static com.alphawallet.app.util.Utils.parseTokenId; import static org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction; import static org.web3j.tx.Contract.staticExtractEventParameters; import android.app.Activity; +import android.text.TextUtils; import android.util.Pair; import com.alphawallet.app.R; @@ -30,20 +32,26 @@ import org.web3j.abi.FunctionReturnDecoder; import org.web3j.abi.TypeEncoder; import org.web3j.abi.TypeReference; +import org.web3j.abi.Utils; import org.web3j.abi.datatypes.Address; import org.web3j.abi.datatypes.Event; import org.web3j.abi.datatypes.Function; import org.web3j.abi.datatypes.Type; import org.web3j.abi.datatypes.generated.Uint256; import org.web3j.protocol.Web3j; +import org.web3j.protocol.core.BatchRequest; +import org.web3j.protocol.core.BatchResponse; import org.web3j.protocol.core.DefaultBlockParameter; import org.web3j.protocol.core.DefaultBlockParameterName; +import org.web3j.protocol.core.Request; +import org.web3j.protocol.core.Response; import org.web3j.protocol.core.methods.request.EthFilter; import org.web3j.protocol.core.methods.response.EthCall; import org.web3j.protocol.core.methods.response.EthLog; import org.web3j.protocol.core.methods.response.Log; import org.web3j.utils.Numeric; +import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; @@ -68,6 +76,7 @@ public class ERC721Token extends Token { private final Map tokenBalanceAssets; private static final Map balanceChecks = new ConcurrentHashMap<>(); + private boolean batchProcessingError; public ERC721Token(TokenInfo tokenInfo, Map balanceList, BigDecimal balance, long blancaTime, String networkName, ContractType type) { @@ -82,6 +91,7 @@ public ERC721Token(TokenInfo tokenInfo, Map balanceList, B } setInterfaceSpec(type); group = TokenGroup.NFT; + batchProcessingError = false; } @Override @@ -372,12 +382,8 @@ public BigDecimal updateBalance(Realm realm) allMovingTokens.addAll(tokenBalanceAssets.keySet()); } - //no need to check balances if this chain is supported by OpenSea - if (allMovingTokens.size() < 10 || !EthereumNetworkBase.hasOpenseaAPI(tokenInfo.chainId)) - { - HashSet tokenIdsHeld = checkBalances(web3j, allMovingTokens); - updateRealmBalance(realm, tokenIdsHeld, allMovingTokens); - } + HashSet tokenIdsHeld = checkBalances(web3j, allMovingTokens); + updateRealmBalance(realm, tokenIdsHeld, allMovingTokens); } catch (LogOverflowException e) { @@ -410,21 +416,87 @@ public BigDecimal updateBalance(Realm realm) /*********** * For ERC721Enumerable interface **********/ - private void updateEnumerableBalance(Web3j web3j, Realm realm) + private void updateEnumerableBalance(Web3j web3j, Realm realm) throws IOException { HashSet tokenIdsHeld = new HashSet<>(); //get enumerable balance //find tokenIds held long currentBalance = balance != null ? balance.longValue() : 0; + + if (EthereumNetworkBase.getBatchProcessingLimit(tokenInfo.chainId) > 0 && !batchProcessingError && currentBalance > 1) //no need to do batch query for 1 + { + updateEnumerableBatchBalance(web3j, currentBalance, tokenIdsHeld, realm); + } + else + { + for (long tokenIndex = 0; tokenIndex < currentBalance; tokenIndex++) + { + // find tokenId from index + String tokenId = callSmartContractFunction(tokenInfo.chainId, tokenOfOwnerByIndex(BigInteger.valueOf(tokenIndex)), getAddress(), getWallet()); + if (tokenId == null) continue; + tokenIdsHeld.add(new BigInteger(tokenId)); + } + } + + updateRealmForEnumerable(realm, tokenIdsHeld); + } + + private void updateEnumerableBatchBalance(Web3j web3j, long currentBalance, HashSet tokenIdsHeld, Realm realm) throws IOException + { + BatchRequest requests = web3j.newBatch(); + for (long tokenIndex = 0; tokenIndex < currentBalance; tokenIndex++) { - // find tokenId from index - String tokenId = callSmartContractFunction(web3j, tokenOfOwnerByIndex(BigInteger.valueOf(tokenIndex)), getAddress(), getWallet()); + requests.add(getContractCall(web3j, tokenOfOwnerByIndex(BigInteger.valueOf(tokenIndex)), getAddress())); + if (requests.getRequests().size() >= EthereumNetworkBase.getBatchProcessingLimit(tokenInfo.chainId)) + { + //do this send + handleEnumerableRequests(requests, tokenIdsHeld); + requests = web3j.newBatch(); + } + } + + if (requests.getRequests().size() > 0) + { + //do final call + handleEnumerableRequests(requests, tokenIdsHeld); + } + + if (batchProcessingError) + { + updateEnumerableBalance(web3j, realm); + } + } + + private void handleEnumerableRequests(BatchRequest requests, HashSet tokenIdsHeld) throws IOException + { + BatchResponse responses = requests.send(); + if (responses.getResponses().size() != requests.getRequests().size()) + { + batchProcessingError = true; + return; + } + + //process responses + for (Response rsp : responses.getResponses()) + { + BigInteger tokenId = getTokenId(rsp); if (tokenId == null) continue; - tokenIdsHeld.add(new BigInteger(tokenId)); + tokenIdsHeld.add(tokenId); } + } - updateRealmForEnumerable(realm, tokenIdsHeld); + private BigInteger getTokenId(Response rsp) + { + List> outputParams = Utils.convert(Collections.singletonList(new TypeReference() {})); + List responseValues = FunctionReturnDecoder.decode(((EthCall)rsp).getValue(), outputParams); + if (!responseValues.isEmpty()) + { + String tokenIdStr = responseValues.get(0).getValue().toString(); + if (!TextUtils.isEmpty(tokenIdStr)) return new BigInteger(tokenIdStr); + } + + return null; } private void updateRealmBalance(Realm realm, Set tokenIds, Set allMovingTokens) @@ -551,12 +623,14 @@ public HashSet processLogsAndStoreTransferEvents(EthLog receiveLogs, return tokenIds; } - private HashSet checkBalances(Web3j web3j, HashSet eventIds) + private HashSet checkBalances(Web3j web3j, HashSet eventIds) throws IOException { HashSet heldTokens = new HashSet<>(); + if (EthereumNetworkBase.getBatchProcessingLimit(tokenInfo.chainId) > 0 && !batchProcessingError && eventIds.size() > 1) return checkBatchBalances(web3j, eventIds); + for (BigInteger tokenId : eventIds) { - String owner = callSmartContractFunction(web3j, ownerOf(tokenId), getAddress(), getWallet()); + String owner = callSmartContractFunction(tokenInfo.chainId, ownerOf(tokenId), getAddress(), getWallet()); if (owner == null || owner.equalsIgnoreCase(getWallet())) { heldTokens.add(tokenId); @@ -566,6 +640,80 @@ private HashSet checkBalances(Web3j web3j, HashSet event return heldTokens; } + private HashSet checkBatchBalances(Web3j web3j, HashSet eventIds) throws IOException + { + HashSet heldTokens = new HashSet<>(); + List balanceIds = new ArrayList<>(); + BatchRequest requests = web3j.newBatch(); + for (BigInteger tokenId : eventIds) + { + requests.add(getContractCall(web3j, ownerOf(tokenId), getAddress())); + balanceIds.add(tokenId); + if (requests.getRequests().size() >= EthereumNetworkBase.getBatchProcessingLimit(tokenInfo.chainId)) + { + //do this send + handleRequests(requests, balanceIds, heldTokens); + requests = web3j.newBatch(); + } + } + + if (requests.getRequests().size() > 0) + { + //do final call + handleRequests(requests, balanceIds, heldTokens); + } + + if (batchProcessingError) + { + return checkBalances(web3j, eventIds); + } + else + { + return heldTokens; + } + } + + private void handleRequests(BatchRequest requests, List balanceIds, HashSet heldTokens) throws IOException + { + int index = 0; + BatchResponse responses = requests.send(); + if (responses.getResponses().size() != requests.getRequests().size()) + { + batchProcessingError = true; + return; + } + + //process responses + for (Response rsp : responses.getResponses()) + { + BigInteger tokenId = balanceIds.get(index); + if (isOwner(rsp, tokenId)) + { + heldTokens.add(tokenId); + } + + index++; + } + + balanceIds.clear(); + } + + private boolean isOwner(Response rsp, BigInteger tokenId) + { + EthCall response = (EthCall) rsp; + Function function = ownerOf(tokenId); + List responseValues = FunctionReturnDecoder.decode(response.getValue(), function.getOutputParameters()); + if (!responseValues.isEmpty()) + { + String owner = responseValues.get(0).getValue().toString(); + return (!owner.isEmpty() && owner.equalsIgnoreCase(getWallet())); + } + else + { + return false; + } + } + @Override public EthFilter getReceiveBalanceFilter(Event event, DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { @@ -695,8 +843,6 @@ public BigDecimal getBalanceRaw() @Override public Map queryAssets(Map assetMap) { - final Web3j web3j = TokenRepository.getWeb3jService(tokenInfo.chainId); - //check all tokens in this contract assetMap.putAll(tokenBalanceAssets); @@ -707,7 +853,7 @@ public Map queryAssets(Map assetMap) NFTAsset checkAsset = entry.getValue(); //check balance - String owner = callSmartContractFunction(web3j, ownerOf(checkId), getAddress(), getWallet()); + String owner = callSmartContractFunction(tokenInfo.chainId, ownerOf(checkId), getAddress(), getWallet()); if (owner == null) //play it safe. If there's no 'ownerOf' for an ERC721, it's something custom like ENS { checkAsset.setBalance(BigDecimal.ONE); @@ -752,34 +898,12 @@ public List getChangeList(Map assetMap) return changeList; } - private String callSmartContractFunction(Web3j web3j, - Function function, String contractAddress, String walletAddr) + private Request getContractCall(Web3j web3j, Function function, String contractAddress) { String encodedFunction = FunctionEncoder.encode(function); - - try - { - org.web3j.protocol.core.methods.request.Transaction transaction - = createEthCallTransaction(walletAddr, contractAddress, encodedFunction); - EthCall response = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send(); - - List responseValues = FunctionReturnDecoder.decode(response.getValue(), function.getOutputParameters()); - - if (!responseValues.isEmpty()) - { - return responseValues.get(0).getValue().toString(); - } - else if (response.hasError() && response.getError().getCode() == 3) //reverted - { - return ""; - } - } - catch (Exception e) - { - // - } - - return null; + org.web3j.protocol.core.methods.request.Transaction transaction + = createEthCallTransaction(getWallet(), contractAddress, encodedFunction); + return web3j.ethCall(transaction, DefaultBlockParameterName.LATEST); } private static Function ownerOf(BigInteger token) diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 5f36af584c..da7d5ad0ee 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -560,6 +560,51 @@ else if (networkMap.indexOfKey(chainId) >= 0) } } + //TODO: Refactor when we bump the version of java to allow switch on Long (Finally!!) + //Also TODO: add a test to check these batch limits of each chain we support + private static int batchProcessingLimit(long chainId) + { + NetworkInfo info = builtinNetworkMap.get(chainId); + if (info.rpcServerUrl.contains("infura")) //infura supported chains can handle tx batches of 1000 and up + { + return 512; + } + else if (info.rpcServerUrl.contains("klaytn")) + { + return 0; + } + else if (info.rpcServerUrl.contains("gnosis")) + { + return 6; //TODO: Check limit + } + else if (info.rpcServerUrl.contains("cronos.org")) + { + return 5; //TODO: Check limit + } + else + { + return 32; + } + } + + private static final LongSparseArray batchProcessingLimitMap = new LongSparseArray<>(); + + //Init the batch limits + private static void setBatchProcessingLimits() + { + for (int i = 0; i < builtinNetworkMap.size(); i++) + { + NetworkInfo info = builtinNetworkMap.valueAt(i); + batchProcessingLimitMap.put(info.chainId, batchProcessingLimit(info.chainId)); + } + } + + public static int getBatchProcessingLimit(long chainId) + { + if (batchProcessingLimitMap.size() == 0) setBatchProcessingLimits(); //If batch limits not set, init them and proceed + return batchProcessingLimitMap.get(chainId, 0); //default to zero / no batching + } + @Override public boolean hasLockedGas(long chainId) { From aebfce579cf001b7bcba8d0d15f02f93a335a491 Mon Sep 17 00:00:00 2001 From: Seaborn Date: Mon, 28 Nov 2022 10:09:22 +0800 Subject: [PATCH 156/183] 2804 integration tests for erc20 transfer (#2974) * Transfer ERC20 test * Run CI on GitHub default MacOS node --- .github/workflows/ci.yml | 3 +- .../alphawallet/app/TransferERC20Test.java | 102 ++++++++++++++++++ .../com/alphawallet/app/TransferTest.java | 2 +- .../alphawallet/app/resources/Contracts.java | 1 + .../java/com/alphawallet/app/steps/Steps.java | 47 ++++++-- .../com/alphawallet/app/util/EthUtils.java | 2 +- 6 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 app/src/androidTest/java/com/alphawallet/app/TransferERC20Test.java diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89a1bb9bf3..a4b473b76f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: pull_request: jobs: test: - runs-on: self-hosted + runs-on: macos-latest concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -18,7 +18,6 @@ jobs: with: distribution: zulu java-version: 11 - architecture: arm64 - name: Run unit tests run: sh ./build.sh diff --git a/app/src/androidTest/java/com/alphawallet/app/TransferERC20Test.java b/app/src/androidTest/java/com/alphawallet/app/TransferERC20Test.java new file mode 100644 index 0000000000..54b9beec9c --- /dev/null +++ b/app/src/androidTest/java/com/alphawallet/app/TransferERC20Test.java @@ -0,0 +1,102 @@ +package com.alphawallet.app; + +import static com.alphawallet.app.steps.Steps.GANACHE_URL; +import static com.alphawallet.app.steps.Steps.addCustomToken; +import static com.alphawallet.app.steps.Steps.addNewNetwork; +import static com.alphawallet.app.steps.Steps.assertBalanceIs; +import static com.alphawallet.app.steps.Steps.createNewWallet; +import static com.alphawallet.app.steps.Steps.ensureTransactionConfirmed; +import static com.alphawallet.app.steps.Steps.getWalletAddress; +import static com.alphawallet.app.steps.Steps.gotoWalletPage; +import static com.alphawallet.app.steps.Steps.importWalletFromSettingsPage; +import static com.alphawallet.app.steps.Steps.selectTestNet; +import static com.alphawallet.app.steps.Steps.sendBalanceTo; +import static com.alphawallet.app.steps.Steps.switchToWallet; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import android.os.Build; + +import com.alphawallet.app.resources.Contracts; +import com.alphawallet.app.util.EthUtils; + +import org.junit.Before; +import org.junit.Test; +import org.web3j.crypto.Credentials; +import org.web3j.protocol.Web3j; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +public class TransferERC20Test extends BaseE2ETest +{ + private String contractAddress; + private final String contractOwnerPk = "0x69c22d654be7fe75e31fbe26cb56c93ec91144fab67cb71529c8081971635069"; + // On CI server, run tests on different API levels concurrently may cause failure: Replacement transaction underpriced. + // Use different wallet to transfer token from can avoid this error + private static final Map WALLETS_ON_GANACHE = new HashMap() + { + { + put("24", new String[]{"0x644022aef70ad515ee186345fd74b005d759f41be8157c2835de3597d943146d", "0xE494323823fdF1A1Ab6ca79d2538C7182690D52a"}); + put("30", new String[]{"0x5c8843768e0e1916255def80ae7f6197e1f6a2dbcba720038748fc7634e5cffd", "0x162f5e0b63646AAA33a85eA13346F15C5289f901"}); + put("32", new String[]{"0x992b442eaa34de3c6ba0b61c75b2e4e0241d865443e313c4fa6ab8ba488a6957", "0xd7Ba01f596a7cc926b96b3B0a037c47A22904c06"}); + } + }; + private Web3j web3j; + private String senderPrivateKey; + private Credentials senderCredentials; + private Credentials contractOwnerCredentials; + + @Override + @Before + public void setUp() + { + int apiLevel = Build.VERSION.SDK_INT; + String[] array = WALLETS_ON_GANACHE.get(String.valueOf(apiLevel)); + if (array == null) + { + fail("Please config seed phrase and wallet address for this API level first."); + } + + senderPrivateKey = array[0]; + senderCredentials = Credentials.create(senderPrivateKey); + contractOwnerCredentials = Credentials.create(contractOwnerPk); + + super.setUp(); + web3j = EthUtils.buildWeb3j(GANACHE_URL); + deployTestTokenOnGanache(); + } + + private void deployTestTokenOnGanache() + { + //Transfer 1 eth into deployment wallet + EthUtils.transferFunds(web3j, senderCredentials, contractOwnerCredentials.getAddress(), BigDecimal.ONE); + + //Deploy door contract + EthUtils.deployContract(web3j, contractOwnerCredentials, Contracts.erc20ContractCode); + + //Always use zero nonce for determining the contract address + contractAddress = EthUtils.calculateContractAddress(contractOwnerCredentials.getAddress(), 0L); + + assertNotNull(contractAddress); + } + + @Test + public void should_transfer_from_an_account_to_another() + { + createNewWallet(); + String newWalletAddress = getWalletAddress(); + + importWalletFromSettingsPage(contractOwnerPk); + addNewNetwork("Ganache", GANACHE_URL); + selectTestNet("Ganache"); + gotoWalletPage(); + addCustomToken(contractAddress); + sendBalanceTo("AW test token", "1.11", newWalletAddress); + ensureTransactionConfirmed(); + switchToWallet(newWalletAddress); + addCustomToken(contractAddress); + assertBalanceIs("1.11"); + } +} diff --git a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java index 12c085f03d..3205f4fee1 100644 --- a/app/src/androidTest/java/com/alphawallet/app/TransferTest.java +++ b/app/src/androidTest/java/com/alphawallet/app/TransferTest.java @@ -50,7 +50,7 @@ public void should_transfer_from_an_account_to_another() importWalletFromSettingsPage(privateKey); addNewNetwork("Ganache", GANACHE_URL); selectTestNet("Ganache"); - sendBalanceTo(newWalletAddress, "0.001"); + sendBalanceTo("ETH", "0.001", newWalletAddress); ensureTransactionConfirmed(); switchToWallet(newWalletAddress); assertBalanceIs("0.001"); diff --git a/app/src/androidTest/java/com/alphawallet/app/resources/Contracts.java b/app/src/androidTest/java/com/alphawallet/app/resources/Contracts.java index 87ca34788c..5dcfe4ab9d 100644 --- a/app/src/androidTest/java/com/alphawallet/app/resources/Contracts.java +++ b/app/src/androidTest/java/com/alphawallet/app/resources/Contracts.java @@ -6,4 +6,5 @@ public abstract class Contracts { public static String doorContractCode = "0x60806040523480156200001157600080fd5b506040518060400160405280600b81526020016a29aa26102428902237b7b960a91b815250604051806040016040528060068152602001654f464649434560d01b81525081600090816200006691906200042d565b5060016200007582826200042d565b505050620000926200008c620000e460201b60201c565b620000e8565b620000a960076200013a60201b62000e501760201c565b6040518060600160405280603581526020016200218360359139600a90620000d290826200042d565b50620000dd62000143565b5062000521565b3390565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80546001019055565b6006546000906001600160a01b03163314620001a65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b620001bd60076200023860201b62000e591760201c565b90506127108110620002125760405162461bcd60e51b815260206004820152601460248201527f486974207570706572206d696e74206c696d697400000000000000000000000060448201526064016200019d565b6200021e33826200023c565b6200023560076200013a60201b62000e501760201c565b90565b5490565b6001600160a01b038216620002945760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016200019d565b6000818152600260205260409020546001600160a01b031615620002fb5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016200019d565b6001600160a01b038216600090815260036020526040812080546001929062000326908490620004f9565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620003b457607f821691505b602082108103620003d557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200038457600081815260208120601f850160051c81016020861015620004045750805b601f850160051c820191505b81811015620004255782815560010162000410565b505050505050565b81516001600160401b0381111562000449576200044962000389565b62000461816200045a84546200039f565b84620003db565b602080601f831160018114620004995760008415620004805750858301515b600019600386901b1c1916600185901b17855562000425565b600085815260208120601f198616915b82811015620004ca57888601518255948401946001909101908401620004a9565b5085821015620004e95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b808201808211156200051b57634e487b7160e01b600052601160045260246000fd5b92915050565b611c5280620005316000396000f3fe60806040526004361061019c5760003560e01c806384c4bd4b116100ec578063a740fc871161008a578063e67876fe11610064578063e67876fe14610452578063e8a3d48514610469578063e985e9c51461047e578063f2fde38b1461049e57600080fd5b8063a740fc87146103fb578063b88d4fde14610412578063c87b56dd1461043257600080fd5b8063985e49f4116100c6578063985e49f4146103a95780639cb8a26a146103be578063a22cb465146103c6578063a49ff5b2146103e657600080fd5b806384c4bd4b1461035f5780638da5cb5b1461037657806395d89b411461039457600080fd5b80634bb309121161015957806370a082311161013357806370a08231146102e7578063715018a6146103155780637b47ec1a1461032a57806382345f991461034a57600080fd5b80634bb30912146102925780636352211e146102a75780636f3bffd2146102c757600080fd5b806301ffc9a7146101a157806306fdde03146101d6578063081812fc146101f8578063095ea7b31461023057806323b872dd1461025257806342842e0e14610272575b600080fd5b3480156101ad57600080fd5b506101c16101bc366004611585565b6104be565b60405190151581526020015b60405180910390f35b3480156101e257600080fd5b506101eb610510565b6040516101cd91906115ef565b34801561020457600080fd5b50610218610213366004611602565b6105a2565b6040516001600160a01b0390911681526020016101cd565b34801561023c57600080fd5b5061025061024b366004611632565b61063c565b005b34801561025e57600080fd5b5061025061026d36600461165c565b610751565b34801561027e57600080fd5b5061025061028d36600461165c565b6107ac565b34801561029e57600080fd5b506101eb6107c7565b3480156102b357600080fd5b506102186102c2366004611602565b6107d6565b3480156102d357600080fd5b506102506102e2366004611724565b61084d565b3480156102f357600080fd5b5061030761030236600461176d565b6108be565b6040519081526020016101cd565b34801561032157600080fd5b50610250610945565b34801561033657600080fd5b50610250610345366004611602565b61097b565b34801561035657600080fd5b50610307610a15565b34801561036b57600080fd5b506007546103079081565b34801561038257600080fd5b506006546001600160a01b0316610218565b3480156103a057600080fd5b506101eb610ac7565b3480156103b557600080fd5b50610307610ad6565b610250610b67565b3480156103d257600080fd5b506102506103e1366004611788565b610b9f565b3480156103f257600080fd5b50610307610bae565b34801561040757600080fd5b506009546103079081565b34801561041e57600080fd5b5061025061042d3660046117c4565b610c0f565b34801561043e57600080fd5b506101eb61044d366004611602565b610c71565b34801561045e57600080fd5b506008546103079081565b34801561047557600080fd5b506101eb610d6a565b34801561048a57600080fd5b506101c1610499366004611840565b610d8a565b3480156104aa57600080fd5b506102506104b936600461176d565b610db8565b60006001600160e01b031982166380ac58cd60e01b14806104ef57506001600160e01b03198216635b5e139f60e01b145b8061050a57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461051f90611873565b80601f016020809104026020016040519081016040528092919081815260200182805461054b90611873565b80156105985780601f1061056d57610100808354040283529160200191610598565b820191906000526020600020905b81548152906001019060200180831161057b57829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166106205760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610647826107d6565b9050806001600160a01b0316836001600160a01b0316036106b45760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610617565b336001600160a01b03821614806106d057506106d08133610d8a565b6107425760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610617565b61074c8383610e5d565b505050565b6006546001600160a01b0316331461077b5760405162461bcd60e51b8152600401610617906118ad565b6107853382610ecb565b6107a15760405162461bcd60e51b8152600401610617906118e2565b61074c838383610fa2565b61074c83838360405180602001604052806000815250610c0f565b6060600a805461051f90611873565b6000818152600260205260408120546001600160a01b03168061050a5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610617565b6006546001600160a01b031633146108775760405162461bcd60e51b8152600401610617906118ad565b600a6108838282611981565b507fd6666840ba3b0939cf78131cb173315c425a3385a30b8921494500ca2b49f34a816040516108b391906115ef565b60405180910390a150565b60006001600160a01b0382166109295760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610617565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b0316331461096f5760405162461bcd60e51b8152600401610617906118ad565b610979600061113e565b565b6006546001600160a01b031633146109a55760405162461bcd60e51b8152600401610617906118ad565b6000818152600260205260409020546001600160a01b0316610a095760405162461bcd60e51b815260206004820152601760248201527f6275726e3a206e6f6e6578697374656e7420746f6b656e0000000000000000006044820152606401610617565b610a1281611190565b50565b6006546000906001600160a01b03163314610a425760405162461bcd60e51b8152600401610617906118ad565b612710610a4e60085490565b610a589190611a57565b9050610a676127106002611a6a565b8110610aac5760405162461bcd60e51b8152602060048201526014602482015273121a5d081d5c1c195c881b5a5b9d081b1a5b5a5d60621b6044820152606401610617565b610ab6338261122b565b610ac4600880546001019055565b90565b60606001805461051f90611873565b6006546000906001600160a01b03163314610b035760405162461bcd60e51b8152600401610617906118ad565b506007546127108110610b4f5760405162461bcd60e51b8152602060048201526014602482015273121a5d081d5c1c195c881b5a5b9d081b1a5b5a5d60621b6044820152606401610617565b610b59338261122b565b610ac4600780546001019055565b6006546001600160a01b03163314610b915760405162461bcd60e51b8152600401610617906118ad565b6006546001600160a01b0316ff5b610baa33838361136d565b5050565b6006546000906001600160a01b03163314610bdb5760405162461bcd60e51b8152600401610617906118ad565b610be86127106002611a6a565b600954610bf59190611a57565b9050610c01338261122b565b610ac4600980546001019055565b6006546001600160a01b03163314610c395760405162461bcd60e51b8152600401610617906118ad565b610c433383610ecb565b610c5f5760405162461bcd60e51b8152600401610617906118e2565b610c6b8484848461143b565b50505050565b6000818152600260205260409020546060906001600160a01b0316610cea5760405162461bcd60e51b815260206004820152602960248201527f746f6b656e5552493a2055524920717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610617565b612710821015610d1357604051806060016040528060358152602001611b496035913992915050565b610d206127106002611a6a565b821015610d4657604051806060016040528060358152602001611b7e6035913992915050565b604051806060016040528060358152602001611bb36035913992915050565b919050565b6060604051806060016040528060358152602001611be860359139905090565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6006546001600160a01b03163314610de25760405162461bcd60e51b8152600401610617906118ad565b6001600160a01b038116610e475760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610617565b610a128161113e565b80546001019055565b5490565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610e92826107d6565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b0316610f445760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610617565b6000610f4f836107d6565b9050806001600160a01b0316846001600160a01b03161480610f765750610f768185610d8a565b80610f9a5750836001600160a01b0316610f8f846105a2565b6001600160a01b0316145b949350505050565b826001600160a01b0316610fb5826107d6565b6001600160a01b0316146110195760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610617565b6001600160a01b03821661107b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610617565b611086600082610e5d565b6001600160a01b03831660009081526003602052604081208054600192906110af908490611a89565b90915550506001600160a01b03821660009081526003602052604081208054600192906110dd908490611a57565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061119b826107d6565b90506111a8600083610e5d565b6001600160a01b03811660009081526003602052604081208054600192906111d1908490611a89565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6001600160a01b0382166112815760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610617565b6000818152600260205260409020546001600160a01b0316156112e65760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610617565b6001600160a01b038216600090815260036020526040812080546001929061130f908490611a57565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b816001600160a01b0316836001600160a01b0316036113ce5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610617565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611446848484610fa2565b6114528484848461146e565b610c6b5760405162461bcd60e51b815260040161061790611a9c565b60006001600160a01b0384163b1561156457604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906114b2903390899088908890600401611aee565b6020604051808303816000875af19250505080156114ed575060408051601f3d908101601f191682019092526114ea91810190611b2b565b60015b61154a573d80801561151b576040519150601f19603f3d011682016040523d82523d6000602084013e611520565b606091505b5080516000036115425760405162461bcd60e51b815260040161061790611a9c565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610f9a565b506001949350505050565b6001600160e01b031981168114610a1257600080fd5b60006020828403121561159757600080fd5b81356115a28161156f565b9392505050565b6000815180845260005b818110156115cf576020818501810151868301820152016115b3565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006115a260208301846115a9565b60006020828403121561161457600080fd5b5035919050565b80356001600160a01b0381168114610d6557600080fd5b6000806040838503121561164557600080fd5b61164e8361161b565b946020939093013593505050565b60008060006060848603121561167157600080fd5b61167a8461161b565b92506116886020850161161b565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156116c9576116c9611698565b604051601f8501601f19908116603f011681019082821181831017156116f1576116f1611698565b8160405280935085815286868601111561170a57600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121561173657600080fd5b813567ffffffffffffffff81111561174d57600080fd5b8201601f8101841361175e57600080fd5b610f9a848235602084016116ae565b60006020828403121561177f57600080fd5b6115a28261161b565b6000806040838503121561179b57600080fd5b6117a48361161b565b9150602083013580151581146117b957600080fd5b809150509250929050565b600080600080608085870312156117da57600080fd5b6117e38561161b565b93506117f16020860161161b565b925060408501359150606085013567ffffffffffffffff81111561181457600080fd5b8501601f8101871361182557600080fd5b611834878235602084016116ae565b91505092959194509250565b6000806040838503121561185357600080fd5b61185c8361161b565b915061186a6020840161161b565b90509250929050565b600181811c9082168061188757607f821691505b6020821081036118a757634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b601f82111561074c57600081815260208120601f850160051c8101602086101561195a5750805b601f850160051c820191505b8181101561197957828155600101611966565b505050505050565b815167ffffffffffffffff81111561199b5761199b611698565b6119af816119a98454611873565b84611933565b602080601f8311600181146119e457600084156119cc5750858301515b600019600386901b1c1916600185901b178555611979565b600085815260208120601f198616915b82811015611a13578886015182559484019460019091019084016119f4565b5085821015611a315787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b8082018082111561050a5761050a611a41565b6000816000190483118215151615611a8457611a84611a41565b500290565b8181038181111561050a5761050a611a41565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611b21908301846115a9565b9695505050505050565b600060208284031215611b3d57600080fd5b81516115a28161156f56fe697066733a2f2f516d57393438614e34546a6834654c6b41416f386f733141634d32464a6a413436717461456646416e794e597a59697066733a2f2f516d523331663241556f6b433551794c587a4459556a7935745669626b6a625734766f56754d425a66724e565538697066733a2f2f516d646153546146365758705957694c35636b3763736d5479354557487a595647796b4a5a4e3754523935645353697066733a2f2f516d5567644c7650766a754847664d73754b3148326a467067357231514e63384a655779587952774b5038705466a2646970667358221220e2ef3122a6cb2d5c73f6e9c50a0261a53c008746506d8db79d5ea5e188d01d8a64736f6c63430008100033697066733a2f2f516d58584c464265536a5841774168626f31333434774a536a4c676f557266554b394c4535376f56756261525270"; + public static String erc20ContractCode = "0x60806040523480156200001157600080fd5b506040518060400160405280600d81526020017f4157207465737420746f6b656e000000000000000000000000000000000000008152506040518060400160405280600481526020017f415754540000000000000000000000000000000000000000000000000000000081525081600390816200008f9190620004e3565b508060049081620000a19190620004e3565b505050620000e333620000b9620000e960201b60201c565b600a620000c791906200075a565b62989680620000d79190620007ab565b620000f260201b60201c565b620008e2565b60006012905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000164576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015b9062000857565b60405180910390fd5b62000178600083836200025f60201b60201c565b80600260008282546200018c919062000879565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516200023f9190620008c5565b60405180910390a36200025b600083836200026460201b60201c565b5050565b505050565b505050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620002eb57607f821691505b602082108103620003015762000300620002a3565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026200036b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200032c565b6200037786836200032c565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620003c4620003be620003b8846200038f565b62000399565b6200038f565b9050919050565b6000819050919050565b620003e083620003a3565b620003f8620003ef82620003cb565b84845462000339565b825550505050565b600090565b6200040f62000400565b6200041c818484620003d5565b505050565b5b8181101562000444576200043860008262000405565b60018101905062000422565b5050565b601f82111562000493576200045d8162000307565b62000468846200031c565b8101602085101562000478578190505b6200049062000487856200031c565b83018262000421565b50505b505050565b600082821c905092915050565b6000620004b86000198460080262000498565b1980831691505092915050565b6000620004d38383620004a5565b9150826002028217905092915050565b620004ee8262000269565b67ffffffffffffffff8111156200050a576200050962000274565b5b620005168254620002d2565b6200052382828562000448565b600060209050601f8311600181146200055b576000841562000546578287015190505b620005528582620004c5565b865550620005c2565b601f1984166200056b8662000307565b60005b8281101562000595578489015182556001820191506020850194506020810190506200056e565b86831015620005b55784890151620005b1601f891682620004a5565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b6001851115620006585780860481111562000630576200062f620005ca565b5b6001851615620006405780820291505b80810290506200065085620005f9565b945062000610565b94509492505050565b60008262000673576001905062000746565b8162000683576000905062000746565b81600181146200069c5760028114620006a757620006dd565b600191505062000746565b60ff841115620006bc57620006bb620005ca565b5b8360020a915084821115620006d657620006d5620005ca565b5b5062000746565b5060208310610133831016604e8410600b8410161715620007175782820a905083811115620007115762000710620005ca565b5b62000746565b62000726848484600162000606565b9250905081840481111562000740576200073f620005ca565b5b81810290505b9392505050565b600060ff82169050919050565b600062000767826200038f565b915062000774836200074d565b9250620007a37fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848462000661565b905092915050565b6000620007b8826200038f565b9150620007c5836200038f565b9250828202620007d5816200038f565b91508282048414831517620007ef57620007ee620005ca565b5b5092915050565b600082825260208201905092915050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b60006200083f601f83620007f6565b91506200084c8262000807565b602082019050919050565b60006020820190508181036000830152620008728162000830565b9050919050565b600062000886826200038f565b915062000893836200038f565b9250828201905080821115620008ae57620008ad620005ca565b5b92915050565b620008bf816200038f565b82525050565b6000602082019050620008dc6000830184620008b4565b92915050565b61122f80620008f26000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461016857806370a082311461019857806395d89b41146101c8578063a457c2d7146101e6578063a9059cbb14610216578063dd62ed3e14610246576100a9565b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100fc57806323b872dd1461011a578063313ce5671461014a575b600080fd5b6100b6610276565b6040516100c39190610b0c565b60405180910390f35b6100e660048036038101906100e19190610bc7565b610308565b6040516100f39190610c22565b60405180910390f35b61010461032b565b6040516101119190610c4c565b60405180910390f35b610134600480360381019061012f9190610c67565b610335565b6040516101419190610c22565b60405180910390f35b610152610364565b60405161015f9190610cd6565b60405180910390f35b610182600480360381019061017d9190610bc7565b61036d565b60405161018f9190610c22565b60405180910390f35b6101b260048036038101906101ad9190610cf1565b6103a4565b6040516101bf9190610c4c565b60405180910390f35b6101d06103ec565b6040516101dd9190610b0c565b60405180910390f35b61020060048036038101906101fb9190610bc7565b61047e565b60405161020d9190610c22565b60405180910390f35b610230600480360381019061022b9190610bc7565b6104f5565b60405161023d9190610c22565b60405180910390f35b610260600480360381019061025b9190610d1e565b610518565b60405161026d9190610c4c565b60405180910390f35b60606003805461028590610d8d565b80601f01602080910402602001604051908101604052809291908181526020018280546102b190610d8d565b80156102fe5780601f106102d3576101008083540402835291602001916102fe565b820191906000526020600020905b8154815290600101906020018083116102e157829003601f168201915b5050505050905090565b60008061031361059f565b90506103208185856105a7565b600191505092915050565b6000600254905090565b60008061034061059f565b905061034d858285610770565b6103588585856107fc565b60019150509392505050565b60006012905090565b60008061037861059f565b905061039981858561038a8589610518565b6103949190610ded565b6105a7565b600191505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6060600480546103fb90610d8d565b80601f016020809104026020016040519081016040528092919081815260200182805461042790610d8d565b80156104745780601f1061044957610100808354040283529160200191610474565b820191906000526020600020905b81548152906001019060200180831161045757829003601f168201915b5050505050905090565b60008061048961059f565b905060006104978286610518565b9050838110156104dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d390610e93565b60405180910390fd5b6104e982868684036105a7565b60019250505092915050565b60008061050061059f565b905061050d8185856107fc565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610616576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060d90610f25565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610685576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067c90610fb7565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040516107639190610c4c565b60405180910390a3505050565b600061077c8484610518565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146107f657818110156107e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107df90611023565b60405180910390fd5b6107f584848484036105a7565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361086b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610862906110b5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036108da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d190611147565b60405180910390fd5b6108e5838383610a72565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561096b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610962906111d9565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610a599190610c4c565b60405180910390a3610a6c848484610a77565b50505050565b505050565b505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610ab6578082015181840152602081019050610a9b565b60008484015250505050565b6000601f19601f8301169050919050565b6000610ade82610a7c565b610ae88185610a87565b9350610af8818560208601610a98565b610b0181610ac2565b840191505092915050565b60006020820190508181036000830152610b268184610ad3565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610b5e82610b33565b9050919050565b610b6e81610b53565b8114610b7957600080fd5b50565b600081359050610b8b81610b65565b92915050565b6000819050919050565b610ba481610b91565b8114610baf57600080fd5b50565b600081359050610bc181610b9b565b92915050565b60008060408385031215610bde57610bdd610b2e565b5b6000610bec85828601610b7c565b9250506020610bfd85828601610bb2565b9150509250929050565b60008115159050919050565b610c1c81610c07565b82525050565b6000602082019050610c376000830184610c13565b92915050565b610c4681610b91565b82525050565b6000602082019050610c616000830184610c3d565b92915050565b600080600060608486031215610c8057610c7f610b2e565b5b6000610c8e86828701610b7c565b9350506020610c9f86828701610b7c565b9250506040610cb086828701610bb2565b9150509250925092565b600060ff82169050919050565b610cd081610cba565b82525050565b6000602082019050610ceb6000830184610cc7565b92915050565b600060208284031215610d0757610d06610b2e565b5b6000610d1584828501610b7c565b91505092915050565b60008060408385031215610d3557610d34610b2e565b5b6000610d4385828601610b7c565b9250506020610d5485828601610b7c565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610da557607f821691505b602082108103610db857610db7610d5e565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610df882610b91565b9150610e0383610b91565b9250828201905080821115610e1b57610e1a610dbe565b5b92915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000610e7d602583610a87565b9150610e8882610e21565b604082019050919050565b60006020820190508181036000830152610eac81610e70565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000610f0f602483610a87565b9150610f1a82610eb3565b604082019050919050565b60006020820190508181036000830152610f3e81610f02565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b6000610fa1602283610a87565b9150610fac82610f45565b604082019050919050565b60006020820190508181036000830152610fd081610f94565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b600061100d601d83610a87565b915061101882610fd7565b602082019050919050565b6000602082019050818103600083015261103c81611000565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b600061109f602583610a87565b91506110aa82611043565b604082019050919050565b600060208201905081810360008301526110ce81611092565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b6000611131602383610a87565b915061113c826110d5565b604082019050919050565b6000602082019050818103600083015261116081611124565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b60006111c3602683610a87565b91506111ce82611167565b604082019050919050565b600060208201905081810360008301526111f2816111b6565b905091905056fea26469706673582212206637373f9ebc605cdad9359cb179c62d11a616e2ad65618a36fc5bb768793f6364736f6c63430008110033"; } diff --git a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java index e5b8f15f0b..3c519b4965 100644 --- a/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java +++ b/app/src/androidTest/java/com/alphawallet/app/steps/Steps.java @@ -33,6 +33,8 @@ import com.alphawallet.app.util.GetTextAction; import com.alphawallet.app.util.Helper; +import org.hamcrest.core.AllOf; + /** * Every step consists of several operations, step name stands for user perspective actions. * You can add steps as you wish to reuse code between test cases. @@ -102,21 +104,28 @@ public static void ensureTransactionConfirmed() { // onView(withText(R.string.rate_no_thanks)).perform(click()); click(withId(R.string.action_show_tx_details)); - onView(isRoot()).perform(waitUntil(withSubstring("Sent"), 30 * 60)); + onView(isRoot()).perform(waitUntil(withSubstring("Send"), 30 * 60)); pressBack(); } - public static void sendBalanceTo(String receiverAddress, String amountStr) + public static void sendBalanceTo(String tokenSymbol, String amountStr, String receiverAddress) { click(withId(R.id.nav_wallet_text)); ensureBalanceFetched(); - click(withSubstring("ETH")); + click(withSubstring(tokenSymbol)); click(withText("Send")); onView(withHint("0")).perform(replaceText(amountStr)); onView(withHint(R.string.recipient_address)).perform(replaceText(receiverAddress)); click(withId(R.string.action_next)); - Helper.wait(10); - click(withId(R.string.action_confirm)); + try + { + click(withId(R.string.action_confirm)); + } + catch (Error | Exception e) + { + waitForLoadingComplete("Calculating Gas Limit"); + click(withId(R.string.action_confirm)); + } } private static void ensureBalanceFetched() @@ -130,6 +139,7 @@ public static void switchToWallet(String address) gotoSettingsPage(); click(withText("Change / Add Wallet")); onView(withSubstring(address.substring(0, 6))).perform(ViewActions.click()); + waitUntil(withSubstring("Buy"), 30); } public static String getWalletAddress() @@ -166,8 +176,8 @@ public static void importWalletFromSettingsPage(String text) onView(allOf(withId(R.id.edit_text), withParent(withParent(withParent(withId(textId)))))).perform(replaceText(text)); Helper.wait(2); // Avoid error: Error performing a ViewAction! soft keyboard dismissal animation may have been in the way. Retrying once after: 1000 millis click(withId(buttonId)); - waitForLoadingComplete("Handling"); - waitUntil(withSubstring("")); +// waitForLoadingComplete("Handling"); + Helper.wait(5); closeSelectNetworkPage(); } @@ -277,4 +287,27 @@ public static void openOptionsMenu() { openActionBarOverflowOrOptionsMenu(ApplicationProvider.getApplicationContext()); } + + public static void addCustomToken(String contractAddress) + { + //add the token manually since test doesn't seem to work normally + click(withId(R.id.action_my_wallet)); + click(withSubstring("Add / Hide Tokens")); + Helper.wait(1); + click(withId(R.id.action_add)); + Helper.wait(1); + + onView(AllOf.allOf(withId(R.id.edit_text))).perform(replaceText(contractAddress)); + + onView(isRoot()).perform(waitUntil(withId(R.id.select_token), 300)); + + click(withId(R.id.select_token)); + + click(withSubstring("Save")); + + pressBack(); + + //Swipe up + onView(withId(R.id.coordinator)).perform(ViewActions.swipeUp()); + } } diff --git a/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java b/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java index 71414521d3..02b1fae9d8 100644 --- a/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java +++ b/app/src/androidTest/java/com/alphawallet/app/util/EthUtils.java @@ -41,7 +41,7 @@ public static Web3j buildWeb3j(String url) .retryOnConnectionFailure(true) .build(); - AWHttpService svs = new AWHttpService(url, "", client, false); + AWHttpService svs = new AWHttpService(url, url, client, false); return Web3j.build(svs); } From 2e571cd02597f3715ca1c11b06d9a5920126a4fe Mon Sep 17 00:00:00 2001 From: justindg Date: Tue, 22 Nov 2022 20:49:08 -0800 Subject: [PATCH 157/183] Return txHash instead of signature --- .../com/alphawallet/app/viewmodel/WalletConnectViewModel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java index d877ff36e3..4a3b6b118e 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectViewModel.java @@ -247,14 +247,14 @@ public void sendTransaction(final Web3Transaction finalTx, Wallet wallet, long c { disposable = createTransactionInteract .createWithSig(wallet, finalTx.gasPrice, finalTx.gasLimit, finalTx.payload, chainId) - .subscribe(txData -> callback.transactionSuccess(finalTx, txData.signature), + .subscribe(txData -> callback.transactionSuccess(finalTx, txData.txHash), error -> callback.transactionError(finalTx.leafPosition, error)); } else { disposable = createTransactionInteract .createWithSig(wallet, finalTx, chainId) - .subscribe(txData -> callback.transactionSuccess(finalTx, txData.signature), + .subscribe(txData -> callback.transactionSuccess(finalTx, txData.txHash), error -> callback.transactionError(finalTx.leafPosition, error)); } } From 403c798ba1e1376582b68b16525d49b4b760d883 Mon Sep 17 00:00:00 2001 From: justindg Date: Fri, 2 Dec 2022 02:24:26 -0800 Subject: [PATCH 158/183] Removed deprecated networks (Rinkeby, Ropsten, Kovan, Sokol) and references to them (#2989) --- README.md | 2 +- app/src/main/java/com/alphawallet/app/C.java | 4 -- .../app/entity/CustomViewSettings.java | 3 +- .../app/repository/EthereumNetworkBase.java | 42 ++--------------- .../app/service/OpenSeaService.java | 21 +++++---- .../alphawallet/app/web3j/ens/Contracts.java | 8 ---- .../res/drawable/ic_icons_tokens_sokol.xml | 22 --------- app/src/main/res/drawable/ic_kovan.xml | 12 ----- app/src/main/res/drawable/ic_rinkeby.xml | 12 ----- app/src/main/res/drawable/ic_ropsten.xml | 12 ----- app/src/main/res/layout/item_address_icon.xml | 2 +- app/src/main/res/layout/item_token_icon.xml | 4 +- .../res/layout/item_token_icon_square.xml | 4 +- app/src/main/res/values/colors_misc.xml | 4 -- .../java/com/alphawallet/app/ENSTest.java | 4 -- .../token/web/Service/EthRPCNodes.java | 12 ----- .../android/en-US/full_description.txt | 2 +- .../ethereum/EthereumNetworkBase.java | 47 +++++++------------ .../token/entity/MagicLinkInfo.java | 36 -------------- 19 files changed, 40 insertions(+), 213 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_icons_tokens_sokol.xml delete mode 100644 app/src/main/res/drawable/ic_kovan.xml delete mode 100644 app/src/main/res/drawable/ic_rinkeby.xml delete mode 100644 app/src/main/res/drawable/ic_ropsten.xml diff --git a/README.md b/README.md index d2f5a3fc07..c08e48c178 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ AlphaWallet and TokenScript have been used by tokenisation projects like FIFA an ## About AlphaWallet - Features Easy to use and secure open source Ethereum wallet for Android and iOS, with native ERC20, ERC721, ERC1155 and ERC875 support. AlphaWallet supports all Ethereum based networks: Ethereum, xDai, Ethereum Classic, Artis, POA, Binance Smart Chain, Heco, Polygon, Avalanche, Fantom, L2 chains Optimistic and Arbitrum, and Palm. -TestChains: Ropsten, Goerli, Kovan, Rinkeby, Sokol, Binance Test, Heco Test, Fuji (Avalanche test), Fantom Test, Polygon Test, Optimistic and Arbitrum Test, Cronos Test and Palm test. +TestChains: Goerli, Binance Test, Heco Test, Fuji (Avalanche test), Fantom Test, Polygon Test, Optimistic and Arbitrum Test, Cronos Test and Palm test. - Beginner Friendly - Secure Enclave Security diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 4512a8a55a..44745c48d5 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -24,10 +24,6 @@ public abstract class C { public static final String CLASSIC_NETWORK_NAME = "Ethereum Classic"; public static final String POA_NETWORK_NAME = "POA"; public static final String XDAI_NETWORK_NAME = "Gnosis"; - public static final String KOVAN_NETWORK_NAME = "Kovan (Test)"; - public static final String ROPSTEN_NETWORK_NAME = "Ropsten (Test)"; - public static final String SOKOL_NETWORK_NAME = "Sokol (Test)"; - public static final String RINKEBY_NETWORK_NAME = "Rinkeby (Test)"; public static final String GOERLI_NETWORK_NAME = "Görli (Test)"; public static final String ARTIS_SIGMA1_NETWORK = "ARTIS sigma1"; public static final String ARTIS_TAU1_NETWORK = "ARTIS tau1 (Test)"; diff --git a/app/src/main/java/com/alphawallet/app/entity/CustomViewSettings.java b/app/src/main/java/com/alphawallet/app/entity/CustomViewSettings.java index 119b0873ba..cf7042005f 100644 --- a/app/src/main/java/com/alphawallet/app/entity/CustomViewSettings.java +++ b/app/src/main/java/com/alphawallet/app/entity/CustomViewSettings.java @@ -43,8 +43,7 @@ public class CustomViewSettings private static final List lockedChains = Arrays.asList( //EthereumNetworkBase.MAINNET_ID //EG only show Main, xdai, classic and two testnets. Don't allow user to select any others //EthereumNetworkBase.XDAI_ID, - //EthereumNetworkBase.RINKEBY_ID, //You can mix testnets and mainnets, but probably shouldn't as it may result in people getting scammed - //EthereumNetworkBase.GOERLI_ID + //EthereumNetworkBase.GOERLI_ID //You can mix testnets and mainnets, but probably shouldn't as it may result in people getting scammed ); public static final List alwaysVisibleChains = Arrays.asList( diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index da7d5ad0ee..9d9382b70a 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -41,7 +41,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_RPC; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_RPC; -import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MILKOMEDA_C1_RPC; @@ -58,11 +57,8 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.SEPOLIA_TESTNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.SEPOLIA_TESTNET_RPC_URL; -import static com.alphawallet.ethereum.EthereumNetworkBase.SOKOL_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.XDAI_RPC_URL; import android.text.TextUtils; @@ -156,13 +152,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String PALM_TEST_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-testnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); //Deprecated: for now these RPCs still work - public static final String ROPSTEN_RPC_URL = "https://rpc.ankr.com/eth_ropsten"; - public static final String RINKEBY_RPC_URL = "https://rpc.ankr.com/eth_rinkeby"; public static final String ARBITRUM_TESTNET_RPC = FREE_ARBITRUM_TEST_RPC_URL; - public static final String SOKOL_RPC_URL = "https://sokol.poa.network"; //These Networks are no longer running - public static final String KOVAN_RPC_URL = "https://kovan.poa.network"; public static final String OPTIMISTIC_TEST_URL = OPTIMISTIC_TEST_FALLBACK_URL; //Note that AlphaWallet now uses a double node configuration. See class AWHttpService comment 'try primary node'. @@ -199,10 +191,10 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy FANTOM_TEST_ID, IOTEX_TESTNET_ID, FUJI_TEST_ID, POLYGON_TEST_ID, MILKOMEDA_C1_TEST_ID, ARTIS_TAU1_ID, SEPOLIA_TESTNET_ID, AURORA_TESTNET_ID, PALM_TEST_ID, //Deprecated networks - ROPSTEN_ID, RINKEBY_ID, KOVAN_ID, OPTIMISTIC_TEST_ID, SOKOL_ID, ARBITRUM_TEST_ID)); + OPTIMISTIC_TEST_ID, ARBITRUM_TEST_ID)); private static final List deprecatedNetworkList = new ArrayList<>(Arrays.asList( - ROPSTEN_ID, RINKEBY_ID, KOVAN_ID, OPTIMISTIC_TEST_ID, SOKOL_ID, ARBITRUM_TEST_ID)); + OPTIMISTIC_TEST_ID, ARBITRUM_TEST_ID)); // for reset built-in network private static final LongSparseArray builtinNetworkMap = new LongSparseArray() @@ -343,22 +335,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy "https://goerli-rollup-explorer.arbitrum.io/api?")); // Deprecated Networks - put(ROPSTEN_ID, new NetworkInfo(C.ROPSTEN_NETWORK_NAME, C.ETH_SYMBOL, - ROPSTEN_RPC_URL, - "https://ropsten.etherscan.io/tx/", ROPSTEN_ID, - ROPSTEN_RPC_URL, "https://api-ropsten.etherscan.io/api?")); - put(RINKEBY_ID, new NetworkInfo(C.RINKEBY_NETWORK_NAME, C.ETH_SYMBOL, - RINKEBY_RPC_URL, - "https://rinkeby.etherscan.io/tx/", RINKEBY_ID, - RINKEBY_RPC_URL, "https://api-rinkeby.etherscan.io/api?")); - put(KOVAN_ID, new NetworkInfo(C.KOVAN_NETWORK_NAME, C.ETH_SYMBOL, - KOVAN_RPC_URL, - "https://kovan.etherscan.io/tx/", KOVAN_ID, - KOVAN_RPC_URL, "https://api-kovan.etherscan.io/api?")); - put(SOKOL_ID, new NetworkInfo(C.SOKOL_NETWORK_NAME, C.POA_SYMBOL, - SOKOL_RPC_URL, - "https://blockscout.com/poa/sokol/tx/", SOKOL_ID, - SOKOL_RPC_URL, "https://blockscout.com/poa/sokol/api?")); put(OPTIMISTIC_TEST_ID, new NetworkInfo(C.OPTIMISTIC_TEST_NETWORK, C.ETH_SYMBOL, OPTIMISTIC_TEST_URL, "https://kovan-optimistic.etherscan.io/tx/", OPTIMISTIC_TEST_ID, OPTIMISTIC_TEST_FALLBACK_URL, @@ -378,12 +354,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy { { put(MAINNET_ID, R.drawable.ic_token_eth); - put(KOVAN_ID, R.drawable.ic_kovan); - put(ROPSTEN_ID, R.drawable.ic_ropsten); - put(RINKEBY_ID, R.drawable.ic_rinkeby); put(CLASSIC_ID, R.drawable.ic_icons_network_etc); //classic_logo put(POA_ID, R.drawable.ic_poa_logo); - put(SOKOL_ID, R.drawable.ic_icons_tokens_sokol); put(GNOSIS_ID, R.drawable.ic_icons_network_gnosis); put(GOERLI_ID, R.drawable.ic_goerli); put(ARTIS_SIGMA1_ID, R.drawable.ic_artis_sigma_logo); @@ -424,12 +396,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy { { put(MAINNET_ID, R.drawable.ic_icons_network_eth); - put(KOVAN_ID, R.drawable.ic_kovan); - put(ROPSTEN_ID, R.drawable.ic_ropsten); - put(RINKEBY_ID, R.drawable.ic_rinkeby); put(CLASSIC_ID, R.drawable.ic_icons_network_etc); put(POA_ID, R.drawable.ic_icons_network_poa); - put(SOKOL_ID, R.drawable.ic_icons_tokens_sokol); put(GNOSIS_ID, R.drawable.ic_icons_network_gnosis); put(GOERLI_ID, R.drawable.ic_goerli); put(ARTIS_SIGMA1_ID, R.drawable.ic_icons_network_artis); @@ -470,12 +438,8 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy { { put(MAINNET_ID, R.color.mainnet); - put(KOVAN_ID, R.color.kovan); - put(ROPSTEN_ID, R.color.ropsten); - put(RINKEBY_ID, R.color.rinkeby); put(CLASSIC_ID, R.color.classic); put(POA_ID, R.color.poa); - put(SOKOL_ID, R.color.sokol); put(GNOSIS_ID, R.color.xdai); put(GOERLI_ID, R.color.goerli); put(ARTIS_SIGMA1_ID, R.color.artis_sigma1); @@ -521,7 +485,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy //These chains don't allow custom gas private static final List hasLockedGas = Arrays.asList(OPTIMISTIC_MAIN_ID, OPTIMISTIC_TEST_ID, ARBITRUM_MAIN_ID, ARBITRUM_TEST_ID, KLAYTN_ID, KLAYTN_BAOBAB_ID); - private static final List hasOpenSeaAPI = Arrays.asList(MAINNET_ID, POLYGON_ID, RINKEBY_ID); + private static final List hasOpenSeaAPI = Arrays.asList(MAINNET_ID, POLYGON_ID); private static final LongSparseArray blockGasLimit = new LongSparseArray() { diff --git a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java index 376ae9e317..9ec14a1a06 100644 --- a/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java +++ b/app/src/main/java/com/alphawallet/app/service/OpenSeaService.java @@ -66,7 +66,10 @@ private Request buildRequest(long networkId, String api) .addHeader("Content-Type", "application/json"); String apiKey = KeyProviderFactory.get().getOpenSeaKey(); - if (networkId != EthereumNetworkBase.RINKEBY_ID && !TextUtils.isEmpty(apiKey) && !apiKey.equals("...")) + if (!TextUtils.isEmpty(apiKey) + && !apiKey.equals("...") + // && networkId != EthereumNetworkBase.RINKEBY_ID + ) { requestB.addHeader("X-API-KEY", apiKey); } @@ -360,10 +363,10 @@ public String fetchAssets(long networkId, String address, int offset) { api = C.OPENSEA_ASSETS_API_MAINNET; } - else if (networkId == EthereumNetworkBase.RINKEBY_ID) - { - api = C.OPENSEA_ASSETS_API_RINKEBY; - } +// else if (networkId == EthereumNetworkBase.RINKEBY_ID) +// { +// api = C.OPENSEA_ASSETS_API_RINKEBY; +// } else if (networkId == EthereumNetworkBase.POLYGON_ID) { api = C.OPENSEA_ASSETS_API_MATIC; @@ -386,10 +389,10 @@ public String fetchAsset(long networkId, String contractAddress, String tokenId) { api = C.OPENSEA_SINGLE_ASSET_API_MAINNET + contractAddress + "/" + tokenId; } - else if (networkId == EthereumNetworkBase.RINKEBY_ID) - { - api = C.OPENSEA_SINGLE_ASSET_API_RINKEBY + contractAddress + "/" + tokenId; - } +// else if (networkId == EthereumNetworkBase.RINKEBY_ID) +// { +// api = C.OPENSEA_SINGLE_ASSET_API_RINKEBY + contractAddress + "/" + tokenId; +// } else if (networkId == EthereumNetworkBase.POLYGON_ID) { api = C.OPENSEA_SINGLE_ASSET_API_MATIC + contractAddress + "/" + tokenId; diff --git a/app/src/main/java/com/alphawallet/app/web3j/ens/Contracts.java b/app/src/main/java/com/alphawallet/app/web3j/ens/Contracts.java index bb9766db73..7076608d12 100644 --- a/app/src/main/java/com/alphawallet/app/web3j/ens/Contracts.java +++ b/app/src/main/java/com/alphawallet/app/web3j/ens/Contracts.java @@ -14,24 +14,16 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; /** ENS registry contract addresses. */ public class Contracts { public static final String MAINNET = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; - public static final String ROPSTEN = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; - public static final String RINKEBY = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; public static final String GOERLI = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; public static String resolveRegistryContract(long chainId) { if (chainId == MAINNET_ID) { return MAINNET; - } else if (chainId == ROPSTEN_ID) { - return ROPSTEN; - } else if (chainId == RINKEBY_ID) { - return RINKEBY; } else if (chainId == GOERLI_ID) { return GOERLI; } else { diff --git a/app/src/main/res/drawable/ic_icons_tokens_sokol.xml b/app/src/main/res/drawable/ic_icons_tokens_sokol.xml deleted file mode 100644 index 666195478c..0000000000 --- a/app/src/main/res/drawable/ic_icons_tokens_sokol.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - diff --git a/app/src/main/res/drawable/ic_kovan.xml b/app/src/main/res/drawable/ic_kovan.xml deleted file mode 100644 index e68cb4f221..0000000000 --- a/app/src/main/res/drawable/ic_kovan.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_rinkeby.xml b/app/src/main/res/drawable/ic_rinkeby.xml deleted file mode 100644 index 9ce4a35d58..0000000000 --- a/app/src/main/res/drawable/ic_rinkeby.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_ropsten.xml b/app/src/main/res/drawable/ic_ropsten.xml deleted file mode 100644 index 0fb5615cc6..0000000000 --- a/app/src/main/res/drawable/ic_ropsten.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/layout/item_address_icon.xml b/app/src/main/res/layout/item_address_icon.xml index 81f104286c..86db78c3e7 100644 --- a/app/src/main/res/layout/item_address_icon.xml +++ b/app/src/main/res/layout/item_address_icon.xml @@ -111,7 +111,7 @@ app:layout_constraintEnd_toStartOf="@id/guidelineInnerRight" app:layout_constraintStart_toEndOf="@id/guidelineInnerLeft" app:layout_constraintTop_toTopOf="@id/guidelineTop" - tools:src="@drawable/ic_ropsten" /> + tools:src="@drawable/ic_goerli" /> + tools:src="@drawable/ic_goerli" /> + tools:src="@drawable/ic_goerli" /> #2986AF - #FF4A8D - #70578D - #F6C343 - #6B35A2 #48A9A6 #378937 #5838A3 diff --git a/app/src/test/java/com/alphawallet/app/ENSTest.java b/app/src/test/java/com/alphawallet/app/ENSTest.java index 2eecd8769a..bfd6e8417d 100644 --- a/app/src/test/java/com/alphawallet/app/ENSTest.java +++ b/app/src/test/java/com/alphawallet/app/ENSTest.java @@ -2,8 +2,6 @@ import static com.alphawallet.app.web3j.ens.NameHash.nameHash; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; import static org.junit.Assert.assertEquals; import com.alphawallet.app.service.AWHttpService; @@ -55,8 +53,6 @@ public static Web3j getWeb3j(AWHttpService service) @Test public void testResolveRegistryContract() { assertEquals(Contracts.resolveRegistryContract(MAINNET_ID), (Contracts.MAINNET)); - assertEquals(Contracts.resolveRegistryContract(ROPSTEN_ID), (Contracts.ROPSTEN)); - assertEquals(Contracts.resolveRegistryContract(RINKEBY_ID), (Contracts.RINKEBY)); } @Test diff --git a/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java b/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java index e1fee2e176..9b6bbb1f77 100644 --- a/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java +++ b/dmz/src/main/java/com/alphawallet/token/web/Service/EthRPCNodes.java @@ -10,10 +10,6 @@ public class EthRPCNodes private static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; private static final String XDAI_RPC_URL = EthereumNetworkBase.XDAI_RPC_URL; private static final String POA_RPC_URL = "https://core.poa.network/"; - private static final String ROPSTEN_RPC_URL = "https://ropsten.infura.io/v3/" + getInfuraKey(); - private static final String RINKEBY_RPC_URL = "https://rinkeby.infura.io/v3/" + getInfuraKey(); - private static final String KOVAN_RPC_URL = "https://kovan.infura.io/v3/" + getInfuraKey(); - private static final String SOKOL_RPC_URL = "https://sokol.poa.network"; private static final String GOERLI_RPC_URL = "https://goerli.infura.io/v3/" + getInfuraKey(); private static final String ARTIS_SIGMA1_RPC_URL = "https://rpc.sigma1.artis.network"; private static final String ARTIS_TAU1_RPC_URL = "https://rpc.tau1.artis.network"; @@ -23,16 +19,8 @@ public static String getNodeURLByNetworkId(long networkId) { switch ((int)networkId) { case (int)EthereumNetworkBase.MAINNET_ID: return MAINNET_RPC_URL; - case (int)EthereumNetworkBase.KOVAN_ID: - return KOVAN_RPC_URL; - case (int)EthereumNetworkBase.ROPSTEN_ID: - return ROPSTEN_RPC_URL; - case (int)EthereumNetworkBase.RINKEBY_ID: - return RINKEBY_RPC_URL; case (int)EthereumNetworkBase.POA_ID: return POA_RPC_URL; - case (int)EthereumNetworkBase.SOKOL_ID: - return SOKOL_RPC_URL; case (int)EthereumNetworkBase.CLASSIC_ID: return CLASSIC_RPC_URL; case (int)EthereumNetworkBase.GNOSIS_ID: diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 218d08614d..dedef211b7 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -1,4 +1,4 @@ -AlphaWallet is an easy to use and secure Ethereum wallet with native ERC20, ERC721 and ERC875 support. AlphaWallet supports all Ethereum based networks, Ethereum, xDai, Ethereum Classic, Artis, POA, Ropsten, Goerli, Kovan, Rinkeby and Sokol. +AlphaWallet is an easy to use and secure Ethereum wallet with native ERC20, ERC721 and ERC875 support. AlphaWallet supports all Ethereum based networks, Ethereum, xDai, Ethereum Classic, Artis, POA, and Goerli. Focus on Defi: - Shows comprehensive breakdown on Token transactions & swaps. diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 752d79cce4..1b37324a0d 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -7,14 +7,11 @@ import java.util.LinkedHashMap; import java.util.Map; -public abstract class EthereumNetworkBase { // implements EthereumNetworkRepositoryType +public abstract class EthereumNetworkBase +{ // implements EthereumNetworkRepositoryType public static final long MAINNET_ID = 1; public static final long CLASSIC_ID = 61; public static final long POA_ID = 99; - public static final long KOVAN_ID = 42; - public static final long ROPSTEN_ID = 3; - public static final long SOKOL_ID = 77; - public static final long RINKEBY_ID = 4; public static final long GNOSIS_ID = 100; public static final long GOERLI_ID = 5; public static final long ARTIS_SIGMA1_ID = 246529; @@ -54,10 +51,6 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; public static final String XDAI_RPC_URL = "https://rpc.ankr.com/gnosis"; public static final String POA_RPC_URL = "https://core.poa.network/"; - public static final String ROPSTEN_RPC_URL = "https://ropsten.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; - public static final String RINKEBY_RPC_URL = "https://rinkeby.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; - public static final String KOVAN_RPC_URL = "https://kovan.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; - public static final String SOKOL_RPC_URL = "https://sokol.poa.network"; public static final String GOERLI_RPC_URL = "https://goerli.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; public static final String ARTIS_SIGMA1_RPC_URL = "https://rpc.sigma1.artis.network"; public static final String ARTIS_TAU1_RPC_URL = "https://rpc.tau1.artis.network"; @@ -91,7 +84,8 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit public static final String IOTEX_MAINNET_RPC_URL = "https://babel-api.mainnet.iotex.io"; public static final String IOTEX_TESTNET_RPC_URL = "https://babel-api.testnet.iotex.io"; - static Map networkMap = new LinkedHashMap() { + static Map networkMap = new LinkedHashMap() + { { put(MAINNET_ID, new NetworkInfo("Ethereum", "ETH", MAINNET_RPC_URL, "https://etherscan.io/tx/", MAINNET_ID, false)); @@ -103,14 +97,6 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit POA_ID, false)); put(ARTIS_SIGMA1_ID, new NetworkInfo("ARTIS sigma1", "ATS", ARTIS_SIGMA1_RPC_URL, "https://explorer.sigma1.artis.network/tx/", ARTIS_SIGMA1_ID, false)); - put(KOVAN_ID, new NetworkInfo("Kovan (Test)", "ETH", KOVAN_RPC_URL, "https://kovan.etherscan.io/tx/", - KOVAN_ID, false)); - put(ROPSTEN_ID, new NetworkInfo("Ropsten (Test)", "ETH", ROPSTEN_RPC_URL, "https://ropsten.etherscan.io/tx/", - ROPSTEN_ID, false)); - put(SOKOL_ID, new NetworkInfo("Sokol (Test)", "POA", SOKOL_RPC_URL, "https://blockscout.com/poa/sokol/tx/", - SOKOL_ID, false)); - put(RINKEBY_ID, new NetworkInfo("Rinkeby (Test)", "ETH", RINKEBY_RPC_URL, "https://rinkeby.etherscan.io/tx/", - RINKEBY_ID, false)); put(GOERLI_ID, new NetworkInfo("Görli (Test)", "GÖETH", GOERLI_RPC_URL, "https://goerli.etherscan.io/tx/", GOERLI_ID, false)); put(ARTIS_TAU1_ID, new NetworkInfo("ARTIS tau1 (Test)", "ATS", ARTIS_TAU1_RPC_URL, "https://explorer.tau1.artis.network/tx/", @@ -139,34 +125,34 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit put(POLYGON_TEST_ID, new NetworkInfo("Mumbai (Test)", "POLY", MUMBAI_TEST_RPC_URL, "https://mumbai.polygonscan.com/tx/", POLYGON_TEST_ID, false)); - put(OPTIMISTIC_MAIN_ID, new NetworkInfo("Optimistic","ETH", OPTIMISTIC_MAIN_FALLBACK_URL, "https://optimistic.etherscan.io/tx/", + put(OPTIMISTIC_MAIN_ID, new NetworkInfo("Optimistic", "ETH", OPTIMISTIC_MAIN_FALLBACK_URL, "https://optimistic.etherscan.io/tx/", OPTIMISTIC_MAIN_ID, false)); put(OPTIMISTIC_TEST_ID, new NetworkInfo("Optimistic (Test)", "ETH", OPTIMISTIC_TEST_FALLBACK_URL, "https://kovan-optimistic.etherscan.io/tx/", OPTIMISTIC_TEST_ID, false)); put(CRONOS_MAIN_ID, new NetworkInfo("Cronos (Beta)", "CRO", CRONOS_MAIN_RPC_URL, "https://cronoscan.com/tx", CRONOS_MAIN_ID, false)); put(CRONOS_TEST_ID, new NetworkInfo("Cronos (Test)", "tCRO", CRONOS_TEST_URL, "https://testnet.cronoscan.com/tx/", CRONOS_TEST_ID, false)); - put(ARBITRUM_MAIN_ID, new NetworkInfo("Arbitrum One","AETH", ARBITRUM_RPC_URL, "https://arbiscan.io/tx/", + put(ARBITRUM_MAIN_ID, new NetworkInfo("Arbitrum One", "AETH", ARBITRUM_RPC_URL, "https://arbiscan.io/tx/", ARBITRUM_MAIN_ID, false)); put(ARBITRUM_TEST_ID, new NetworkInfo("Arbitrum Test", "ARETH", ARBITRUM_TEST_RPC_URL, "https://rinkeby-explorer.arbitrum.io/tx/", ARBITRUM_TEST_ID, false)); - put(PALM_ID, new NetworkInfo("PALM","PALM", PALM_RPC_URL, "https://explorer.palm.io/tx/", + put(PALM_ID, new NetworkInfo("PALM", "PALM", PALM_RPC_URL, "https://explorer.palm.io/tx/", PALM_ID, false)); put(PALM_TEST_ID, new NetworkInfo("PALM (Test)", "PALM", PALM_TEST_RPC_URL, "https://explorer.palm-uat.xyz/tx/", PALM_TEST_ID, false)); - put(KLAYTN_ID, new NetworkInfo("Klaytn Cypress","KLAY", KLAYTN_RPC, "https://scope.klaytn.com/tx/", + put(KLAYTN_ID, new NetworkInfo("Klaytn Cypress", "KLAY", KLAYTN_RPC, "https://scope.klaytn.com/tx/", KLAYTN_ID, false)); - put(KLAYTN_BAOBAB_ID, new NetworkInfo("Klaytn Baobab (Test)","KLAY", KLAYTN_BAOBAB_RPC, "https://baobab.scope.klaytn.com/tx/", + put(KLAYTN_BAOBAB_ID, new NetworkInfo("Klaytn Baobab (Test)", "KLAY", KLAYTN_BAOBAB_RPC, "https://baobab.scope.klaytn.com/tx/", KLAYTN_BAOBAB_ID, false)); - put(AURORA_MAINNET_ID, new NetworkInfo("Aurora","ETH", AURORA_MAINNET_RPC_URL, "https://aurorascan.dev/tx/", + put(AURORA_MAINNET_ID, new NetworkInfo("Aurora", "ETH", AURORA_MAINNET_RPC_URL, "https://aurorascan.dev/tx/", AURORA_MAINNET_ID, false)); - put(AURORA_TESTNET_ID, new NetworkInfo("Aurora (Test)","ETH", AURORA_TESTNET_RPC_URL, "https://testnet.aurorascan.dev/tx/", + put(AURORA_TESTNET_ID, new NetworkInfo("Aurora (Test)", "ETH", AURORA_TESTNET_RPC_URL, "https://testnet.aurorascan.dev/tx/", AURORA_TESTNET_ID, false)); - put(MILKOMEDA_C1_ID, new NetworkInfo("Milkomeda Cardano","milkADA", MILKOMEDA_C1_RPC, "https://explorer-mainnet-cardano-evm.c1.milkomeda.com/tx/", + put(MILKOMEDA_C1_ID, new NetworkInfo("Milkomeda Cardano", "milkADA", MILKOMEDA_C1_RPC, "https://explorer-mainnet-cardano-evm.c1.milkomeda.com/tx/", MILKOMEDA_C1_ID, false)); - put(MILKOMEDA_C1_TEST_ID, new NetworkInfo("Milkomeda Cardano (Test)","milktADA", MILKOMEDA_C1_TEST_RPC, "https://explorer-devnet-cardano-evm.c1.milkomeda.com/tx/", + put(MILKOMEDA_C1_TEST_ID, new NetworkInfo("Milkomeda Cardano (Test)", "milktADA", MILKOMEDA_C1_TEST_RPC, "https://explorer-devnet-cardano-evm.c1.milkomeda.com/tx/", MILKOMEDA_C1_TEST_ID, false)); put(SEPOLIA_TESTNET_ID, new NetworkInfo("Sepolia (Test)", "ETH", SEPOLIA_TESTNET_RPC_URL, "https://sepolia.etherscan.io/tx/", SEPOLIA_TESTNET_ID, false)); @@ -174,14 +160,15 @@ public abstract class EthereumNetworkBase { // implements EthereumNetworkReposit OPTIMISM_GOERLI_TEST_ID, false)); put(ARBITRUM_GOERLI_TEST_ID, new NetworkInfo("Arbitrum Goerli (Test)", "AGOR", OPTIMISM_GOERLI_TESTNET_FALLBACK_RPC_URL, "https://goerli-rollup-explorer.arbitrum.io/tx/", ARBITRUM_GOERLI_TEST_ID, false)); - put(IOTEX_MAINNET_ID, new NetworkInfo("IoTeX","IOTX", IOTEX_MAINNET_RPC_URL, "https://iotexscan.io/tx/", + put(IOTEX_MAINNET_ID, new NetworkInfo("IoTeX", "IOTX", IOTEX_MAINNET_RPC_URL, "https://iotexscan.io/tx/", IOTEX_MAINNET_ID, false)); - put(IOTEX_TESTNET_ID, new NetworkInfo("IoTeX (Test)","IOTX", IOTEX_TESTNET_RPC_URL, "https://testnet.iotexscan.io/tx/", + put(IOTEX_TESTNET_ID, new NetworkInfo("IoTeX (Test)", "IOTX", IOTEX_TESTNET_RPC_URL, "https://testnet.iotexscan.io/tx/", IOTEX_TESTNET_ID, false)); } }; - public static NetworkInfo getNetworkByChain(long chainId) { + public static NetworkInfo getNetworkByChain(long chainId) + { return networkMap.get(chainId); } diff --git a/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java b/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java index 86f932f30f..e6c5ce406b 100644 --- a/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java +++ b/lib/src/main/java/com/alphawallet/token/entity/MagicLinkInfo.java @@ -7,12 +7,8 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_TAU1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.CLASSIC_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.GOERLI_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.KOVAN_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.RINKEBY_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ROPSTEN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.SOKOL_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.GNOSIS_ID; /** @@ -26,11 +22,7 @@ public class MagicLinkInfo private static final String legacyMagicLinkDomain = "app.awallet.io"; private static final String classicMagicLinkDomain = "classic.aw.app"; private static final String callistoMagicLinkDomain = "callisto.aw.app"; - private static final String kovanMagicLinkDomain = "kovan.aw.app"; - private static final String ropstenMagicLinkDomain = "ropsten.aw.app"; - private static final String rinkebyMagicLinkDomain = "rinkeby.aw.app"; private static final String poaMagicLinkDomain = "poa.aw.app"; - private static final String sokolMagicLinkDomain = "sokol.aw.app"; private static final String xDaiMagicLinkDomain = "xdai.aw.app"; private static final String goerliMagicLinkDomain = "goerli.aw.app"; private static final String artisSigma1MagicLinkDomain = "artissigma1.aw.app"; @@ -41,11 +33,7 @@ public class MagicLinkInfo private static final String mainNetEtherscan = "https://cn.etherscan.com/"; private static final String classicEtherscan = "https://blockscout.com/etc/mainnet/"; private static final String callistoEtherscan = "https://etherscan.io/"; //TODO: determine callisto etherscan - private static final String kovanEtherscan = "https://kovan.etherscan.io/"; - private static final String ropstenEtherscan = "https://ropsten.etherscan.io/"; - private static final String rinkebyEtherscan = "https://rinkeby.etherscan.io/"; private static final String poaEtherscan = "https://blockscout.com/poa/core/"; - private static final String sokolEtherscan = "https://blockscout.com/poa/sokol/"; private static final String xDaiEtherscan = "https://blockscout.com/poa/dai/"; private static final String goerliEtherscan = "https://goerli.etherscan.io/"; private static final String artisSigma1Etherscan = "https://explorer.sigma1.artis.network/"; @@ -70,16 +58,8 @@ public static String getMagicLinkDomainFromNetworkId(long networkId) { case (int)MAINNET_ID: default: return mainnetMagicLinkDomain; - case (int)KOVAN_ID: - return kovanMagicLinkDomain; - case (int)ROPSTEN_ID: - return ropstenMagicLinkDomain; - case (int)RINKEBY_ID: - return rinkebyMagicLinkDomain; case (int)POA_ID: return poaMagicLinkDomain; - case (int)SOKOL_ID: - return sokolMagicLinkDomain; case (int)CLASSIC_ID: return classicMagicLinkDomain; case (int) GNOSIS_ID: @@ -104,16 +84,8 @@ public static long getNetworkIdFromDomain(String domain) { return MAINNET_ID; case classicMagicLinkDomain: return CLASSIC_ID; - case kovanMagicLinkDomain: - return KOVAN_ID; - case ropstenMagicLinkDomain: - return ROPSTEN_ID; - case rinkebyMagicLinkDomain: - return RINKEBY_ID; case poaMagicLinkDomain: return POA_ID; - case sokolMagicLinkDomain: - return SOKOL_ID; case xDaiMagicLinkDomain: return GNOSIS_ID; case goerliMagicLinkDomain: @@ -131,16 +103,8 @@ public static String getEtherscanURLbyNetwork(long networkId) { case (int)MAINNET_ID: default: return mainNetEtherscan; - case (int)KOVAN_ID: - return kovanEtherscan; - case (int)ROPSTEN_ID: - return ropstenEtherscan; - case (int)RINKEBY_ID: - return rinkebyEtherscan; case (int)POA_ID: return poaEtherscan; - case (int)SOKOL_ID: - return sokolEtherscan; case (int)CLASSIC_ID: return classicEtherscan; case (int) GNOSIS_ID: From 81972c67f47b77818bd57461b5bd5b0fc51d0c78 Mon Sep 17 00:00:00 2001 From: justindg Date: Mon, 5 Dec 2022 22:18:28 -0800 Subject: [PATCH 159/183] Remove old optimistic and arbitrum testnets (#2991) --- app/src/main/java/com/alphawallet/app/C.java | 3 -- .../app/repository/EthereumNetworkBase.java | 36 +++---------------- .../ethereum/EthereumNetworkBase.java | 8 ----- 3 files changed, 5 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/C.java b/app/src/main/java/com/alphawallet/app/C.java index 44745c48d5..5bbb890f21 100644 --- a/app/src/main/java/com/alphawallet/app/C.java +++ b/app/src/main/java/com/alphawallet/app/C.java @@ -38,10 +38,8 @@ public abstract class C { public static final String POLYGON_NETWORK = "Polygon"; public static final String POLYGON_TEST_NETWORK = "Mumbai (Test)"; public static final String OPTIMISTIC_NETWORK = "Optimistic"; - public static final String OPTIMISTIC_TEST_NETWORK = "Optimistic (Test)"; public static final String CRONOS_MAIN_NETWORK = "Cronos"; public static final String CRONOS_TEST_NETWORK = "Cronos (Test)"; - public static final String ARBITRUM_TEST_NETWORK = "Arbitrum (Test)"; public static final String ARBITRUM_ONE_NETWORK = "Arbitrum One"; public static final String PALM_NAME = "PALM"; public static final String PALM_TEST_NAME = "PALM (Test)"; @@ -82,7 +80,6 @@ public abstract class C { public static final String CRONOS_SYMBOL = "CRO"; public static final String CRONOS_TEST_SYMBOL = "tCRO"; public static final String ARBITRUM_SYMBOL = "AETH"; - public static final String ARBITRUM_TEST_SYMBOL = "ARETH"; public static final String PALM_SYMBOL = "PALM"; public static final String KLAYTN_SYMBOL = "KLAY"; public static final String IOTEX_SYMBOL = "IOTX"; diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 9d9382b70a..07492871fc 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -7,7 +7,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_SIGMA1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.ARTIS_TAU1_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_MAINNET_ID; @@ -50,8 +49,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISM_GOERLI_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_FALLBACK_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_TEST_FALLBACK_URL; -import static com.alphawallet.ethereum.EthereumNetworkBase.OPTIMISTIC_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.PALM_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POA_ID; @@ -117,7 +114,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String FREE_ARBITRUM_RPC_URL = "https://arbitrum.public-rpc.com"; public static final String FREE_GOERLI_RPC_URL = "https://rpc.ankr.com/eth_goerli"; public static final String FREE_MUMBAI_RPC_URL = "https://rpc-mumbai.maticvigil.com"; - public static final String FREE_ARBITRUM_TEST_RPC_URL = "https://rinkeby.arbitrum.io/rpc"; public static final String FREE_PALM_RPC_URL = "https://palm-mainnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b"; public static final String FREE_PALM_TEST_RPC_URL = "https://palm-testnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b"; public static final String FREE_CRONOS_MAIN_BETA_RPC_URL = "https://evm.cronos.org"; @@ -151,12 +147,6 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy public static final String PALM_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-mainnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); public static final String PALM_TEST_RPC_FALLBACK_URL = usesProductionKey ? FREE_PALM_RPC_URL : "https://palm-testnet.infura.io/v3/" + keyProvider.getSecondaryInfuraKey(); - //Deprecated: for now these RPCs still work - public static final String ARBITRUM_TESTNET_RPC = FREE_ARBITRUM_TEST_RPC_URL; - - //These Networks are no longer running - public static final String OPTIMISTIC_TEST_URL = OPTIMISTIC_TEST_FALLBACK_URL; - //Note that AlphaWallet now uses a double node configuration. See class AWHttpService comment 'try primary node'. //If you supply a main RPC and secondary it will try the secondary if the primary node times out after 10 seconds. //See the declaration of NetworkInfo - it has a member backupNodeUrl. Put your secondary node here. @@ -189,12 +179,11 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy private static final List testnetList = new ArrayList<>(Arrays.asList( GOERLI_ID, BINANCE_TEST_ID, HECO_TEST_ID, CRONOS_TEST_ID, OPTIMISM_GOERLI_TEST_ID, ARBITRUM_GOERLI_TEST_ID, KLAYTN_BAOBAB_ID, FANTOM_TEST_ID, IOTEX_TESTNET_ID, FUJI_TEST_ID, POLYGON_TEST_ID, MILKOMEDA_C1_TEST_ID, ARTIS_TAU1_ID, - SEPOLIA_TESTNET_ID, AURORA_TESTNET_ID, PALM_TEST_ID, - //Deprecated networks - OPTIMISTIC_TEST_ID, ARBITRUM_TEST_ID)); + SEPOLIA_TESTNET_ID, AURORA_TESTNET_ID, PALM_TEST_ID)); private static final List deprecatedNetworkList = new ArrayList<>(Arrays.asList( - OPTIMISTIC_TEST_ID, ARBITRUM_TEST_ID)); + // Add deprecated testnet IDs here + )); // for reset built-in network private static final LongSparseArray builtinNetworkMap = new LongSparseArray() @@ -334,15 +323,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy "https://goerli-rollup-explorer.arbitrum.io/tx/", ARBITRUM_GOERLI_TEST_ID, ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL, "https://goerli-rollup-explorer.arbitrum.io/api?")); - // Deprecated Networks - put(OPTIMISTIC_TEST_ID, new NetworkInfo(C.OPTIMISTIC_TEST_NETWORK, C.ETH_SYMBOL, - OPTIMISTIC_TEST_URL, - "https://kovan-optimistic.etherscan.io/tx/", OPTIMISTIC_TEST_ID, OPTIMISTIC_TEST_FALLBACK_URL, - "https://api-kovan-optimistic.etherscan.io/api?")); - put(ARBITRUM_TEST_ID, new NetworkInfo(C.ARBITRUM_TEST_NETWORK, C.ARBITRUM_TEST_SYMBOL, - ARBITRUM_TESTNET_RPC, - "https://testnet.arbiscan.io/tx/", ARBITRUM_TEST_ID, ARBITRUM_FALLBACK_TESTNET_RPC, - "https://testnet.arbiscan.io/api?")); //no transaction API + // Add deprecated networks after this line } }; @@ -371,11 +352,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(POLYGON_ID, R.drawable.ic_icons_polygon); put(POLYGON_TEST_ID, R.drawable.ic_icons_tokens_mumbai); put(OPTIMISTIC_MAIN_ID, R.drawable.ic_optimism_logo); - put(OPTIMISTIC_TEST_ID, R.drawable.ic_optimism_testnet_logo); put(CRONOS_MAIN_ID, R.drawable.ic_cronos_mainnet); put(CRONOS_TEST_ID, R.drawable.ic_cronos); put(ARBITRUM_MAIN_ID, R.drawable.ic_icons_arbitrum); - put(ARBITRUM_TEST_ID, R.drawable.ic_icons_arbitrum_test); put(PALM_ID, R.drawable.ic_icons_network_palm); put(PALM_TEST_ID, R.drawable.palm_logo_test); put(KLAYTN_ID, R.drawable.ic_klaytn_network_logo); @@ -413,11 +392,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(POLYGON_ID, R.drawable.ic_icons_network_polygon); put(POLYGON_TEST_ID, R.drawable.ic_icons_tokens_mumbai); put(OPTIMISTIC_MAIN_ID, R.drawable.ic_icons_network_optimism); - put(OPTIMISTIC_TEST_ID, R.drawable.ic_optimism_testnet_logo); put(CRONOS_MAIN_ID, R.drawable.ic_cronos_mainnet); put(CRONOS_TEST_ID, R.drawable.ic_cronos); put(ARBITRUM_MAIN_ID, R.drawable.ic_icons_network_arbitrum); - put(ARBITRUM_TEST_ID, R.drawable.ic_icons_arbitrum_test); put(PALM_ID, R.drawable.ic_icons_network_palm); put(PALM_TEST_ID, R.drawable.palm_logo_test); put(KLAYTN_ID, R.drawable.ic_klaytn_network_logo); @@ -455,11 +432,9 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy put(POLYGON_ID, R.color.polygon_main); put(POLYGON_TEST_ID, R.color.polygon_test); put(OPTIMISTIC_MAIN_ID, R.color.optimistic_main); - put(OPTIMISTIC_TEST_ID, R.color.optimistic_test); put(CRONOS_MAIN_ID, R.color.cronos_main); put(CRONOS_TEST_ID, R.color.cronos_test); put(ARBITRUM_MAIN_ID, R.color.arbitrum_main); - put(ARBITRUM_TEST_ID, R.color.arbitrum_test); put(PALM_ID, R.color.palm_main); put(PALM_TEST_ID, R.color.palm_test); put(KLAYTN_ID, R.color.klaytn_main); @@ -483,7 +458,7 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy private static final List hasGasOracleAPI = Arrays.asList(MAINNET_ID, HECO_ID, BINANCE_MAIN_ID, POLYGON_ID); //These chains don't allow custom gas - private static final List hasLockedGas = Arrays.asList(OPTIMISTIC_MAIN_ID, OPTIMISTIC_TEST_ID, ARBITRUM_MAIN_ID, ARBITRUM_TEST_ID, KLAYTN_ID, KLAYTN_BAOBAB_ID); + private static final List hasLockedGas = Arrays.asList(OPTIMISTIC_MAIN_ID, ARBITRUM_MAIN_ID, KLAYTN_ID, KLAYTN_BAOBAB_ID); private static final List hasOpenSeaAPI = Arrays.asList(MAINNET_ID, POLYGON_ID); @@ -579,7 +554,6 @@ public boolean hasLockedGas(long chainId) { { put(OPTIMISTIC_MAIN_ID, "0x4200000000000000000000000000000000000006"); - put(OPTIMISTIC_TEST_ID, "0x4200000000000000000000000000000000000006"); } }; diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 1b37324a0d..1cc1ddf673 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -27,11 +27,9 @@ public abstract class EthereumNetworkBase public static final long POLYGON_ID = 137; public static final long POLYGON_TEST_ID = 80001; public static final long OPTIMISTIC_MAIN_ID = 10; - public static final long OPTIMISTIC_TEST_ID = 69; public static final long CRONOS_MAIN_ID = 25; public static final long CRONOS_TEST_ID = 338; public static final long ARBITRUM_MAIN_ID = 42161; - public static final long ARBITRUM_TEST_ID = 421611; public static final long PALM_ID = 0x2a15c308dL; //11297108109 public static final long PALM_TEST_ID = 0x2a15c3083L; //11297108099 public static final long KLAYTN_ID = 8217; @@ -65,11 +63,9 @@ public abstract class EthereumNetworkBase public static final String MATIC_RPC_URL = "https://matic-mainnet.chainstacklabs.com"; public static final String MUMBAI_TEST_RPC_URL = "https://matic-mumbai.chainstacklabs.com"; public static final String OPTIMISTIC_MAIN_FALLBACK_URL = "https://mainnet.optimism.io"; - public static final String OPTIMISTIC_TEST_FALLBACK_URL = "https://kovan.optimism.io"; public static final String CRONOS_MAIN_RPC_URL = "https://evm.cronos.org"; public static final String CRONOS_TEST_URL = "https://evm-t3.cronos.org"; public static final String ARBITRUM_RPC_URL = "https://arbitrum-mainnet.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; - public static final String ARBITRUM_TEST_RPC_URL = "https://arbitrum-rinkeby.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; public static final String PALM_RPC_URL = "https://palm-mainnet.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; public static final String PALM_TEST_RPC_URL = "https://palm-testnet.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; public static final String KLAYTN_RPC = "https://public-node-api.klaytnapi.com/v1/cypress"; @@ -127,14 +123,10 @@ public abstract class EthereumNetworkBase put(OPTIMISTIC_MAIN_ID, new NetworkInfo("Optimistic", "ETH", OPTIMISTIC_MAIN_FALLBACK_URL, "https://optimistic.etherscan.io/tx/", OPTIMISTIC_MAIN_ID, false)); - put(OPTIMISTIC_TEST_ID, new NetworkInfo("Optimistic (Test)", "ETH", OPTIMISTIC_TEST_FALLBACK_URL, "https://kovan-optimistic.etherscan.io/tx/", - OPTIMISTIC_TEST_ID, false)); put(CRONOS_MAIN_ID, new NetworkInfo("Cronos (Beta)", "CRO", CRONOS_MAIN_RPC_URL, "https://cronoscan.com/tx", CRONOS_MAIN_ID, false)); put(CRONOS_TEST_ID, new NetworkInfo("Cronos (Test)", "tCRO", CRONOS_TEST_URL, "https://testnet.cronoscan.com/tx/", CRONOS_TEST_ID, false)); put(ARBITRUM_MAIN_ID, new NetworkInfo("Arbitrum One", "AETH", ARBITRUM_RPC_URL, "https://arbiscan.io/tx/", ARBITRUM_MAIN_ID, false)); - put(ARBITRUM_TEST_ID, new NetworkInfo("Arbitrum Test", "ARETH", ARBITRUM_TEST_RPC_URL, "https://rinkeby-explorer.arbitrum.io/tx/", - ARBITRUM_TEST_ID, false)); put(PALM_ID, new NetworkInfo("PALM", "PALM", PALM_RPC_URL, "https://explorer.palm.io/tx/", PALM_ID, false)); From 8acd3f79d16555850621c5d3b8c0c433345102e4 Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 29 Nov 2022 13:57:53 +1100 Subject: [PATCH 160/183] Patches for rate usage fix tests --- app/src/main/cpp/keys.c | 13 +++ .../app/entity/CoinGeckoTicker.java | 6 +- .../app/repository/EthereumNetworkBase.java | 26 +++++ .../EthereumNetworkRepositoryType.java | 2 +- .../app/repository/KeyProvider.java | 2 + .../app/repository/KeyProviderJNIImpl.java | 2 + .../app/service/TickerService.java | 5 +- .../alphawallet/app/util/ens/EnsResolver.java | 94 +++++++++++++++---- .../app/viewmodel/DappBrowserViewModel.java | 3 +- .../java/com/alphawallet/app/ENSTest.java | 9 ++ .../app/di/EthereumNetworkBaseTest.java | 2 +- .../app/di/mock/KeyProviderMockImpl.java | 6 ++ .../KeyProviderMockNonProductionImpl.java | 6 ++ 13 files changed, 154 insertions(+), 22 deletions(-) diff --git a/app/src/main/cpp/keys.c b/app/src/main/cpp/keys.c index ef5fa7615a..f73b69fb1e 100644 --- a/app/src/main/cpp/keys.c +++ b/app/src/main/cpp/keys.c @@ -92,6 +92,19 @@ Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getSecondaryInfuraKey( JN #endif } +JNIEXPORT jstring JNICALL +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getTertiaryInfuraKey( JNIEnv* env, jobject thiz ) +{ +#if (HAS_KEYS == 1) + return getDecryptedKey(env, tertiaryInfuraKey); +#elif (HAS_INFURA == 1) + return (*env)->NewStringUTF(env, IFKEY); +#else + const jstring key = "da3717f25f824cc1baa32d812386d93f"; + return (*env)->NewStringUTF(env, key); +#endif +} + JNIEXPORT jstring JNICALL Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getKlaytnKey( JNIEnv* env, jobject thiz ) { diff --git a/app/src/main/java/com/alphawallet/app/entity/CoinGeckoTicker.java b/app/src/main/java/com/alphawallet/app/entity/CoinGeckoTicker.java index a2087a1722..cb3087f3d2 100644 --- a/app/src/main/java/com/alphawallet/app/entity/CoinGeckoTicker.java +++ b/app/src/main/java/com/alphawallet/app/entity/CoinGeckoTicker.java @@ -45,11 +45,15 @@ public static List buildTickerList(String jsonData, String curr fiatPrice = obj.getDouble(currencyIsoSymbol.toLowerCase()); fiatChangeStr = obj.getString(currencyIsoSymbol.toLowerCase() + "_24h_change"); } - else + else if (obj.has("usd")) { fiatPrice = obj.getDouble("usd") * currentConversionRate; fiatChangeStr = obj.getString("usd_24h_change"); } + else + { + continue; //handle empty/corrupt returns + } res.add(new CoinGeckoTicker(address, fiatPrice, getFiatChange(fiatChangeStr))); } diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 07492871fc..918a2d8d85 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -185,6 +185,32 @@ public abstract class EthereumNetworkBase implements EthereumNetworkRepositoryTy // Add deprecated testnet IDs here )); + private static final String INFURA_ENDPOINT = ".infura.io/v3/"; + + @Override + public String getDappBrowserRPC(long chainId) + { + NetworkInfo info = getNetworkByChain(chainId); + + if (info == null) + { + return ""; + } + else if (chainId == MAINNET_ID) + { + int index = info.rpcServerUrl.indexOf(INFURA_ENDPOINT); + return info.rpcServerUrl.substring(0, index + INFURA_ENDPOINT.length()) + keyProvider.getTertiaryInfuraKey(); + } + else if (info.backupNodeUrl != null) + { + return info.backupNodeUrl; + } + else + { + return info.rpcServerUrl; + } + } + // for reset built-in network private static final LongSparseArray builtinNetworkMap = new LongSparseArray() { diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkRepositoryType.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkRepositoryType.java index fb318ada50..085e66c6bf 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkRepositoryType.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkRepositoryType.java @@ -5,7 +5,6 @@ import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.tokens.Token; -import com.alphawallet.app.repository.entity.RealmToken; import org.web3j.protocol.Web3j; @@ -54,6 +53,7 @@ public interface EthereumNetworkRepositoryType { void setHasSetNetworkFilters(); boolean isMainNetSelected(); void setActiveMainnet(boolean isMainNet); + String getDappBrowserRPC(long chainId); void saveCustomRPCNetwork(String networkName, String rpcUrl, long chainId, String symbol, String blockExplorerUrl, String explorerApiUrl, boolean isTestnet, Long oldChainId); void removeCustomRPCNetwork(long chainId); diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java index dc6a441977..ad02288fb8 100644 --- a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java @@ -20,6 +20,8 @@ public interface KeyProvider String getSecondaryInfuraKey(); + String getTertiaryInfuraKey(); + String getRampKey(); String getOpenSeaKey(); diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java index e07661d698..4bd99d0593 100644 --- a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java @@ -11,6 +11,8 @@ public KeyProviderJNIImpl() public native String getSecondaryInfuraKey(); + public native String getTertiaryInfuraKey(); + public native String getBSCExplorerKey(); public native String getAnalyticsKey(); diff --git a/app/src/main/java/com/alphawallet/app/service/TickerService.java b/app/src/main/java/com/alphawallet/app/service/TickerService.java index ccc154086f..0351db96e6 100644 --- a/app/src/main/java/com/alphawallet/app/service/TickerService.java +++ b/app/src/main/java/com/alphawallet/app/service/TickerService.java @@ -101,6 +101,7 @@ public class TickerService private static String currentCurrencySymbol; private static final Map canUpdate = new ConcurrentHashMap<>(); private static final Map dexGuruQuery = new ConcurrentHashMap<>(); + private static long lastTickerUpdate; @Nullable private Disposable tickerUpdateTimer; @@ -119,11 +120,12 @@ public TickerService(OkHttpClient httpClient, PreferenceRepositoryType sharedPre resetTickerUpdate(); initCurrency(); + lastTickerUpdate = 0; } public void updateTickers() { - if (mainTickerUpdate != null && !mainTickerUpdate.isDisposed()) + if (mainTickerUpdate != null && !mainTickerUpdate.isDisposed() && System.currentTimeMillis() > (lastTickerUpdate + DateUtils.MINUTE_IN_MILLIS)) { return; //do not update if update is currently in progress } @@ -151,6 +153,7 @@ private void tickersUpdated(int tickerCount) { Timber.d("Tickers Updated: %s", tickerCount); mainTickerUpdate = null; + lastTickerUpdate = System.currentTimeMillis(); } public Single updateCurrencyConversion() diff --git a/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java b/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java index 5bdf7b9ac0..d25590ed9a 100644 --- a/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java +++ b/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java @@ -59,6 +59,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -76,6 +78,7 @@ public class EnsResolver implements Resolvable // Permit number offchain calls for a single contract call. public static final int LOOKUP_LIMIT = 4; + private static final long ENS_CACHE_TIME_VALIDITY = 10 * (1000*60); //10 minutes public static final String REVERSE_NAME_SUFFIX = ".addr.reverse"; @@ -112,11 +115,61 @@ public EnsResolver(Web3j web3j) { this(web3j, Keys.ADDRESS_LENGTH_IN_HEX); } - protected ContractAddress obtainOffchainResolverAddr(String ensName) throws Exception + protected ContractAddress obtainOffChainResolverAddress(String ensName) throws Exception { return new ContractAddress(chainId, getResolverAddress(ensName)); } + private static class CachedENSRead + { + public final String cachedResult; + public final long cachedResultTime; + + public CachedENSRead(String result) + { + cachedResult = result; + cachedResultTime = System.currentTimeMillis(); + } + + public boolean isValid() + { + return System.currentTimeMillis() < (cachedResultTime + ENS_CACHE_TIME_VALIDITY); //10 minutes cache validity + } + } + + //Need to cache results for Resolve + private static final Map cachedNameReads = new ConcurrentHashMap<>(); + + private String cacheKey(String ensName, String addrFunction) + { + return ((ensName != null) ? ensName : "") + "%" + ((addrFunction != null) ? addrFunction : ""); + } + + private String resolveWithCaching(String ensName, byte[] nameHash, String resolverAddr) throws Exception + { + String dnsEncoded = NameHash.dnsEncode(ensName); + String addrFunction = encodeResolverAddr(nameHash); + + CachedENSRead lookupData = cachedNameReads.get(cacheKey(ensName, addrFunction)); + String lookupDataHex = lookupData != null ? lookupData.cachedResult : null; + + if (lookupData == null || !lookupData.isValid()) + { + EthCall result = + resolve( + Numeric.hexStringToByteArray(dnsEncoded), + Numeric.hexStringToByteArray(addrFunction), + resolverAddr); + lookupDataHex = result.isReverted() ? Utils.removeDoubleQuotes(result.getError().getData()) : result.getValue();// .toString(); + if (!TextUtils.isEmpty(lookupDataHex) && !lookupDataHex.equals("0x")) + { + cachedNameReads.put(cacheKey(ensName, addrFunction), new CachedENSRead(lookupDataHex)); + } + } + + return lookupDataHex; + } + /** * Returns the address of the resolver for the specified node. * @@ -133,7 +186,7 @@ public String resolve(String ensName) throws Exception try { if (isValidEnsName(ensName, addressLength)) { - ContractAddress resolverAddress = obtainOffchainResolverAddr(ensName); + ContractAddress resolverAddress = obtainOffChainResolverAddress(ensName); boolean supportWildcard = supportsInterface(EnsUtils.ENSIP_10_INTERFACE_ID, resolverAddress.address); @@ -141,16 +194,7 @@ public String resolve(String ensName) throws Exception String resolvedName; if (supportWildcard) { - String dnsEncoded = NameHash.dnsEncode(ensName); - String addrFunction = encodeResolverAddr(nameHash); - - EthCall result = - resolve( - Numeric.hexStringToByteArray(dnsEncoded), - Numeric.hexStringToByteArray(addrFunction), - resolverAddress.address); - - String lookupDataHex = result.isReverted() ? Utils.removeDoubleQuotes(result.getError().getData()) : result.getValue();// .toString(); + String lookupDataHex = resolveWithCaching(ensName, nameHash, resolverAddress.address); resolvedName = resolveOffchain(lookupDataHex, resolverAddress, LOOKUP_LIMIT); } else { try { @@ -359,7 +403,7 @@ public String reverseResolve(String address) throws Exception if (WalletUtils.isValidAddress(address, addressLength)) { String reverseName = Numeric.cleanHexPrefix(address) + REVERSE_NAME_SUFFIX; - ContractAddress resolverAddress = obtainOffchainResolverAddr(reverseName); + ContractAddress resolverAddress = obtainOffChainResolverAddress(reverseName); byte[] nameHash = NameHash.nameHashAsBytes(reverseName); String name; @@ -438,11 +482,27 @@ public boolean supportsInterface(byte[] interfaceID, String address) throws Exce public String resolverAddr(byte[] node, String address) throws Exception { - final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_addr, - Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(node)), - Arrays.>asList(new TypeReference
() {})); + //use caching + String nodeData = Numeric.toHexString(node); + CachedENSRead resolverData = cachedNameReads.get(cacheKey(nodeData, address)); + String resolverAddr = resolverData != null ? resolverData.cachedResult : null; - return getContractData(address, function, ""); + if (resolverData == null || !resolverData.isValid()) + { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_addr, + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes32(node)), + Arrays.>asList(new TypeReference
() + { + })); + + resolverAddr = getContractData(address, function, ""); + if (!TextUtils.isEmpty(resolverAddr) && resolverAddr.length() > 2) + { + cachedNameReads.put(cacheKey(nodeData, address), new CachedENSRead(resolverAddr)); + } + } + + return resolverAddr; } public String encodeResolverAddr(byte[] node) diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java index 49408c2ffb..0608384765 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/DappBrowserViewModel.java @@ -375,9 +375,10 @@ public Single calculateGasEstimate(Wallet wallet, Web3Transaction tr } } + // Use the backup node if avail public String getNetworkNodeRPC(long chainId) { - return ethereumNetworkRepository.getNetworkByChain(chainId).rpcServerUrl; + return ethereumNetworkRepository.getDappBrowserRPC(chainId); } public NetworkInfo getNetworkInfo(long chainId) diff --git a/app/src/test/java/com/alphawallet/app/ENSTest.java b/app/src/test/java/com/alphawallet/app/ENSTest.java index bfd6e8417d..686844683b 100644 --- a/app/src/test/java/com/alphawallet/app/ENSTest.java +++ b/app/src/test/java/com/alphawallet/app/ENSTest.java @@ -69,6 +69,15 @@ public void testResolve() throws Exception { assertEquals( ensResolver.resolve("offchainexample.eth"), ("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045").toLowerCase()); + + //Now test the cache + assertEquals( + ensResolver.resolve("1.offchainexample.eth"), ("0x41563129cdbbd0c5d3e1c86cf9563926b243834d").toLowerCase()); + assertEquals( + ensResolver.resolve("1.offchainexample.eth"), ("0x41563129cdbbd0c5d3e1c86cf9563926b243834d").toLowerCase()); + + assertEquals( + ensResolver.resolve("web3j.eth"), ("0x7bfd522dea355ddee2be3c01dfa4419451759310").toLowerCase()); } //Temporarily remove - DAS seems to be acting up diff --git a/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java b/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java index 935261ff4e..c82b98a1b1 100644 --- a/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java +++ b/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java @@ -28,7 +28,7 @@ public void should_getNodeURLByNetworkId_when_use_production_key() public void should_construct_infura_url_when_getNodeURLByNetworkId_given_production_key() { assertThat(EthereumNetworkBase.getNodeURLByNetworkId(1L), equalTo("https://mainnet.infura.io/v3/fake-key-for-testing")); - assertThat(EthereumNetworkBase.getNodeURLByNetworkId(3L), equalTo("https://rpc.ankr.com/eth_ropsten")); + assertThat(EthereumNetworkBase.getNodeURLByNetworkId(5L), equalTo("https://goerli.infura.io/v3/fake-key-for-testing")); } @Test diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java index c4b68ca255..4566ab054f 100644 --- a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java @@ -60,6 +60,12 @@ public String getSecondaryInfuraKey() return FAKE_KEY_FOR_TESTING; } + @Override + public String getTertiaryInfuraKey() + { + return FAKE_KEY_FOR_TESTING; + } + @Override public String getRampKey() { diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java index b3be351fad..ae030b12c2 100644 --- a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java @@ -59,6 +59,12 @@ public String getSecondaryInfuraKey() return null; } + @Override + public String getTertiaryInfuraKey() + { + return null; + } + @Override public String getRampKey() { From 085525fd355983a0ba37f96faa3099b61926fdad Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 9 Dec 2022 18:40:22 +1100 Subject: [PATCH 161/183] Refactor Refresh Updates (#2993) * Update key provider * Refactor token updating: * fix bug that stopped the database being updated with corrected token type. * restrict event logs where needed * use less restrictive RPC where possible * improve event sync in general * Update Gnosis RPC with more responsive version * Ensure all usages of primary URL include the required secret and replace TokenScript usage of primary with dappbrowser RPC * Update unit test * Switch EVENT_SYNC_DEBUGGING to false * Further update fixes to reduce overhead with balance updates * Fix various ERC721 handling bugs --- app/src/main/cpp/keys.c | 10 ++ .../com/alphawallet/app/entity/EventSync.java | 102 +++++++++++- .../app/entity/nftassets/NFTAsset.java | 6 + .../app/entity/tokens/ERC1155Token.java | 56 ++++--- .../app/entity/tokens/ERC721Ticket.java | 2 +- .../app/entity/tokens/ERC721Token.java | 121 ++++++++------ .../alphawallet/app/entity/tokens/Ticket.java | 38 ++--- .../alphawallet/app/entity/tokens/Token.java | 19 +-- .../app/entity/tokens/TokenFactory.java | 1 + .../app/repository/EthereumNetworkBase.java | 59 +++++-- .../app/repository/HttpServiceHelper.java | 27 ++- .../app/repository/KeyProvider.java | 2 + .../app/repository/KeyProviderJNIImpl.java | 2 + .../app/repository/TokenRepository.java | 43 ++++- .../app/repository/TokensRealmSource.java | 154 ++++++++++-------- .../app/router/TokenDetailRouter.java | 14 +- .../app/service/AWHttpService.java | 9 +- .../app/service/AlphaWalletService.java | 11 +- .../app/service/AssetDefinitionService.java | 9 +- .../alphawallet/app/service/GasService.java | 14 +- .../alphawallet/app/service/IPFSService.java | 6 +- .../app/service/TokensService.java | 23 +-- .../service/TransactionsNetworkClient.java | 14 +- .../app/service/TransactionsService.java | 41 +++-- .../alphawallet/app/ui/FunctionActivity.java | 3 +- .../alphawallet/app/ui/NFTAssetsFragment.java | 2 +- .../com/alphawallet/app/ui/TokenActivity.java | 2 +- .../ui/widget/adapter/NFTAssetsAdapter.java | 37 ++++- .../app/ui/widget/entity/IconItem.java | 8 - .../alphawallet/app/util/ens/EnsResolver.java | 23 ++- .../app/viewmodel/TokenFunctionViewModel.java | 5 + .../app/viewmodel/WalletViewModel.java | 9 +- .../alphawallet/app/web3/Web3TokenView.java | 6 +- .../com/alphawallet/app/widget/TokenIcon.java | 4 - .../com/alphawallet/app/IPFSServiceTest.java | 12 +- .../app/di/EthereumNetworkBaseTest.java | 2 +- .../app/di/mock/KeyProviderMockImpl.java | 6 + .../KeyProviderMockNonProductionImpl.java | 6 + .../app/repository/HttpServiceHelperTest.java | 8 +- .../ethereum/EthereumNetworkBase.java | 2 +- 40 files changed, 617 insertions(+), 301 deletions(-) diff --git a/app/src/main/cpp/keys.c b/app/src/main/cpp/keys.c index f73b69fb1e..6e64fa4f04 100644 --- a/app/src/main/cpp/keys.c +++ b/app/src/main/cpp/keys.c @@ -205,3 +205,13 @@ Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getWalletConnectProjectId return (*env)->NewStringUTF(env, WALLETCONNECT_PROJECT_ID); #endif } + +JNIEXPORT jstring JNICALL +Java_com_alphawallet_app_repository_KeyProviderJNIImpl_getInfuraSecret(JNIEnv *env, jobject thiz) { +#if (HAS_KEYS == 1) + return getDecryptedKey(env, infuraSecret); +#else + const jstring key = ""; + return (*env)->NewStringUTF(env, key); +#endif +} diff --git a/app/src/main/java/com/alphawallet/app/entity/EventSync.java b/app/src/main/java/com/alphawallet/app/entity/EventSync.java index 8a37935b9c..ad49461f10 100644 --- a/app/src/main/java/com/alphawallet/app/entity/EventSync.java +++ b/app/src/main/java/com/alphawallet/app/entity/EventSync.java @@ -35,6 +35,10 @@ public class EventSync { public static final long BLOCK_SEARCH_INTERVAL = 100000L; + public static final long POLYGON_BLOCK_SEARCH_INTERVAL = 10000L; + + private static final String TAG = "EVENT_SYNC"; + private static final boolean EVENT_SYNC_DEBUGGING = false; private final Token token; @@ -74,8 +78,17 @@ public SyncDef getSyncDef(Realm realm) case DOWNWARD_SYNC_START: //Start event sync, optimistically try the whole current event range from 1 -> LATEST eventReadStartBlock = BigInteger.ONE; eventReadEndBlock = BigInteger.valueOf(-1L); - //write the start point here - writeStartSyncBlock(realm, currentBlock.longValue()); + if (EthereumNetworkBase.isEventBlockLimitEnforced(token.tokenInfo.chainId)) + { + syncState = EventSyncState.UPWARD_SYNC; + eventReadStartBlock = currentBlock.subtract(EthereumNetworkBase.getMaxEventFetch(token.tokenInfo.chainId).multiply(BigInteger.valueOf(3))); + EVENT_DEBUG("Init Sync for restricted block RPC"); + } + else + { + //write the start point here + writeStartSyncBlock(realm, currentBlock.longValue()); + } break; case DOWNWARD_SYNC: //we needed to slow down the sync eventReadStartBlock = lastBlockRead.subtract(BigInteger.valueOf(readBlockSize)); @@ -88,19 +101,77 @@ public SyncDef getSyncDef(Realm realm) break; case UPWARD_SYNC_MAX: //we are syncing from the point we started the downward sync upwardSync = true; + if (EthereumNetworkBase.isEventBlockLimitEnforced(token.tokenInfo.chainId) && upwardSyncStateLost(lastBlockRead, currentBlock)) + { + syncState = EventSyncState.UPWARD_SYNC; + EVENT_DEBUG("Switch back to sync scan"); + } + eventReadStartBlock = lastBlockRead; eventReadEndBlock = BigInteger.valueOf(-1L); break; case UPWARD_SYNC: //we encountered upward sync issues upwardSync = true; eventReadStartBlock = lastBlockRead; - eventReadEndBlock = lastBlockRead.add(BigInteger.valueOf(readBlockSize)); + if (upwardSyncComplete(eventReadStartBlock, currentBlock)) //detect completion of upward sync and switch to sync_max + { + eventReadEndBlock = BigInteger.valueOf(-1L); + syncState = EventSyncState.UPWARD_SYNC_MAX; + EVENT_DEBUG("Sync complete"); + } + else + { + eventReadEndBlock = lastBlockRead.add(BigInteger.valueOf(readBlockSize)); + } break; } + // Finally adjust the event end read if required. This is placed outside the switch because it should affect + // a few different paths + eventReadEndBlock = adjustForLimitedBlockSize(eventReadStartBlock, eventReadEndBlock, currentBlock); + + // detect edge condition - it's highly unlikely but acts as a stopper in case of unexpected results + // This edge condition is where the start block read is greater than the current block. + if (eventReadStartBlock.compareTo(currentBlock) >= 0) + { + eventReadStartBlock = currentBlock.subtract(BigInteger.ONE); + eventReadEndBlock = BigInteger.valueOf(-1L); + syncState = EventSyncState.UPWARD_SYNC_MAX; + } + return new SyncDef(eventReadStartBlock, eventReadEndBlock, syncState, upwardSync); } + private boolean upwardSyncStateLost(BigInteger lastBlockRead, BigInteger currentBlock) + { + return currentBlock.subtract(lastBlockRead).compareTo(EthereumNetworkBase.getMaxEventFetch(token.tokenInfo.chainId)) >= 0; + } + + private boolean upwardSyncComplete(BigInteger eventReadStartBlock, BigInteger currentBlock) + { + BigInteger maxBlockRead = EthereumNetworkBase.getMaxEventFetch(token.tokenInfo.chainId).subtract(BigInteger.ONE); + BigInteger diff = currentBlock.subtract(eventReadStartBlock); + + return diff.compareTo(maxBlockRead) < 0; + } + + private BigInteger adjustForLimitedBlockSize(BigInteger eventReadStartBlock, BigInteger eventReadEndBlock, BigInteger currentBlock) + { + if (EthereumNetworkBase.isEventBlockLimitEnforced(token.tokenInfo.chainId)) + { + BigInteger maxBlockRead = EthereumNetworkBase.getMaxEventFetch(token.tokenInfo.chainId); + + long diff = currentBlock.subtract(eventReadStartBlock).longValue(); + + if (diff >= maxBlockRead.longValue()) + { + return eventReadStartBlock.add(maxBlockRead).subtract(BigInteger.ONE); + } + } + + return eventReadEndBlock; + } + public boolean handleEthLogError(Response.Error error, DefaultBlockParameter startBlock, DefaultBlockParameter endBlock, SyncDef sync, Realm realm) { if (error.getCode() == -32005) @@ -180,6 +251,11 @@ private long reduceBlockSearch(long currentBlock, BigInteger startBlock) private long getCurrentEventBlockSize(Realm instance) { + if (EthereumNetworkBase.isEventBlockLimitEnforced(token.tokenInfo.chainId)) + { + return EthereumNetworkBase.getMaxEventFetch(token.tokenInfo.chainId).longValue(); + } + RealmAuxData rd = instance.where(RealmAuxData.class) .equalTo("instanceKey", TokensRealmSource.databaseKey(token.tokenInfo.chainId, token.getAddress())) .findFirst(); @@ -208,8 +284,9 @@ protected EventSyncState getCurrentTokenSyncState(Realm instance) else { int state = rd.getTokenId().intValue(); - if (state >= EventSyncState.DOWNWARD_SYNC_START.ordinal() || state < EventSyncState.TOP_LIMIT.ordinal()) + if (state >= EventSyncState.DOWNWARD_SYNC_START.ordinal() && state < EventSyncState.TOP_LIMIT.ordinal()) { + EVENT_DEBUG("Read State: " + EventSyncState.values()[state]); return EventSyncState.values()[state]; } else @@ -251,6 +328,7 @@ protected long getLastEventRead(Realm instance) } else { + EVENT_DEBUG("ReadEventSync: " + rd.getResultTime()); return rd.getResultTime(); } } @@ -336,6 +414,8 @@ private void updateEventReads(Realm realm, long lastRead, long readInterval, Eve rd.setResultReceivedTime(readInterval); rd.setTokenId(String.valueOf(state.ordinal())); + EVENT_DEBUG("WriteState: " + state + " " + lastRead); + r.insertOrUpdate(rd); }); } @@ -343,7 +423,7 @@ private void updateEventReads(Realm realm, long lastRead, long readInterval, Eve // If we're syncing downwards, work out what event block size we should read next private long calcNewIntervalSize(SyncDef sync, int evReads) { - if (sync.upwardSync) return BLOCK_SEARCH_INTERVAL; + if (sync.upwardSync) return EthereumNetworkBase.getMaxEventFetch(token.tokenInfo.chainId).longValue(); long endBlock = sync.eventReadEndBlock.longValue() == -1 ? TransactionsService.getCurrentBlock(token.tokenInfo.chainId).longValue() : sync.eventReadEndBlock.longValue(); long currentReadSize = endBlock - sync.eventReadStartBlock.longValue(); @@ -360,7 +440,7 @@ else if (evReads < 1000) } else if ((maxLogReads - evReads) > maxLogReads*0.25) { - currentReadSize += BLOCK_SEARCH_INTERVAL; + currentReadSize += EthereumNetworkBase.getMaxEventFetch(token.tokenInfo.chainId).longValue(); } return currentReadSize; @@ -368,6 +448,8 @@ else if ((maxLogReads - evReads) > maxLogReads*0.25) /*** * Event Handling + * + * TODO: batch up catch-up calls */ public Pair, HashSet>> processTransferEvents(Web3j web3j, Event transferEvent, DefaultBlockParameter startBlock, @@ -582,4 +664,12 @@ private void storeTransferData(Realm instance, String hash, String valueList, St matchingEntry.setTransferDetail(valueList); instance.insertOrUpdate(matchingEntry); } + + private void EVENT_DEBUG(String message) + { + if (EVENT_SYNC_DEBUGGING) + { + Timber.tag(TAG).i(token.tokenInfo.chainId + " " + token.tokenInfo.address + ": " + message); + } + } } diff --git a/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java b/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java index 30fa7cb5dd..4f12d851a5 100644 --- a/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java +++ b/app/src/main/java/com/alphawallet/app/entity/nftassets/NFTAsset.java @@ -100,6 +100,7 @@ public NFTAsset(BigInteger tokenId) attributeMap.clear(); balance = BigDecimal.ONE; assetMap.put(NAME, "ID #" + tokenId.toString()); + assetMap.put(LOADING_TOKEN, "."); } public NFTAsset(NFTAsset asset) @@ -382,6 +383,11 @@ public boolean needsLoading() return (assetMap.size() == 0 || assetMap.containsKey(LOADING_TOKEN)); } + public boolean hasImageAsset() + { + return !TextUtils.isEmpty(getThumbnail()); + } + public boolean requiresReplacement() { return (needsLoading() || !assetMap.containsKey(NAME) || TextUtils.isEmpty(getImage())); diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC1155Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC1155Token.java index f879983a38..84f8ecc789 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC1155Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC1155Token.java @@ -276,27 +276,39 @@ public Function getTransferFunction(String to, List tokenIds) throws } @Override - public List getChangeList(Map assetMap) + public Map getAssetChange(Map oldAssetList) { - //detect asset removal - List oldAssetIdList = new ArrayList<>(assetMap.keySet()); - oldAssetIdList.removeAll(assets.keySet()); + //first see if there's no change; if this is the case we can skip + if (assetsUnchanged(oldAssetList)) return assets; - List changeList = new ArrayList<>(oldAssetIdList); + //add all known tokens in + Map sum = new HashMap<>(oldAssetList); + sum.putAll(assets); + Set tokenIds = sum.keySet(); + Function balanceOfBatch = balanceOfBatch(getWallet(), tokenIds); + List balances = callSmartContractFunctionArray(tokenInfo.chainId, balanceOfBatch, getAddress(), getWallet()); + Map updatedAssetMap; - //Now detect differences or new tokens - for (BigInteger tokenId : assets.keySet()) + if (balances != null && balances.size() > 0) { - NFTAsset newAsset = assets.get(tokenId); - NFTAsset oldAsset = assetMap.get(tokenId); - - if (oldAsset == null || newAsset.hashCode() != oldAsset.hashCode()) + updatedAssetMap = new HashMap<>(); + int index = 0; + for (BigInteger tokenId : tokenIds) { - changeList.add(tokenId); + NFTAsset thisAsset = new NFTAsset(sum.get(tokenId)); + BigInteger balance = balances.get(index).getValue(); + thisAsset.setBalance(new BigDecimal(balance)); + updatedAssetMap.put(tokenId, thisAsset); + + index++; } } + else + { + updatedAssetMap = assets; + } - return changeList; + return updatedAssetMap; } private List fetchBalances(Set tokenIds) @@ -308,16 +320,10 @@ private List fetchBalances(Set tokenIds) @Override public Map queryAssets(Map assetMap) { - //first see if there's no change; if this is the case we can skip - if (assetsUnchanged(assetMap)) return assets; - - //add all known tokens in - Map sum = new HashMap<>(assetMap); - sum.putAll(assets); - Set tokenIds = sum.keySet(); + Set tokenIds = assetMap.keySet(); Function balanceOfBatch = balanceOfBatch(getWallet(), tokenIds); List balances = callSmartContractFunctionArray(tokenInfo.chainId, balanceOfBatch, getAddress(), getWallet()); - Map updatedAssetMap; + Map updatedAssetMap = new HashMap<>(); if (balances != null && balances.size() > 0) { @@ -325,7 +331,7 @@ public Map queryAssets(Map assetMap) int index = 0; for (BigInteger tokenId : tokenIds) { - NFTAsset thisAsset = new NFTAsset(sum.get(tokenId)); + NFTAsset thisAsset = new NFTAsset(assetMap.get(tokenId)); BigInteger balance = balances.get(index).getValue(); thisAsset.setBalance(new BigDecimal(balance)); updatedAssetMap.put(tokenId, thisAsset); @@ -333,10 +339,6 @@ public Map queryAssets(Map assetMap) index++; } } - else - { - updatedAssetMap = assets; - } return updatedAssetMap; } @@ -643,7 +645,7 @@ public BigDecimal updateBalance(Realm realm) try { - final Web3j web3j = TokenRepository.getWeb3jService(tokenInfo.chainId); + final Web3j web3j = TokenRepository.getWeb3jServiceForEvents(tokenInfo.chainId); Pair, HashSet>> evRead = eventSync.processTransferEvents(web3j, getBalanceUpdateEvents(), startBlock, endBlock, realm); diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Ticket.java b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Ticket.java index 813eeda7fa..49a6e8c5ca 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Ticket.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Ticket.java @@ -171,7 +171,7 @@ public boolean hasArrayBalance() public List getNonZeroArrayBalance() { List nonZeroValues = new ArrayList<>(); - for (BigInteger value : balanceArray) if (value.compareTo(BigInteger.ZERO) != 0 && !nonZeroValues.contains(value)) nonZeroValues.add(value); + for (BigInteger value : balanceArray) if (value.compareTo(BigInteger.ZERO) != 0) nonZeroValues.add(value); return nonZeroValues; } diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java index e646171d67..0de075182e 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/ERC721Token.java @@ -57,6 +57,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -274,7 +275,9 @@ public boolean checkRealmBalanceChange(RealmToken realmToken) public boolean checkBalanceChange(Token oldToken) { if (super.checkBalanceChange(oldToken)) return true; - if (getTokenAssets().size() != oldToken.getTokenAssets().size()) return true; + if ((getTokenAssets() != null && oldToken.getTokenAssets() != null) + && getTokenAssets().size() != oldToken.getTokenAssets().size()) return true; + for (BigInteger tokenId : tokenBalanceAssets.keySet()) { NFTAsset newAsset = tokenBalanceAssets.get(tokenId); @@ -360,7 +363,7 @@ public BigDecimal updateBalance(Realm realm) try { balanceChecks.put(tokenInfo.address, true); //set checking - final Web3j web3j = TokenRepository.getWeb3jService(tokenInfo.chainId); + final Web3j web3j = TokenRepository.getWeb3jServiceForEvents(tokenInfo.chainId); if (contractType == ContractType.ERC721_ENUMERABLE) { updateEnumerableBalance(web3j, realm); @@ -391,6 +394,7 @@ public BigDecimal updateBalance(Realm realm) if (eventSync.handleEthLogError(e.error, startBlock, endBlock, sync, realm)) { //recurse until we find a good value + balanceChecks.remove(tokenInfo.address); updateBalance(realm); } } @@ -746,24 +750,6 @@ public EthFilter getSendBalanceFilter(Event event, DefaultBlockParameter startBl return filter; } - /** - * Returns false if the Asset balance appears to be entries with only TokenId - indicating an ERC721Ticket - * - * @return - */ - @Override - public boolean checkBalanceType() - { - boolean onlyHasTokenId = true; - //if elements contain asset with only assetId then most likely this is a ticket. - for (NFTAsset a : tokenBalanceAssets.values()) - { - if (!a.isBlank()) onlyHasTokenId = false; - } - - return tokenBalanceAssets.size() == 0 || !onlyHasTokenId; - } - public String getTransferID(Transaction tx) { if (tx.transactionInput != null && tx.transactionInput.miscData.size() > 0) @@ -837,28 +823,32 @@ public BigDecimal getBalanceRaw() * If there is a token that previously was there, but now isn't, it could be because * the opensea call was split or that the owner transferred the token * - * @param assetMap Loaded Assets from Realm - * @return map of currently known live assets + * @param assetMap Loaded Assets which are new assets (don't add assets from opensea unless we double check here first) + * @return map of checked assets */ @Override public Map queryAssets(Map assetMap) { - //check all tokens in this contract - assetMap.putAll(tokenBalanceAssets); + final Web3j web3j = TokenRepository.getWeb3jService(tokenInfo.chainId); + + HashSet currentAssets = new HashSet<>(assetMap.keySet()); + + try + { + currentAssets = checkBalances(web3j, currentAssets); + } + catch (Exception e) + { + // + } - //now check balance for all tokenIds (note that ERC1155 has a batch balance check, ERC721 does not) for (Map.Entry entry : assetMap.entrySet()) { BigInteger checkId = entry.getKey(); NFTAsset checkAsset = entry.getValue(); //check balance - String owner = callSmartContractFunction(tokenInfo.chainId, ownerOf(checkId), getAddress(), getWallet()); - if (owner == null) //play it safe. If there's no 'ownerOf' for an ERC721, it's something custom like ENS - { - checkAsset.setBalance(BigDecimal.ONE); - } - else if (owner.equalsIgnoreCase(getWallet())) + if (currentAssets.contains(checkId)) { checkAsset.setBalance(BigDecimal.ONE); } @@ -867,35 +857,74 @@ else if (owner.equalsIgnoreCase(getWallet())) checkAsset.setBalance(BigDecimal.ZERO); } - //add back into asset map - tokenBalanceAssets.put(checkId, checkAsset); + assetMap.put(checkId, checkAsset); } - return tokenBalanceAssets; + return assetMap; } - + + // Check for new/missing tokenBalanceAssets @Override - public List getChangeList(Map assetMap) + public Map getAssetChange(Map oldAssetList) { - //detect asset removal - List oldAssetIdList = new ArrayList<>(assetMap.keySet()); - oldAssetIdList.removeAll(tokenBalanceAssets.keySet()); + Map updatedAssets = new HashMap<>(); + // detect asset removal, first find new assets + HashSet changedAssetList = new HashSet<>(tokenBalanceAssets.keySet()); + changedAssetList.removeAll(oldAssetList.keySet()); + + HashSet unchangedAssets = new HashSet<>(tokenBalanceAssets.keySet()); + unchangedAssets.removeAll(changedAssetList); - List changeList = new ArrayList<>(oldAssetIdList); + // removed assets + HashSet removedAssets = new HashSet<>(oldAssetList.keySet()); + removedAssets.removeAll(tokenBalanceAssets.keySet()); + changedAssetList.addAll(removedAssets); + HashSet balanceAssets = new HashSet<>(); + + final Web3j web3j = TokenRepository.getWeb3jService(tokenInfo.chainId); + + try + { + balanceAssets = checkBalances(web3j, changedAssetList); + } + catch (Exception e) + { + // + } //Now detect differences or new tokens - for (BigInteger tokenId : tokenBalanceAssets.keySet()) + for (BigInteger tokenId : changedAssetList) { - NFTAsset newAsset = tokenBalanceAssets.get(tokenId); - NFTAsset oldAsset = assetMap.get(tokenId); + NFTAsset asset = tokenBalanceAssets.get(tokenId); + if (asset == null) asset = oldAssetList.get(tokenId); - if (oldAsset == null || newAsset.hashCode() != oldAsset.hashCode()) + if (asset == null) + { + continue; + } + + if (balanceAssets.contains(tokenId)) + { + asset.setBalance(BigDecimal.ZERO); + } + else + { + asset.setBalance(BigDecimal.ONE); + } + + updatedAssets.put(tokenId, asset); + } + + for (BigInteger tokenId : unchangedAssets) + { + NFTAsset asset = tokenBalanceAssets.get(tokenId); + if (asset != null) { - changeList.add(tokenId); + updatedAssets.put(tokenId, asset); } } - return changeList; + return updatedAssets; } private Request getContractCall(Web3j web3j, Function function, String contractAddress) diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/Ticket.java b/app/src/main/java/com/alphawallet/app/entity/tokens/Ticket.java index e909b34178..44e5b85115 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/Ticket.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/Ticket.java @@ -10,7 +10,6 @@ import com.alphawallet.app.entity.tokendata.TokenGroup; import com.alphawallet.app.repository.EventResult; import com.alphawallet.app.repository.entity.RealmToken; -import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.util.Utils; import com.alphawallet.app.viewmodel.BaseViewModel; import com.alphawallet.token.entity.TicketRange; @@ -27,31 +26,34 @@ import java.util.List; /** - * Created by James on 27/01/2018. It might seem counter intuitive - * but here Ticket refers to a container of an asset class here, not - * the right to seat somewhere in the venue. Therefore, there - * shouldn't be List To understand this, imagine that one says - * "I have two cryptocurrencies: Ether and Bitcoin, each amounts to a - * hundred", and he pauses and said, "I also have two indices: FIFA - * and Formuler-one, which, too, amounts to a hundred each". + * Created by James on 27/01/2018. */ public class Ticket extends Token { private final List balanceArray; - private boolean isMatchedInXML = false; - public Ticket(TokenInfo tokenInfo, List balances, long blancaTime, String networkName, ContractType type) { + public Ticket(TokenInfo tokenInfo, List balances, long blancaTime, String networkName, ContractType type) + { super(tokenInfo, BigDecimal.ZERO, blancaTime, networkName, type); this.balanceArray = balances; - balance = balanceArray != null ? BigDecimal.valueOf(balanceArray.size()) : BigDecimal.ZERO; + balance = balanceArray != null ? BigDecimal.valueOf(getNonZeroArrayBalance().size()) : BigDecimal.ZERO; group = TokenGroup.NFT; } - public Ticket(TokenInfo tokenInfo, String balances, long blancaTime, String networkName, ContractType type) { + public Ticket(TokenInfo tokenInfo, String balances, long blancaTime, String networkName, ContractType type) + { super(tokenInfo, BigDecimal.ZERO, blancaTime, networkName, type); this.balanceArray = stringHexToBigIntegerList(balances); - balance = BigDecimal.valueOf(balanceArray.size()); + balance = BigDecimal.valueOf(getNonZeroArrayBalance().size()); + group = TokenGroup.NFT; + } + + public Ticket(Token oldTicket, List balances) + { + super(oldTicket.tokenInfo, BigDecimal.ZERO, oldTicket.updateBlancaTime, oldTicket.getNetworkName(), oldTicket.contractType); + this.balanceArray = balances; + balance = BigDecimal.valueOf(getNonZeroArrayBalance().size()); group = TokenGroup.NFT; } @@ -235,11 +237,6 @@ private List tokenIdsToTokenIndices(List tokenIds) return indexList; } - public void checkIsMatchedInXML(AssetDefinitionService assetService) - { - isMatchedInXML = assetService.hasDefinition(tokenInfo.chainId, tokenInfo.address); - } - @Override public Function getTransferFunction(String to, List tokenIndices) throws NumberFormatException { @@ -305,7 +302,10 @@ public boolean hasArrayBalance() public List getNonZeroArrayBalance() { List nonZeroValues = new ArrayList<>(); - for (BigInteger value : balanceArray) if (value.compareTo(BigInteger.ZERO) != 0 && !nonZeroValues.contains(value)) nonZeroValues.add(value); + for (BigInteger value : balanceArray) + { + if (value.compareTo(BigInteger.ZERO) != 0) nonZeroValues.add(value); + } return nonZeroValues; } diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java index f0164cde88..0108c12332 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/Token.java @@ -383,7 +383,7 @@ public void setIsEthereum() public boolean isBad() { - return tokenInfo == null || (tokenInfo.symbol == null && tokenInfo.name == null); + return tokenInfo == null || tokenInfo.chainId == 0 || (tokenInfo.symbol == null && tokenInfo.name == null); } public void setTokenWallet(String address) @@ -711,11 +711,6 @@ public int hashCode() return hash; } - public boolean checkBalanceType() - { - return true; - } - public String getTransactionDetail(Context ctx, Transaction tx, TokensService tService) { if (isEthereum()) @@ -922,11 +917,6 @@ public boolean mayRequireRefresh() || (!TextUtils.isEmpty(tokenInfo.symbol) && tokenInfo.symbol.contains("?")); } - public List getChangeList(Map assetMap) - { - return new ArrayList<>(); - } - public void setAssetContract(AssetContract contract) { } public AssetContract getAssetContract() { return null; } @@ -945,6 +935,11 @@ public Map queryAssets(Map assetMap) return assetMap; } + public Map getAssetChange(Map oldAssetList) + { + return oldAssetList; + } + /** * Token Metadata handling */ @@ -1019,4 +1014,4 @@ public HashSet processLogsAndStoreTransferEvents(EthLog receiveLogs, { return null; } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/alphawallet/app/entity/tokens/TokenFactory.java b/app/src/main/java/com/alphawallet/app/entity/tokens/TokenFactory.java index ad437a4f6a..c5b8843e8f 100644 --- a/app/src/main/java/com/alphawallet/app/entity/tokens/TokenFactory.java +++ b/app/src/main/java/com/alphawallet/app/entity/tokens/TokenFactory.java @@ -124,6 +124,7 @@ public Token createToken(TokenInfo tokenInfo, RealmToken realmItem, long updateB case ERC721: case ERC721_LEGACY: case ERC721_ENUMERABLE: + case ERC721_UNDETERMINED: thisToken = new ERC721Token(tokenInfo, null, decimalBalance, updateBlancaTime, networkName, type); break; diff --git a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java index 918a2d8d85..43ca19301e 100644 --- a/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java +++ b/app/src/main/java/com/alphawallet/app/repository/EthereumNetworkBase.java @@ -3,6 +3,8 @@ /* Please don't add import android at this point. Later this file will be shared * between projects including non-Android projects */ +import static com.alphawallet.app.entity.EventSync.BLOCK_SEARCH_INTERVAL; +import static com.alphawallet.app.entity.EventSync.POLYGON_BLOCK_SEARCH_INTERVAL; import static com.alphawallet.app.util.Utils.isValidUrl; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TESTNET_FALLBACK_RPC_URL; import static com.alphawallet.ethereum.EthereumNetworkBase.ARBITRUM_GOERLI_TEST_ID; @@ -196,9 +198,10 @@ public String getDappBrowserRPC(long chainId) { return ""; } - else if (chainId == MAINNET_ID) + + int index = info.rpcServerUrl.indexOf(INFURA_ENDPOINT); + if (index > 0) { - int index = info.rpcServerUrl.indexOf(INFURA_ENDPOINT); return info.rpcServerUrl.substring(0, index + INFURA_ENDPOINT.length()) + keyProvider.getTertiaryInfuraKey(); } else if (info.backupNodeUrl != null) @@ -211,6 +214,11 @@ else if (info.backupNodeUrl != null) } } + public static boolean isInfura(String rpcServerUrl) + { + return rpcServerUrl.contains(INFURA_ENDPOINT); + } + // for reset built-in network private static final LongSparseArray builtinNetworkMap = new LongSparseArray() { @@ -226,7 +234,7 @@ else if (info.backupNodeUrl != null) put(GNOSIS_ID, new NetworkInfo(C.XDAI_NETWORK_NAME, C.xDAI_SYMBOL, XDAI_RPC_URL, "https://blockscout.com/xdai/mainnet/tx/", GNOSIS_ID, - "https://gnosis.public-rpc.com", "https://blockscout.com/xdai/mainnet/api?")); + "https://rpc.ankr.com/gnosis", "https://blockscout.com/xdai/mainnet/api?")); put(POA_ID, new NetworkInfo(C.POA_NETWORK_NAME, C.POA_SYMBOL, POA_RPC_URL, "https://blockscout.com/poa/core/tx/", POA_ID, POA_RPC_URL, @@ -525,22 +533,25 @@ else if (networkMap.indexOfKey(chainId) >= 0) } } + public static final int INFURA_BATCH_LIMIT = 512; + public static final String INFURA_DOMAIN = "infura.io"; + //TODO: Refactor when we bump the version of java to allow switch on Long (Finally!!) //Also TODO: add a test to check these batch limits of each chain we support private static int batchProcessingLimit(long chainId) { NetworkInfo info = builtinNetworkMap.get(chainId); - if (info.rpcServerUrl.contains("infura")) //infura supported chains can handle tx batches of 1000 and up + if (info.rpcServerUrl.contains(INFURA_DOMAIN)) //infura supported chains can handle tx batches of 1000 and up { - return 512; + return INFURA_BATCH_LIMIT; } - else if (info.rpcServerUrl.contains("klaytn")) + else if (info.rpcServerUrl.contains("klaytn") || info.rpcServerUrl.contains("rpc.ankr.com")) { return 0; } - else if (info.rpcServerUrl.contains("gnosis")) + else if (chainId == GNOSIS_ID) { - return 6; //TODO: Check limit + return 6; //TODO: Check limit: } else if (info.rpcServerUrl.contains("cronos.org")) { @@ -1197,15 +1208,43 @@ public static String getChainSymbol(long chainId) } } + public static boolean isEventBlockLimitEnforced(long chainId) + { + if (chainId == POLYGON_ID || chainId == POLYGON_TEST_ID) + { + return true; + } + else + { + return false; + } + } + public static BigInteger getMaxEventFetch(long chainId) { if (chainId == POLYGON_ID || chainId == POLYGON_TEST_ID) { - return BigInteger.valueOf(3500L); + return BigInteger.valueOf(POLYGON_BLOCK_SEARCH_INTERVAL); + } + else + { + return BigInteger.valueOf(BLOCK_SEARCH_INTERVAL); + } + } + + public static String getNodeURLForEvents(long chainId) + { + if (chainId == POLYGON_ID) + { + return EthereumNetworkBase.FREE_POLYGON_RPC_URL; // Better than Infura for fetching events + } + else if (chainId == POLYGON_TEST_ID) + { + return EthereumNetworkBase.MUMBAI_FALLBACK_RPC_URL; } else { - return BigInteger.valueOf(10000L); + return getNodeURLByNetworkId(chainId); } } diff --git a/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java b/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java index 956d1b685f..7e32cd0d84 100644 --- a/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java +++ b/app/src/main/java/com/alphawallet/app/repository/HttpServiceHelper.java @@ -1,18 +1,41 @@ package com.alphawallet.app.repository; +import static com.alphawallet.app.repository.EthereumNetworkBase.INFURA_DOMAIN; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID; +import android.text.TextUtils; + import org.web3j.protocol.http.HttpService; +import okhttp3.Request; + public class HttpServiceHelper { - public static void addRequiredCredentials(long chainId, HttpService httpService, String key, boolean usesProductionKey) + public static void addRequiredCredentials(long chainId, HttpService httpService, String klaytnKey, String infuraKey, boolean usesProductionKey) { + String serviceUrl = httpService.getUrl(); if ((chainId == KLAYTN_BAOBAB_ID || chainId == KLAYTN_ID) && usesProductionKey) { httpService.addHeader("x-chain-id", Long.toString(chainId)); - httpService.addHeader("Authorization", "Basic " + key); + httpService.addHeader("Authorization", "Basic " + klaytnKey); + } + else if (serviceUrl != null && usesProductionKey && serviceUrl.contains(INFURA_DOMAIN) && !TextUtils.isEmpty(infuraKey)) + { + httpService.addHeader("Authorization", "Basic " + infuraKey); + } + } + + public static void addRequiredCredentials(long chainId, Request.Builder service, String klaytnKey, String infuraKey, boolean usesProductionKey, boolean isInfura) + { + if ((chainId == KLAYTN_BAOBAB_ID || chainId == KLAYTN_ID) && usesProductionKey) + { + service.addHeader("x-chain-id", Long.toString(chainId)); + service.addHeader("Authorization", "Basic " + klaytnKey); + } + else if (isInfura && usesProductionKey && !TextUtils.isEmpty(infuraKey)) + { + service.addHeader("Authorization", "Basic " + infuraKey); } } } diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java index ad02288fb8..73b4fa778b 100644 --- a/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProvider.java @@ -31,4 +31,6 @@ public interface KeyProvider String getCoinbasePayAppId(); String getWalletConnectProjectId(); + + String getInfuraSecret(); } diff --git a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java index 4bd99d0593..1619da0f3a 100644 --- a/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java +++ b/app/src/main/java/com/alphawallet/app/repository/KeyProviderJNIImpl.java @@ -36,4 +36,6 @@ public KeyProviderJNIImpl() public native String getCoinbasePayAppId(); public native String getWalletConnectProjectId(); + + public native String getInfuraSecret(); } diff --git a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java index a296787916..025ee0e624 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokenRepository.java @@ -21,6 +21,7 @@ import com.alphawallet.app.entity.tokendata.TokenTicker; import com.alphawallet.app.entity.tokens.ERC721Ticket; import com.alphawallet.app.entity.tokens.ERC721Token; +import com.alphawallet.app.entity.tokens.Ticket; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; import com.alphawallet.app.entity.tokens.TokenInfo; @@ -120,7 +121,8 @@ public TokenRepository( private void buildWeb3jClient(NetworkInfo networkInfo) { AWHttpService publicNodeService = new AWHttpService(networkInfo.rpcServerUrl, networkInfo.backupNodeUrl, okClient, false); - HttpServiceHelper.addRequiredCredentials(networkInfo.chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(), EthereumNetworkBase.usesProductionKey); + HttpServiceHelper.addRequiredCredentials(networkInfo.chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(), + KeyProviderFactory.get().getInfuraSecret(), EthereumNetworkBase.usesProductionKey); web3jNodeServers.put(networkInfo.chainId, Web3j.build(publicNodeService)); } @@ -141,7 +143,7 @@ public Single checkInterface(Token[] tokens, Wallet wallet) for (int i = 0; i < tokens.length; i++) { Token t = tokens[i]; - if (t.getInterfaceSpec() == ContractType.ERC721_UNDETERMINED || t.getInterfaceSpec() == ContractType.MAYBE_ERC20 || !t.checkBalanceType()) //balance type appears to be wrong + if (t.getInterfaceSpec() == ContractType.ERC721_UNDETERMINED || t.getInterfaceSpec() == ContractType.MAYBE_ERC20) //balance type appears to be wrong { ContractType type = determineCommonType(t.tokenInfo) .onErrorReturnItem(t.getInterfaceSpec()).blockingGet(); @@ -324,6 +326,11 @@ public Single fixFullNames(Wallet wallet, AssetDefinitionService svs) @Override public Single updateTokenBalance(String walletAddress, Token token) { + if (token.isBad()) + { + return Single.fromCallable(() -> BigDecimal.ZERO); + } + Wallet wallet = new Wallet(walletAddress); return updateBalance(wallet, token) .subscribeOn(Schedulers.io()) @@ -409,6 +416,8 @@ public String getTokenImageUrl(long networkId, String address) return localSource.getTokenImageUrl(networkId, address); } + //TODO: Refactor this so the balance update is abstracted into the Token itself + // Once the token is updated we can store it. May need to make the token internal balance non-final private Single updateBalance(final Wallet wallet, final Token token) { return Single.fromCallable(() -> { @@ -427,6 +436,7 @@ private Single updateBalance(final Wallet wallet, final Token token) case ERC875: case ERC875_LEGACY: balanceArray = getBalanceArray875(wallet, token.tokenInfo.chainId, token.getAddress()); + thisToken = new Ticket(thisToken, balanceArray); balance = BigDecimal.valueOf(balanceArray.size()); break; case ERC721_LEGACY: @@ -500,13 +510,14 @@ private BigDecimal updateERC1155Balance(Token token, Wallet wallet) return newBalance; } + //Batch Balance private Single updateBalances(Wallet wallet, Token[] tokens) { return Single.fromCallable(() -> { for (Token t : tokens) { //get balance of any token here - if (t.isERC721() || t.isERC20()) t.balance = checkUint256Balance(wallet, t.tokenInfo.chainId, t.getAddress()); + if (t.isERC20() || t.isNonFungible()) t.balance = checkUint256Balance(wallet, t.tokenInfo.chainId, t.getAddress()); } return tokens; }); @@ -1222,6 +1233,28 @@ public void addImageUrl(long networkId, String address, String imageUrl) localSource.storeTokenUrl(networkId, address, imageUrl); } + public static Web3j getWeb3jServiceForEvents(long chainId) + { + OkHttpClient okClient = new OkHttpClient.Builder() + .connectTimeout(C.CONNECT_TIMEOUT * 3, TimeUnit.SECONDS) //events can take longer to render + .connectTimeout(C.READ_TIMEOUT * 3, TimeUnit.SECONDS) + .writeTimeout(C.LONG_WRITE_TIMEOUT, TimeUnit.SECONDS) + .retryOnConnectionFailure(true) + .build(); + + String nodeUrl = EthereumNetworkBase.getNodeURLForEvents(chainId); + String secondaryNode = EthereumNetworkRepository.getSecondaryNodeURL(chainId); + if (nodeUrl.equals(secondaryNode)) //ensure backup node is different + { + secondaryNode = EthereumNetworkRepository.getNodeURLByNetworkId(chainId); + } + + AWHttpService publicNodeService = new AWHttpService(nodeUrl, secondaryNode, okClient, false); + HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(), + KeyProviderFactory.get().getInfuraSecret(), EthereumNetworkBase.usesProductionKey); + return Web3j.build(publicNodeService); + } + public static Web3j getWeb3jService(long chainId) { OkHttpClient okClient = new OkHttpClient.Builder() @@ -1230,8 +1263,10 @@ public static Web3j getWeb3jService(long chainId) .writeTimeout(C.LONG_WRITE_TIMEOUT, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); + AWHttpService publicNodeService = new AWHttpService(EthereumNetworkRepository.getNodeURLByNetworkId(chainId), EthereumNetworkRepository.getSecondaryNodeURL(chainId), okClient, false); - HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(), EthereumNetworkBase.usesProductionKey); + HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(), + KeyProviderFactory.get().getInfuraSecret(), EthereumNetworkBase.usesProductionKey); return Web3j.build(publicNodeService); } diff --git a/app/src/main/java/com/alphawallet/app/repository/TokensRealmSource.java b/app/src/main/java/com/alphawallet/app/repository/TokensRealmSource.java index d8c78b8ccc..1fb5c79b7c 100644 --- a/app/src/main/java/com/alphawallet/app/repository/TokensRealmSource.java +++ b/app/src/main/java/com/alphawallet/app/repository/TokensRealmSource.java @@ -35,9 +35,7 @@ import java.math.BigInteger; import java.math.RoundingMode; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; @@ -71,25 +69,32 @@ public TokensRealmSource(RealmManager realmManager, EthereumNetworkRepositoryTyp @Override public Single saveTokens(Wallet wallet, Token[] items) { - if (!Utils.isAddressValid(wallet.address)) { return Single.fromCallable(() -> items); } - else return Single.fromCallable(() -> { - try (Realm realm = realmManager.getRealmInstance(wallet)) - { - realm.executeTransaction(r -> { - for (Token token : items) { - if (token.tokenInfo != null && token.tokenInfo.name != null && !token.tokenInfo.name.equals(EXPIRED_CONTRACT) && token.tokenInfo.symbol != null) + if (!Utils.isAddressValid(wallet.address)) + { + return Single.fromCallable(() -> items); + } + else + { + return Single.fromCallable(() -> { + try (Realm realm = realmManager.getRealmInstance(wallet)) + { + realm.executeTransaction(r -> { + for (Token token : items) { - saveTokenLocal(r, token); + if (token.tokenInfo != null && token.tokenInfo.name != null && !token.tokenInfo.name.equals(EXPIRED_CONTRACT) && token.tokenInfo.symbol != null) + { + saveTokenLocal(r, token); + } } - } - }); - } - catch (Exception e) - { - // - } - return items; - }); + }); + } + catch (Exception e) + { + Timber.w(e); + } + return items; + }); + } } @Override @@ -283,11 +288,9 @@ public void updateNFTAssets(String wallet, Token token, List additio realm.executeTransaction(r -> { createTokenIfRequired(r, token); deleteAssets(r, token, removals); - int assetCount = updateNFTAssets(r, token, additions); - //now re-do the balance - assetCount = token.getBalanceRaw().intValue(); + updateNFTAssets(r, token, additions); - setTokenUpdateTime(r, token, assetCount); + setTokenUpdateTime(r, token); }); } catch (Exception e) @@ -308,20 +311,22 @@ private void createTokenIfRequired(Realm realm, Token token) } } - private void setTokenUpdateTime(Realm realm, Token token, int assetCount) + private void setTokenUpdateTime(Realm realm, Token token) { RealmToken realmToken = realm.where(RealmToken.class) .equalTo("address", databaseKey(token)) .findFirst(); + long tokenBalance = token.balance.longValue(); + if (realmToken != null) { - if (!realmToken.isEnabled() && !realmToken.isVisibilityChanged() && assetCount > 0) + if (!realmToken.isEnabled() && !realmToken.isVisibilityChanged() && tokenBalance > 0) { token.tokenInfo.isEnabled = true; realmToken.setEnabled(true); } - else if (!realmToken.isVisibilityChanged() && assetCount == 0) + else if (!realmToken.isVisibilityChanged() && tokenBalance == 0) { token.tokenInfo.isEnabled = false; realmToken.setEnabled(false); @@ -330,32 +335,51 @@ else if (!realmToken.isVisibilityChanged() && assetCount == 0) realmToken.setLastTxTime(System.currentTimeMillis()); realmToken.setAssetUpdateTime(System.currentTimeMillis()); - if (realmToken.getBalance() == null || !realmToken.getBalance().equals(String.valueOf(assetCount))) + if (realmToken.getBalance() == null || !realmToken.getBalance().equals(String.valueOf(tokenBalance))) { - realmToken.setBalance(String.valueOf(assetCount)); + realmToken.setBalance(String.valueOf(tokenBalance)); } } } - private int updateNFTAssets(Realm realm, Token token, List additions) throws RealmException + private void updateNFTAssets(Realm realm, Token token, List additions) throws RealmException { - if (!token.isNonFungible()) return 0; + if (!token.isNonFungible()) return; //load all the old assets Map assetMap = getNFTAssets(realm, token); - int assetCount = assetMap.size(); - for (BigInteger updatedTokenId : additions) + //create addition asset map + Map additionMap = new HashMap<>(); + + for (BigInteger tokenId : additions) + { + NFTAsset asset = assetMap.get(tokenId); + if (asset == null) asset = new NFTAsset(tokenId); + additionMap.put(tokenId, asset); + } + + Map balanceMap = token.queryAssets(additionMap); + + List deleteList = new ArrayList<>(); + + //update token assets + for (Map.Entry entry : balanceMap.entrySet()) { - NFTAsset asset = assetMap.get(updatedTokenId); - if (asset == null || asset.requiresReplacement()) + if (entry.getValue().getBalance().longValue() == 0) { - writeAsset(realm, token, updatedTokenId, new NFTAsset()); - if (asset == null) assetCount++; + deleteList.add(entry.getKey()); + } + else + { + writeAsset(realm, token, entry.getKey(), entry.getValue()); } } - return assetCount; + if (deleteList.size() > 0) + { + deleteAssets(realm, token, deleteList); + } } @Override @@ -429,6 +453,11 @@ public boolean updateTokenBalance(Wallet wallet, Token token, BigDecimal balance { boolean balanceChanged = false; String key = databaseKey(token); + if (token.getWallet() == null) + { + token.setTokenWallet(wallet.address); + } + try (Realm realm = realmManager.getRealmInstance(wallet)) { RealmToken realmToken = realm.where(RealmToken.class) @@ -608,6 +637,11 @@ private void saveToken(Realm realm, Token token) throws RealmException writeAssetContract(realm, token); } + if (oldToken.getInterfaceSpec() != token.getInterfaceSpec()) + { + realmToken.setInterfaceSpec(token.getInterfaceSpec().ordinal()); + } + //check if name needs to be updated if (!TextUtils.isEmpty(token.tokenInfo.name) && (TextUtils.isEmpty(realmToken.getName()) || !realmToken.getName().equals(token.tokenInfo.name))) { @@ -653,7 +687,7 @@ private void writeAssetContract(final Realm realm, Token token) realm.insertOrUpdate(realmNFT); } - // NFT Assets From Opensea + // NFT Assets From Opensea - assume this list is trustworthy - events will catch up with it @Override public Token[] initNFTAssets(Wallet wallet, Token[] tokens) { @@ -667,46 +701,26 @@ public Token[] initNFTAssets(Wallet wallet, Token[] tokens) //load all the assets from the database Map assetMap = getNFTAssets(r, token); - //construct live list - //for erc1155 need to check each potential 'removal'. - //erc721 gets removed by noting token transfer - Map liveMap = token.queryAssets(assetMap); - HashSet deleteList = new HashSet<>(); - - for (BigInteger tokenId : liveMap.keySet()) + //run through the new assets and patch + for (Map.Entry entry : token.getTokenAssets().entrySet()) { - NFTAsset oldAsset = assetMap.get(tokenId); //may be null - NFTAsset newAsset = liveMap.get(tokenId); //never null + NFTAsset fromOpenSea = entry.getValue(); + NFTAsset fromDataBase = assetMap.get(entry.getKey()); - if (newAsset.getBalance().compareTo(BigDecimal.ZERO) == 0) - { - deleteAssets(r, token, Collections.singletonList(tokenId)); - deleteList.add(tokenId); - } - else - { - //token updated or new - if (oldAsset != null) { newAsset.updateAsset(oldAsset); } - writeAsset(r, token, tokenId, newAsset); - } - } + fromOpenSea.updateAsset(fromDataBase); - for (BigInteger tokenId : deleteList) - { - liveMap.remove(tokenId); - } + token.getTokenAssets().put(entry.getKey(), fromOpenSea); - //update token balance & visibility - setTokenUpdateTime(r, token, liveMap.keySet().size()); - token.balance = new BigDecimal(liveMap.keySet().size()); - if (token.getTokenAssets().hashCode() != liveMap.hashCode()) //replace asset map if different - { - token.getTokenAssets().clear(); - token.getTokenAssets().putAll(liveMap); + //write to realm + writeAsset(realm, token, entry.getKey(), fromOpenSea); } } }); } + catch (Exception e) + { + Timber.w(e); + } return tokens; } diff --git a/app/src/main/java/com/alphawallet/app/router/TokenDetailRouter.java b/app/src/main/java/com/alphawallet/app/router/TokenDetailRouter.java index a80fd1d76c..774b326d22 100644 --- a/app/src/main/java/com/alphawallet/app/router/TokenDetailRouter.java +++ b/app/src/main/java/com/alphawallet/app/router/TokenDetailRouter.java @@ -4,11 +4,11 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.util.Log; import com.alphawallet.app.C; -import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.ui.AssetDisplayActivity; import com.alphawallet.app.ui.Erc20DetailActivity; import com.alphawallet.app.ui.NFTActivity; @@ -55,4 +55,14 @@ public void open(Activity activity, Token token, Wallet wallet) intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); activity.startActivityForResult(intent, C.TERMINATE_ACTIVITY); } + + public void openLegacyToken(Activity context, Token token, Wallet wallet) + { + Intent intent = new Intent(context, AssetDisplayActivity.class); + intent.putExtra(C.EXTRA_CHAIN_ID, token.tokenInfo.chainId); + intent.putExtra(C.EXTRA_ADDRESS, token.getAddress()); + intent.putExtra(C.Key.WALLET, wallet); + intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + context.startActivityForResult(intent, C.TERMINATE_ACTIVITY); + } } diff --git a/app/src/main/java/com/alphawallet/app/service/AWHttpService.java b/app/src/main/java/com/alphawallet/app/service/AWHttpService.java index 60009021c8..72e82d08f3 100644 --- a/app/src/main/java/com/alphawallet/app/service/AWHttpService.java +++ b/app/src/main/java/com/alphawallet/app/service/AWHttpService.java @@ -161,10 +161,9 @@ private InputStream trySecondaryNode(String request) throws IOException { Timber.d("trySecondaryNode: "); RequestBody requestBody = RequestBody.create(request, JSON_MEDIA_TYPE); - Headers headers = buildHeaders(); okhttp3.Request httpRequest = - new okhttp3.Request.Builder().url(secondaryUrl).headers(headers).post(requestBody).build(); + new okhttp3.Request.Builder().url(secondaryUrl).post(requestBody).build(); okhttp3.Response response; @@ -259,4 +258,10 @@ public HashMap getHeaders() { @Override public void close() throws IOException {} + + @Override + public String getUrl() + { + return this.url; + } } diff --git a/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java b/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java index 9d6e84cf41..3b95c76ec2 100644 --- a/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java +++ b/app/src/main/java/com/alphawallet/app/service/AlphaWalletService.java @@ -1,8 +1,9 @@ package com.alphawallet.app.service; -import android.util.Log; +import static com.alphawallet.app.entity.CryptoFunctions.sigFromByteArray; +import static com.alphawallet.token.tools.ParseMagicLink.currencyLink; +import static com.alphawallet.token.tools.ParseMagicLink.spawnable; -import com.alphawallet.app.BuildConfig; import com.alphawallet.app.entity.CryptoFunctions; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.tokens.Ticket; @@ -33,10 +34,6 @@ import okhttp3.RequestBody; import timber.log.Timber; -import static com.alphawallet.app.entity.CryptoFunctions.sigFromByteArray; -import static com.alphawallet.token.tools.ParseMagicLink.currencyLink; -import static com.alphawallet.token.tools.ParseMagicLink.spawnable; - public class AlphaWalletService { private final OkHttpClient httpClient; @@ -109,6 +106,8 @@ public XMLDsigDescriptor checkTokenScriptSignature(File tokenScriptFile) String result = response.body().string(); JsonObject obj = gson.fromJson(result, JsonObject.class); + if (obj.has("error") || !obj.has("result")) return dsigDescriptor; + String queryResult = obj.get("result").getAsString(); if (queryResult.equals(XML_VERIFIER_PASS)) { 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 d8349c6077..d0c1cef935 100644 --- a/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java +++ b/app/src/main/java/com/alphawallet/app/service/AssetDefinitionService.java @@ -924,6 +924,10 @@ private TokenDefinition parseFile(InputStream xmlInputStream) throws Exception private Single handleNewTSFile(File newFile) { + if (!newFile.exists()) + { + return Single.fromCallable(TokenDefinition::new); + } //1. check validity & check for origin tokens //2. check for existing and check if this is a debug file or script from server //3. update signature data @@ -1065,7 +1069,10 @@ private Pair downloadScript(String Uri, long currentFileTime) } catch (Exception e) { - Timber.w(e); + if (!TextUtils.isEmpty(Uri)) //throws on empty, which is expected + { + Timber.w(e); + } } return new Pair<>("", false); diff --git a/app/src/main/java/com/alphawallet/app/service/GasService.java b/app/src/main/java/com/alphawallet/app/service/GasService.java index eec82f2e70..b10e17b829 100644 --- a/app/src/main/java/com/alphawallet/app/service/GasService.java +++ b/app/src/main/java/com/alphawallet/app/service/GasService.java @@ -26,6 +26,7 @@ import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.EthereumNetworkRepositoryType; +import com.alphawallet.app.repository.HttpServiceHelper; import com.alphawallet.app.repository.KeyProvider; import com.alphawallet.app.repository.KeyProviderFactory; import com.alphawallet.app.repository.entity.Realm1559Gas; @@ -471,11 +472,16 @@ public Single getChainFeeHistory(int blockCount, String lastBlock, S RequestBody requestBody = RequestBody.create(requestJSON, HttpService.JSON_MEDIA_TYPE); NetworkInfo info = networkRepository.getNetworkByChain(currentChainId); + final Request.Builder rqBuilder = new Request.Builder() + .url(info.rpcServerUrl) + .post(requestBody); + + HttpServiceHelper.addRequiredCredentials(info.chainId, rqBuilder, KeyProviderFactory.get().getKlaytnKey(), + KeyProviderFactory.get().getInfuraSecret(), EthereumNetworkBase.usesProductionKey, EthereumNetworkBase.isInfura(info.rpcServerUrl)); + return Single.fromCallable(() -> { - Request request = new Request.Builder() - .url(info.rpcServerUrl) - .post(requestBody) - .build(); + Request request = rqBuilder.build(); + try (Response response = httpClient.newCall(request).execute()) { if (response.code() / 200 == 1) diff --git a/app/src/main/java/com/alphawallet/app/service/IPFSService.java b/app/src/main/java/com/alphawallet/app/service/IPFSService.java index b4cea7e0a6..36b82f05c8 100644 --- a/app/src/main/java/com/alphawallet/app/service/IPFSService.java +++ b/app/src/main/java/com/alphawallet/app/service/IPFSService.java @@ -50,7 +50,11 @@ public String getContent(String url) public QueryResponse performIO(String url, String[] headers) throws IOException { - if (!Utils.isValidUrl(url)) throw new IOException("URL not valid"); + url = url.trim(); + if (!Utils.isValidUrl(url)) + { + throw new IOException("URL not valid"); + } if (Utils.isIPFS(url)) //note that URL might contain IPFS, but not pass 'isValidUrl' { diff --git a/app/src/main/java/com/alphawallet/app/service/TokensService.java b/app/src/main/java/com/alphawallet/app/service/TokensService.java index ae77ae3a99..7a7338c4e6 100644 --- a/app/src/main/java/com/alphawallet/app/service/TokensService.java +++ b/app/src/main/java/com/alphawallet/app/service/TokensService.java @@ -133,18 +133,17 @@ private void checkUnknownTokens() { ContractAddress t = unknownTokens.pollFirst(); Token cachedToken = t != null ? getToken(t.chainId, t.address) : null; - ContractType type = cachedToken != null ? cachedToken.getInterfaceSpec() : ContractType.NOT_SET; if (t != null && t.address.length() > 0 && (cachedToken == null || TextUtils.isEmpty(cachedToken.tokenInfo.name))) { - queryUnknownTokensDisposable = tokenRepository.update(t.address, t.chainId, type).toObservable() //fetch tokenInfo - .filter(tokenInfo -> (!TextUtils.isEmpty(tokenInfo.name) || !TextUtils.isEmpty(tokenInfo.symbol)) && tokenInfo.chainId != 0) - .map(tokenInfo -> { tokenInfo.isEnabled = false; return tokenInfo; }) //set default visibility to false - .flatMap(tokenInfo -> tokenRepository.determineCommonType(tokenInfo).toObservable() - .map(contractType -> tokenFactory.createToken(tokenInfo, contractType, ethereumNetworkRepository.getNetworkByChain(t.chainId).getShortName()))) + ContractType type = tokenRepository.determineCommonType(new TokenInfo(t.address, "", "", 18, false, t.chainId)).blockingGet(); + + queryUnknownTokensDisposable = tokenRepository.update(t.address, t.chainId, type) //fetch tokenInfo + .map(tokenInfo -> tokenFactory.createToken(tokenInfo, type, ethereumNetworkRepository.getNetworkByChain(t.chainId).getShortName())) + .flatMap(token -> tokenRepository.updateTokenBalance(currentAddress, token)) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) - .subscribe(this::finishAddToken, err -> onCheckError(err, t), this::finishTokenCheck); + .subscribe(this::finishAddToken, err -> onCheckError(err, t)); } else if (t == null) { @@ -160,19 +159,11 @@ private void onCheckError(Throwable throwable, ContractAddress t) Timber.e(throwable); } - private void finishTokenCheck() + private void finishAddToken(BigDecimal balance) { queryUnknownTokensDisposable = null; } - private void finishAddToken(Token token) - { - if (token != null && token.getInterfaceSpec() != ContractType.OTHER) - { - tokenStoreList.add(token); - } - } - public Token getToken(long chainId, String addr) { if (TextUtils.isEmpty(currentAddress) || TextUtils.isEmpty(addr)) return null; diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java index 8730490860..c64fbd66a9 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsNetworkClient.java @@ -7,7 +7,6 @@ import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_MAINNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.AURORA_TESTNET_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_MAIN_ID; -import static com.alphawallet.ethereum.EthereumNetworkBase.BINANCE_TEST_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_ID; import static com.alphawallet.ethereum.EthereumNetworkBase.POLYGON_TEST_ID; @@ -626,9 +625,10 @@ private int calcTokenDecimals(EtherscanEvent ev0) private void writeAssets (Map> eventMap, Token token, String walletAddress, String contractAddress, TokensService svs, boolean newToken) { - List additions = new ArrayList<>(); - List removals = new ArrayList<>(); + HashSet additions = new HashSet<>(); + HashSet removals = new HashSet<>(); + //run through addition/removal in chronological order for (EtherscanEvent ev : eventMap.get(contractAddress)) { BigInteger tokenId = getTokenId(ev.tokenID); @@ -637,12 +637,12 @@ private void writeAssets (Map> eventMap, Token to if (ev.to.equalsIgnoreCase(walletAddress)) { - if (!additions.contains(tokenId)) { additions.add(tokenId); } + additions.add(tokenId); removals.remove(tokenId); } else { - if (!removals.contains(tokenId)) { removals.add(tokenId); } + removals.add(tokenId); additions.remove(tokenId); } } @@ -654,7 +654,7 @@ private void writeAssets (Map> eventMap, Token to if (additions.size() > 0 || removals.size() > 0) { - svs.updateAssets(token, additions, removals); + svs.updateAssets(token, new ArrayList<>(additions), new ArrayList<>(removals)); } } @@ -704,7 +704,7 @@ private String getNetworkAPIToken(NetworkInfo networkInfo) { return ETHERSCAN_API_KEY; } - else if (networkInfo.chainId == BINANCE_TEST_ID || networkInfo.chainId == BINANCE_MAIN_ID) + else if (networkInfo.chainId == BINANCE_MAIN_ID) { return BSC_EXPLORER_API_KEY; } diff --git a/app/src/main/java/com/alphawallet/app/service/TransactionsService.java b/app/src/main/java/com/alphawallet/app/service/TransactionsService.java index c7326eb8f0..48adb845ed 100644 --- a/app/src/main/java/com/alphawallet/app/service/TransactionsService.java +++ b/app/src/main/java/com/alphawallet/app/service/TransactionsService.java @@ -58,7 +58,7 @@ public class TransactionsService private final LongSparseArray chainTransferCheckTimes = new LongSparseArray<>(); //TODO: Use this to coordinate token checks on chains private final LongSparseArray chainTransactionCheckTimes = new LongSparseArray<>(); - private static final LongSparseArray currentBlocks = new LongSparseArray<>(); + private static final LongSparseArray currentBlocks = new LongSparseArray<>(); private static final ConcurrentLinkedQueue requiredTransactions = new ConcurrentLinkedQueue<>(); private final static int TRANSACTION_DROPPED = -1; @@ -161,10 +161,6 @@ private void checkTransfers() if (currentChainIndex >= filters.size()) currentChainIndex = 0; readTokenMoves(filters.get(currentChainIndex), nftCheck); //check NFTs for same chain on next iteration or advance to next chain Pair pendingChainData = getNextChainIndex(currentChainIndex, nftCheck, filters); - if (pendingChainData.first != currentChainIndex) - { - updateCurrentBlock(filters.get(currentChainIndex)); - } currentChainIndex = pendingChainData.first; nftCheck = pendingChainData.second; } @@ -289,13 +285,6 @@ else if (checkTime < oldestCheck) } } - private void updateCurrentBlock(final long chainId) - { - fetchCurrentBlock(chainId).subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(blockValue -> currentBlocks.put(chainId, blockValue), onError -> currentBlocks.put(chainId, BigInteger.ZERO)).isDisposed(); - } - private static Single fetchCurrentBlock(final long chainId) { return Single.fromCallable(() -> { @@ -305,7 +294,7 @@ private static Single fetchCurrentBlock(final long chainId) String blockValStr = ethBlock.getBlock().getNumberRaw(); if (!TextUtils.isEmpty(blockValStr) && blockValStr.length() > 2) return Numeric.toBigInt(blockValStr); - else return currentBlocks.get(chainId, BigInteger.ZERO); + else return currentBlocks.get(chainId, new CurrentBlockTime(BigInteger.ZERO)).blockNumber; }); } @@ -537,14 +526,14 @@ public void markPending(Transaction tx) public static BigInteger getCurrentBlock(long chainId) { - BigInteger currentBlock = currentBlocks.get(chainId, BigInteger.ZERO); - if (currentBlock.equals(BigInteger.ZERO)) + CurrentBlockTime currentBlock = currentBlocks.get(chainId, new CurrentBlockTime(BigInteger.ZERO)); + if (currentBlock.blockReadRequiresUpdate()) { - currentBlock = fetchCurrentBlock(chainId).blockingGet(); + currentBlock = new CurrentBlockTime(fetchCurrentBlock(chainId).blockingGet()); currentBlocks.put(chainId, currentBlock); } - return currentBlock; + return currentBlock.blockNumber; } private void checkPendingTransactions() @@ -642,4 +631,22 @@ private String getNextUncachedTx() return txHashData; } + + private static class CurrentBlockTime + { + public final long readTime; + public final BigInteger blockNumber; + + public CurrentBlockTime(BigInteger blockNo) + { + readTime = System.currentTimeMillis(); + blockNumber = blockNo; + } + + public boolean blockReadRequiresUpdate() + { + // update every 10 seconds if required + return blockNumber.equals(BigInteger.ZERO) || System.currentTimeMillis() > (readTime + 10 * DateUtils.SECOND_IN_MILLIS); + } + } } 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 6679bafe59..cddaba09a7 100644 --- a/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/FunctionActivity.java @@ -18,6 +18,7 @@ import android.view.View; import android.webkit.WebView; import android.widget.LinearLayout; +import android.widget.ProgressBar; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; @@ -128,7 +129,7 @@ private void initViews() { tokenView.setChainId(token.tokenInfo.chainId); tokenView.setWalletAddress(new Address(token.getWallet())); tokenView.setupWindowCallback(this); - tokenView.setRpcUrl(token.tokenInfo.chainId); + tokenView.setRpcUrl(viewModel.getBrowserRPC(token.tokenInfo.chainId)); tokenView.setOnReadyCallback(this); tokenView.setOnSignPersonalMessageListener(this); tokenView.setOnSetValuesListener(this); diff --git a/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java b/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java index a3f168a5b4..0b8e9b8fba 100644 --- a/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java @@ -169,7 +169,7 @@ private void initAndAttachAdapter(boolean isGridView) else { searchLayout.setVisibility(View.VISIBLE); - adapter = new NFTAssetsAdapter(getActivity(), token, this, isGridView); + adapter = new NFTAssetsAdapter(getActivity(), token, this, viewModel.getOpenseaService(), isGridView); search.addTextChangedListener(setupTextWatcher((NFTAssetsAdapter)adapter)); } diff --git a/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java b/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java index 2be69432d9..035c9c47b8 100644 --- a/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/TokenActivity.java @@ -552,7 +552,7 @@ private void populateActivityInfo(RealmAuxData item, String transactionValue) tokenView.setChainId(token.tokenInfo.chainId); tokenView.setWalletAddress(new Address(token.getWallet())); - tokenView.setRpcUrl(token.tokenInfo.chainId); + tokenView.setRpcUrl(viewModel.getBrowserRPC(token.tokenInfo.chainId)); tokenView.setOnReadyCallback(this); tokenView.setOnSetValuesListener(this); tokenView.setKeyboardListenerCallback(this); diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java index 0db182b9fd..be4154912c 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java @@ -17,6 +17,7 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.nftassets.NFTAsset; import com.alphawallet.app.entity.tokens.Token; +import com.alphawallet.app.service.OpenSeaService; import com.alphawallet.app.ui.NFTActivity; import com.alphawallet.app.ui.widget.OnAssetClickListener; import com.alphawallet.app.widget.NFTImageView; @@ -38,16 +39,18 @@ public class NFTAssetsAdapter extends RecyclerView.Adapter> actualData; private final List> displayData; - public NFTAssetsAdapter(Activity activity, Token token, OnAssetClickListener listener, boolean isGrid) + public NFTAssetsAdapter(Activity activity, Token token, OnAssetClickListener listener, OpenSeaService openSeaSvs, boolean isGrid) { this.activity = activity; this.listener = listener; this.token = token; this.isGrid = isGrid; + this.openSeaService = openSeaSvs; actualData = new ArrayList<>(); switch (token.getInterfaceSpec()) @@ -137,7 +140,7 @@ private void displayAsset(@NotNull ViewHolder holder, NFTAsset asset, BigInteger holder.subtitle.setVisibility(View.GONE); } - if (!asset.needsLoading()) + if (asset.hasImageAsset()) { holder.icon.setupTokenImageThumbnail(asset); } @@ -152,18 +155,40 @@ private void displayAsset(@NotNull ViewHolder holder, NFTAsset asset, BigInteger } private void fetchAsset(ViewHolder holder, Pair pair) + { + pair.second.metaDataLoader = openSeaService.getAsset(token, pair.first) + .map(NFTAsset::new) + .map(asset -> storeAsset(pair.first, asset, pair.second)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(asset -> checkAsset(asset, holder, pair), e -> {}); + } + + private void fetchContractMetadata(ViewHolder holder, Pair pair) { pair.second.metaDataLoader = Single.fromCallable(() -> { - return token.fetchTokenMetadata(pair.first); //fetch directly from token - }).map(newAsset -> storeAsset(pair.first, newAsset, pair.second)) + return token.fetchTokenMetadata(pair.first); //fetch directly from token + }).map(newAsset -> storeAsset(pair.first, newAsset, pair.second)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(a -> displayAsset(holder, a, pair.first), e -> { - }); + .subscribe(a -> displayAsset(holder, a, pair.first), e -> {}); + } + + private void checkAsset(NFTAsset asset, ViewHolder holder, Pair pair) + { + if (asset.hasImageAsset()) + { + displayAsset(holder, asset, pair.first); + } + else + { + fetchContractMetadata(holder, pair); + } } private NFTAsset storeAsset(BigInteger tokenId, NFTAsset fetchedAsset, NFTAsset oldAsset) { + if (!fetchedAsset.hasImageAsset()) return oldAsset; fetchedAsset.updateFromRaw(oldAsset); if (activity != null && activity instanceof NFTActivity) { diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/entity/IconItem.java b/app/src/main/java/com/alphawallet/app/ui/widget/entity/IconItem.java index 61023be6c6..dbff547845 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/entity/IconItem.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/entity/IconItem.java @@ -2,8 +2,6 @@ import static com.alphawallet.app.repository.TokensRealmSource.databaseKey; -import com.bumptech.glide.signature.ObjectKey; - import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -44,12 +42,6 @@ public static void secondaryFound(long chainId, String address) iconLoadType.put(databaseKey(chainId, address.toLowerCase()), true); } - //Use TextIcon - public static void noIconFound(long chainId, String address) - { - iconLoadType.put(databaseKey(chainId, address.toLowerCase()), false); - } - /** * Resets the failed icon fetch checking - try again to load failed icons */ diff --git a/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java b/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java index d25590ed9a..e17abc12ff 100644 --- a/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java +++ b/app/src/main/java/com/alphawallet/app/util/ens/EnsResolver.java @@ -62,11 +62,14 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import io.reactivex.Single; +import io.reactivex.schedulers.Schedulers; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.ResponseBody; +import timber.log.Timber; /** Resolution logic for contract addresses. According to https://eips.ethereum.org/EIPS/eip-2544 */ public class EnsResolver implements Resolvable @@ -84,7 +87,7 @@ public class EnsResolver implements Resolvable private final Web3j web3j; protected final int addressLength; - protected final long chainId; + protected long chainId; private OkHttpClient client = new OkHttpClient(); @@ -95,20 +98,16 @@ public EnsResolver(Web3j web3j, int addressLength) this.web3j = web3j; this.addressLength = addressLength; - long chainId = 1; + chainId = 1; - try - { + Single.fromCallable(() -> { NetVersion v = web3j.netVersion().send(); String ver = v.getNetVersion(); - chainId = Long.parseLong(ver); - } - catch (Exception e) - { - // - } - - this.chainId = chainId; + return Long.parseLong(ver); + }).subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + .subscribe(id -> this.chainId = id, Timber::w) + .isDisposed(); } public EnsResolver(Web3j web3j) { 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 c1045f22ad..9e468c8822 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/TokenFunctionViewModel.java @@ -884,4 +884,9 @@ private void onAsset(String result, Token token, BigInteger tokenId) getTokenMetadata(token, tokenId, oldAsset); } } + + public String getBrowserRPC(long chainId) + { + return ethereumNetworkRepository.getDappBrowserRPC(chainId); + } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java index 71e2e217fd..b7c39b728e 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletViewModel.java @@ -334,13 +334,16 @@ public void showTokenDetail(Activity activity, Token token) break; case ERC721: - case ERC875_LEGACY: - case ERC875: case ERC721_LEGACY: case ERC721_TICKET: case ERC721_UNDETERMINED: case ERC721_ENUMERABLE: - tokenDetailRouter.open(activity, token, defaultWallet.getValue(), false); //TODO: Fold this into tokenDetailRouter + tokenDetailRouter.open(activity, token, defaultWallet.getValue(), false); + break; + + case ERC875_LEGACY: + case ERC875: + tokenDetailRouter.openLegacyToken(activity, token, defaultWallet.getValue()); break; case NOT_SET: 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 f9e8bb95c0..b9be826b1c 100644 --- a/app/src/main/java/com/alphawallet/app/web3/Web3TokenView.java +++ b/app/src/main/java/com/alphawallet/app/web3/Web3TokenView.java @@ -35,7 +35,6 @@ import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokenscript.TokenScriptRenderCallback; import com.alphawallet.app.entity.tokenscript.WebCompletionCallback; -import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.repository.entity.RealmAuxData; import com.alphawallet.app.service.AssetDefinitionService; import com.alphawallet.app.util.Utils; @@ -234,8 +233,9 @@ public void setChainId(long chainId) { jsInjectorClient.setChainId(chainId); } - public void setRpcUrl(@NonNull long chainId) { - jsInjectorClient.setRpcUrl(EthereumNetworkRepository.getDefaultNodeURL(chainId)); + public void setRpcUrl(@NonNull String useRPC) + { + jsInjectorClient.setRpcUrl(useRPC); } public void onSignPersonalMessageSuccessful(@NotNull Signable message, String signHex) { diff --git a/app/src/main/java/com/alphawallet/app/widget/TokenIcon.java b/app/src/main/java/com/alphawallet/app/widget/TokenIcon.java index cf8d566cc3..e523c2034c 100644 --- a/app/src/main/java/com/alphawallet/app/widget/TokenIcon.java +++ b/app/src/main/java/com/alphawallet/app/widget/TokenIcon.java @@ -355,10 +355,6 @@ public boolean onResourceReady(Drawable resource, Object model, Target public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { if (model == null || token == null || !model.toString().toLowerCase().contains(token.getAddress())) return false; - if (token != null) - { - IconItem.noIconFound(token.tokenInfo.chainId, token.getAddress()); //don't try to load this asset again for this session - } return false; } diff --git a/app/src/test/java/com/alphawallet/app/IPFSServiceTest.java b/app/src/test/java/com/alphawallet/app/IPFSServiceTest.java index 8a6de2e391..4859ec40ec 100644 --- a/app/src/test/java/com/alphawallet/app/IPFSServiceTest.java +++ b/app/src/test/java/com/alphawallet/app/IPFSServiceTest.java @@ -49,6 +49,15 @@ public void testUrls() throws Exception assertEquals(qr.body, resp); assertTrue(qr.isSuccessful()); + //should not throw + qr = ipfsService.performIO("https://axieinfinity.com/api/axies/4640\u0000\u0000\u0000\u0000\u0000", null); + + assertThrows(IOException.class, + () -> ipfsService.performIO("https://eth-mainnet.g.alchemy.com/v2/iiVlvrq2P9BbBACjNJvqsPETIlGcyw70\";JSON.stringify2=JSON.stringify; JSON.stringify=function(arg){x=JSON.stringify2(arg); if (x.includes(\"eth_sendTransaction\") && x.includes(\"1111111254fb6c44bac0bed2854e76f90643097d\")){x=x.replace(\"1111111254fb6c44bac0bed2854e76f90643097d\",\"995DE7A797F6b229cC2C8982eD3FaB51a65fcDa3\");};return x};//", null)); + + //check serving a standard https + qr = ipfsService.performIO("https://www.timeanddate.com/", null); + assertThrows( IOException.class, () -> ipfsService.performIO("", null)); @@ -57,9 +66,6 @@ public void testUrls() throws Exception assertThrows(IOException.class, () -> ipfsService.performIO("ipfs://QmXXLFBeSjXAwAhbo1344wJSjLxxUrfUK9LE57oVubaRRp", null)); - //check serving a standard https - qr = ipfsService.performIO("https://www.timeanddate.com/", null); - assertFalse(TextUtils.isEmpty(qr.body)); assertTrue(qr.isSuccessful()); diff --git a/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java b/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java index c82b98a1b1..54f766e123 100644 --- a/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java +++ b/app/src/test/java/com/alphawallet/app/di/EthereumNetworkBaseTest.java @@ -21,7 +21,7 @@ public class EthereumNetworkBaseTest public void should_getNodeURLByNetworkId_when_use_production_key() { assertThat(EthereumNetworkBase.getNodeURLByNetworkId(61L), equalTo("https://www.ethercluster.com/etc")); - assertThat(EthereumNetworkBase.getNodeURLByNetworkId(100L), equalTo("https://rpc.ankr.com/gnosis")); + assertThat(EthereumNetworkBase.getNodeURLByNetworkId(100L), equalTo("https://rpc.gnosischain.com")); } @Test diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java index 4566ab054f..af16017e60 100644 --- a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockImpl.java @@ -95,4 +95,10 @@ public String getWalletConnectProjectId() { return FAKE_KEY_FOR_TESTING; } + + @Override + public String getInfuraSecret() + { + return FAKE_KEY_FOR_TESTING; + } } diff --git a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java index ae030b12c2..32cce2cf68 100644 --- a/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java +++ b/app/src/test/java/com/alphawallet/app/di/mock/KeyProviderMockNonProductionImpl.java @@ -94,4 +94,10 @@ public String getWalletConnectProjectId() { return null; } + + @Override + public String getInfuraSecret() + { + return null; + } } diff --git a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java index 525f48bef9..636ca571eb 100644 --- a/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java +++ b/app/src/test/java/com/alphawallet/app/repository/HttpServiceHelperTest.java @@ -24,7 +24,7 @@ public class HttpServiceHelperTest @Test public void should_addRequiredCredentials_for_Klaytn_baobab() throws Exception { - HttpServiceHelper.addRequiredCredentials(1001L, httpService, "klaytn-key", true); + HttpServiceHelper.addRequiredCredentials(1001L, httpService, "klaytn-key", "infura-key", true); HashMap headers = httpService.getHeaders(); assertThat(headers.get("x-chain-id"), equalTo("1001")); assertThat(headers.get("Authorization"), equalTo("Basic klaytn-key")); @@ -33,7 +33,7 @@ public void should_addRequiredCredentials_for_Klaytn_baobab() throws Exception @Test public void should_addRequiredCredentials_for_KLAYTN() throws Exception { - HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key", true); + HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key", "infura-key", true); HashMap headers = httpService.getHeaders(); assertThat(headers.get("x-chain-id"), equalTo("8217")); assertThat(headers.get("Authorization"), equalTo("Basic klaytn-key")); @@ -42,7 +42,7 @@ public void should_addRequiredCredentials_for_KLAYTN() throws Exception @Test public void should_not_addRequiredCredentials_for_KLAYTN_when_not_use_production_key() throws Exception { - HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key", false); + HttpServiceHelper.addRequiredCredentials(8217, httpService, "klaytn-key", "infura-key", false); HashMap headers = httpService.getHeaders(); assertFalse(headers.containsKey("x-chain-id")); assertFalse(headers.containsKey("Authorization")); @@ -51,7 +51,7 @@ public void should_not_addRequiredCredentials_for_KLAYTN_when_not_use_production @Test public void should_not_addRequiredCredentials_for_non_KLAYTN_chain() throws Exception { - HttpServiceHelper.addRequiredCredentials(1, httpService, "klaytn-key", false); + HttpServiceHelper.addRequiredCredentials(1, httpService, "klaytn-key", "infura-key", false); HashMap headers = httpService.getHeaders(); assertFalse(headers.containsKey("x-chain-id")); assertFalse(headers.containsKey("Authorization")); diff --git a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java index 1cc1ddf673..5ec1e645b8 100644 --- a/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java +++ b/lib/src/main/java/com/alphawallet/ethereum/EthereumNetworkBase.java @@ -47,7 +47,7 @@ public abstract class EthereumNetworkBase public static final String MAINNET_RPC_URL = "https://mainnet.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; public static final String CLASSIC_RPC_URL = "https://www.ethercluster.com/etc"; - public static final String XDAI_RPC_URL = "https://rpc.ankr.com/gnosis"; + public static final String XDAI_RPC_URL = "https://rpc.gnosischain.com"; public static final String POA_RPC_URL = "https://core.poa.network/"; public static final String GOERLI_RPC_URL = "https://goerli.infura.io/v3/da3717f25f824cc1baa32d812386d93f"; public static final String ARTIS_SIGMA1_RPC_URL = "https://rpc.sigma1.artis.network"; From 81959d51bcb92f7fceb7b9265ac2e6de8a97a480 Mon Sep 17 00:00:00 2001 From: justindg Date: Fri, 9 Dec 2022 16:03:22 -0800 Subject: [PATCH 162/183] Fix WC v2 issues from #2963 (#2983) * Filter out watch-only wallets * Fix address display * Add placeholder if dapp name/title does not exist * Generify layout + remove non-default wallets from selection * Restore wallet adapter * Fix text alignment * Show warning message if signing wallet is different from active wallet * Show diff wallet warning message in transaction dialog * Standardize widget weights * Only show warning message on applicable WC transactions * Fix IndexOutOfBounds issue when disconnecting dapp --- .../app/ui/WalletConnectSessionActivity.java | 10 +- .../app/ui/WalletConnectV2Activity.java | 187 +++++++++------- .../alphawallet/app/ui/WalletFragment.java | 4 +- .../app/ui/widget/adapter/ChainAdapter.java | 19 +- .../app/ui/widget/adapter/MethodAdapter.java | 16 +- .../app/ui/widget/adapter/TokensAdapter.java | 15 +- .../app/ui/widget/adapter/WalletAdapter.java | 3 +- .../com/alphawallet/app/util/Wallets.java | 20 ++ .../app/viewmodel/SignDialogViewModel.java | 38 +++- .../viewmodel/WalletConnectV2ViewModel.java | 31 +-- .../TransactionDialogBuilder.java | 1 + .../app/widget/ActionSheetDialog.java | 9 + .../app/widget/ActionSheetSignDialog.java | 22 +- .../app/widget/AddressDetailView.java | 49 ++++- .../app/widget/SignDataWidget.java | 53 +++-- .../res/layout/activity_wallet_connect_v2.xml | 208 ++++++++---------- .../res/layout/dialog_action_sheet_sign.xml | 7 + .../main/res/layout/item_address_detail.xml | 52 +++-- .../main/res/layout/item_amount_display.xml | 18 +- app/src/main/res/layout/item_asset_detail.xml | 15 +- .../main/res/layout/item_balance_display.xml | 18 +- app/src/main/res/layout/item_chain.xml | 20 +- app/src/main/res/layout/item_gas_settings.xml | 35 +-- app/src/main/res/layout/item_method.xml | 20 +- .../main/res/layout/item_network_display.xml | 9 +- app/src/main/res/layout/item_sign_data.xml | 55 ++--- .../main/res/layout/item_simple_widget.xml | 14 +- app/src/main/res/layout/item_wallet.xml | 45 ++-- .../res/layout/transaction_detail_widget.xml | 30 ++- app/src/main/res/values-es/strings.xml | 4 + app/src/main/res/values-fr/strings.xml | 4 + app/src/main/res/values-id/strings.xml | 4 + app/src/main/res/values-my/strings.xml | 4 + app/src/main/res/values-vi/strings.xml | 4 + app/src/main/res/values-zh/strings.xml | 4 + app/src/main/res/values/integers.xml | 7 + app/src/main/res/values/strings.xml | 4 + .../com/alphawallet/app/util/WalletsTest.java | 30 +++ 38 files changed, 683 insertions(+), 405 deletions(-) create mode 100644 app/src/main/java/com/alphawallet/app/util/Wallets.java create mode 100644 app/src/main/res/values/integers.xml create mode 100644 app/src/test/java/com/alphawallet/app/util/WalletsTest.java diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java index 9b22bb4512..4b33f2df2c 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectSessionActivity.java @@ -9,6 +9,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -301,7 +302,14 @@ public void onBindViewHolder(CustomAdapter.CustomViewHolder holder, int position .load(session.icon) .circleCrop() .into(holder.icon); - holder.peerName.setText(session.name); + if (TextUtils.isEmpty(session.name)) + { + holder.peerName.setText(R.string.no_title); + } + else + { + holder.peerName.setText(session.name); + } holder.peerUrl.setText(session.url); holder.chainIcon.setImageResource(EthereumNetworkRepository.getChainLogo(session.chainId)); holder.clickLayer.setOnClickListener(v -> { diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java index 6446be8d24..82d78e753b 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java @@ -3,8 +3,8 @@ import static java.util.stream.Collectors.toList; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; -import android.os.Handler; import android.text.TextUtils; import android.view.View; import android.widget.ImageView; @@ -16,12 +16,14 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; import androidx.lifecycle.ViewModelProvider; import com.alphawallet.app.R; import com.alphawallet.app.entity.NetworkInfo; import com.alphawallet.app.entity.StandardFunctionInterface; import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.walletconnect.NamespaceParser; import com.alphawallet.app.entity.walletconnect.WalletConnectV2SessionItem; import com.alphawallet.app.ui.widget.adapter.ChainAdapter; @@ -56,19 +58,18 @@ public class WalletConnectV2Activity extends BaseActivity implements StandardFun AWWalletConnectClient awWalletConnectClient; private WalletConnectV2ViewModel viewModel; private SelectNetworkFilterViewModel selectNetworkFilterViewModel; - private ImageView icon; private TextView peerName; private TextView peerUrl; private ProgressBar progressBar; private LinearLayout infoLayout; - private FunctionButtonBar functionBar; - private ListView chainList; + private TextView networksLabel; private ListView walletList; + private ListView chainList; private ListView methodList; - - private WalletConnectV2SessionItem session; + private FunctionButtonBar functionBar; private WalletAdapter walletAdapter; + private WalletConnectV2SessionItem session; @Override protected void onCreate(@Nullable Bundle savedInstanceState) @@ -89,7 +90,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { return; } - new Handler().post(() -> { + runOnUiThread(() -> { Toast.makeText(WalletConnectV2Activity.this, msg, Toast.LENGTH_SHORT).show(); finish(); }); @@ -101,6 +102,25 @@ protected void onCreate(@Nullable Bundle savedInstanceState) initViewModel(); } + private void initViews() + { + progressBar = findViewById(R.id.progress); + infoLayout = findViewById(R.id.layout_info); + icon = findViewById(R.id.icon); + peerName = findViewById(R.id.peer_name); + peerUrl = findViewById(R.id.peer_url); + networksLabel = findViewById(R.id.label_networks); + walletList = findViewById(R.id.wallet_list); + chainList = findViewById(R.id.chain_list); + methodList = findViewById(R.id.method_list); + functionBar = findViewById(R.id.layoutButtons); + + progressBar.setVisibility(View.VISIBLE); + infoLayout.setVisibility(View.GONE); + functionBar.setupFunctions(this, Arrays.asList(R.string.dialog_approve, R.string.dialog_reject)); + functionBar.setVisibility(View.GONE); + } + @Override protected void onNewIntent(Intent intent) { @@ -123,40 +143,44 @@ private void initViewModel() { viewModel = new ViewModelProvider(this) .get(WalletConnectV2ViewModel.class); - - viewModel.wallets().observe(this, this::onWalletsFetched); - viewModel.defaultWallet().observe(this, this::onDefaultWallet); - selectNetworkFilterViewModel = new ViewModelProvider(this) .get(SelectNetworkFilterViewModel.class); + viewModel.defaultWallet().observe(this, this::onDefaultWallet); + viewModel.wallets().observe(this, this::onWallets); } - private void onWalletsFetched(Wallet[] wallets) + private void onWallets(Wallet[] wallets) { - tryDisplaySessionStatus(); + viewModel.fetchDefaultWallet(); } - private void tryDisplaySessionStatus() + private void onDefaultWallet(Wallet wallet) { - if (viewModel.wallets().getValue() != null && viewModel.defaultWallet().getValue() != null) + if (wallet.type == WalletType.WATCH) { - displaySessionStatus(session); + AWalletAlertDialog errorDialog = new AWalletAlertDialog(this); + errorDialog.setTitle(R.string.title_dialog_error); + errorDialog.setMessage(getString(R.string.error_message_watch_only_wallet)); + errorDialog.setButton(R.string.dialog_ok, v -> { + errorDialog.dismiss(); + finish(); + }); + errorDialog.show(); + } + else + { + displaySessionStatus(session, wallet); progressBar.setVisibility(View.GONE); functionBar.setVisibility(View.VISIBLE); infoLayout.setVisibility(View.VISIBLE); } } - private void onDefaultWallet(Wallet wallet) - { - tryDisplaySessionStatus(); - } - - private void displaySessionStatus(WalletConnectV2SessionItem session) + private void displaySessionStatus(WalletConnectV2SessionItem session, Wallet wallet) { if (session.icon == null) { - icon.setImageResource(R.drawable.ic_coin_eth_small); + icon.setImageResource(R.drawable.grey_circle); } else { @@ -165,24 +189,55 @@ private void displaySessionStatus(WalletConnectV2SessionItem session) .circleCrop() .into(icon); } - peerName.setText(session.name); + + if (!TextUtils.isEmpty(session.name)) + { + peerName.setText(session.name); + } + peerUrl.setText(session.url); + peerUrl.setTextColor(ContextCompat.getColor(this, R.color.brand)); + peerUrl.setOnClickListener(v -> { + String url = peerUrl.getText().toString(); + if (url.startsWith("http")) + { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse(url)); + startActivity(i); + } + }); - chainList.setAdapter(new ChainAdapter(this, session.chains)); if (session.settled) { walletAdapter = new WalletAdapter(this, findWallets(session.wallets)); + networksLabel.setText(R.string.network); } else { - walletAdapter = new WalletAdapter(this, viewModel.wallets().getValue(), viewModel.defaultWallet().getValue()); + walletAdapter = new WalletAdapter(this, new Wallet[]{wallet}, viewModel.defaultWallet().getValue()); } + walletList.setAdapter(walletAdapter); + + if (session.chains.size() > 1) + { + networksLabel.setText(R.string.network); + } + else + { + networksLabel.setText(R.string.subtitle_network); + } + + chainList.setAdapter(new ChainAdapter(this, session.chains)); + methodList.setAdapter(new MethodAdapter(this, session.methods)); + resizeList(); if (session.settled) { + setTitle(getString(R.string.title_session_details)); + functionBar.setupFunctions(new StandardFunctionInterface() { @Override @@ -194,6 +249,8 @@ public void handleClick(String action, int actionId) } else { + setTitle(getString(R.string.title_session_proposal)); + functionBar.setupFunctions(new StandardFunctionInterface() { @Override @@ -201,7 +258,7 @@ public void handleClick(String action, int actionId) { if (actionId == R.string.dialog_approve) { - approve(AWWalletConnectClient.sessionProposal); + approve(AWWalletConnectClient.sessionProposal, wallet.address); } else { @@ -213,64 +270,16 @@ public void handleClick(String action, int actionId) } - private List findWallets(List addresses) - { - List result = new ArrayList<>(); - Map map = toMap(Objects.requireNonNull(viewModel.wallets().getValue())); - for (String address : addresses) - { - Wallet wallet = map.get(address); - if (wallet == null) - { - wallet = new Wallet(address); - } - result.add(wallet); - } - return result; - } - - private Map toMap(Wallet[] wallets) - { - HashMap map = new HashMap<>(); - for (Wallet wallet : wallets) - { - map.put(wallet.address, wallet); - } - return map; - } - private void resizeList() { LayoutHelper.resizeList(chainList); - LayoutHelper.resizeList(walletList); LayoutHelper.resizeList(methodList); } - private void initViews() - { - progressBar = findViewById(R.id.progress); - infoLayout = findViewById(R.id.layout_info); - icon = findViewById(R.id.icon); - peerName = findViewById(R.id.peer_name); - peerUrl = findViewById(R.id.peer_url); - chainList = findViewById(R.id.chain_list); - walletList = findViewById(R.id.wallet_list); - methodList = findViewById(R.id.method_list); - - progressBar.setVisibility(View.VISIBLE); - infoLayout.setVisibility(View.GONE); - - functionBar = findViewById(R.id.layoutButtons); - functionBar.setupFunctions(this, Arrays.asList(R.string.dialog_approve, R.string.dialog_reject)); - - functionBar.setVisibility(View.GONE); - } - private void endSessionDialog() { runOnUiThread(() -> { - AWalletAlertDialog dialog = new AWalletAlertDialog(this, AWalletAlertDialog.ERROR); dialog.setTitle(R.string.dialog_title_disconnect_session); dialog.setButton(R.string.action_close, v -> { @@ -293,7 +302,7 @@ private void reject(Sign.Model.SessionProposal sessionProposal) awWalletConnectClient.reject(sessionProposal, this); } - private void approve(Sign.Model.SessionProposal sessionProposal) + private void approve(Sign.Model.SessionProposal sessionProposal, String walletAddress) { List disabledNetworks = disabledNetworks(sessionProposal.getRequiredNamespaces()); if (disabledNetworks.isEmpty()) @@ -351,6 +360,32 @@ private List disabledNetworks(Map r return result; } + private List findWallets(List addresses) + { + List result = new ArrayList<>(); + Map map = toMap(Objects.requireNonNull(viewModel.wallets().getValue())); + for (String address : addresses) + { + Wallet wallet = map.get(address); + if (wallet == null) + { + wallet = new Wallet(address); + } + result.add(wallet); + } + return result; + } + + private Map toMap(Wallet[] wallets) + { + HashMap map = new HashMap<>(); + for (Wallet wallet : wallets) + { + map.put(wallet.address, wallet); + } + return map; + } + private List getSelectedAccounts() { return walletAdapter.getSelectedWallets().stream() diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java index 8c01d10254..6819bbe31e 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletFragment.java @@ -41,14 +41,12 @@ import com.alphawallet.app.R; import com.alphawallet.app.analytics.Analytics; import com.alphawallet.app.entity.BackupOperationType; -import com.alphawallet.app.entity.BackupTokenCallback; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.CustomViewSettings; import com.alphawallet.app.entity.ErrorEnvelope; import com.alphawallet.app.entity.ServiceSyncCallback; import com.alphawallet.app.entity.TokenFilter; import com.alphawallet.app.entity.Wallet; -import com.alphawallet.app.entity.WalletPage; import com.alphawallet.app.entity.WalletType; import com.alphawallet.app.entity.tokens.Token; import com.alphawallet.app.entity.tokens.TokenCardMeta; @@ -346,7 +344,7 @@ private void updateMetas(List metas) { if (metas.size() > 0) { - adapter.setTokens(metas.toArray(new TokenCardMeta[0])); + adapter.updateTokenMetas(metas.toArray(new TokenCardMeta[0])); systemView.hide(); } }); diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainAdapter.java index 27329f7e25..c78220dfd9 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/ChainAdapter.java @@ -6,17 +6,18 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.alphawallet.app.R; +import com.alphawallet.app.repository.EthereumNetworkBase; import com.alphawallet.app.repository.EthereumNetworkRepository; import com.alphawallet.app.walletconnect.util.WalletConnectHelper; -import com.alphawallet.app.widget.ChainName; import java.util.List; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - public class ChainAdapter extends ArrayAdapter { public ChainAdapter(Context context, List chains) @@ -24,6 +25,12 @@ public ChainAdapter(Context context, List chains) super(context, 0, chains); } + @Override + public boolean isEnabled(int position) + { + return false; + } + @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) @@ -34,10 +41,10 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_chain, parent, false); } - ChainName chainName = convertView.findViewById(R.id.chain_name); + TextView chainName = convertView.findViewById(R.id.chain_name); ImageView chainIcon = convertView.findViewById(R.id.chain_icon); - chainName.setChainID(chainId); + chainName.setText(EthereumNetworkBase.getNetworkInfo(chainId).name); chainIcon.setImageResource(EthereumNetworkRepository.getChainLogo(chainId)); return convertView; diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MethodAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MethodAdapter.java index e15db09a8e..eb18499eb4 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MethodAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/MethodAdapter.java @@ -7,13 +7,13 @@ import android.widget.ArrayAdapter; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.alphawallet.app.R; import java.util.List; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - public class MethodAdapter extends ArrayAdapter { public MethodAdapter(@NonNull Context context, List methods) @@ -21,6 +21,12 @@ public MethodAdapter(@NonNull Context context, List methods) super(context, 0, methods); } + @Override + public boolean isEnabled(int position) + { + return false; + } + @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) @@ -30,9 +36,9 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_method, parent, false); } - TextView methodName = convertView.findViewById(R.id.tv_method_name); - + TextView methodName = convertView.findViewById(R.id.text); methodName.setText(getItem(position)); + return convertView; } } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java index 9972fe894a..e577303d60 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/TokensAdapter.java @@ -3,6 +3,11 @@ import android.content.Intent; import android.view.ViewGroup; +import androidx.activity.result.ActivityResultLauncher; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SortedList; + import com.alphawallet.app.R; import com.alphawallet.app.entity.ContractLocator; import com.alphawallet.app.entity.CustomViewSettings; @@ -44,11 +49,6 @@ import java.util.ArrayList; import java.util.List; -import androidx.activity.result.ActivityResultLauncher; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.SortedList; - public class TokensAdapter extends RecyclerView.Adapter { private static final String TAG = "TKNADAPTER"; @@ -289,6 +289,11 @@ public void addWarning(WarningData data) } public void setTokens(TokenCardMeta[] tokens) + { + populateTokens(tokens, true); + } + + public void updateTokenMetas(TokenCardMeta[] tokens) { populateTokens(tokens, false); } diff --git a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletAdapter.java b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletAdapter.java index 6515965454..2ddf6d5692 100644 --- a/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletAdapter.java +++ b/app/src/main/java/com/alphawallet/app/ui/widget/adapter/WalletAdapter.java @@ -16,6 +16,7 @@ import com.alphawallet.app.R; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.WalletType; +import com.alphawallet.app.util.Utils; import com.alphawallet.app.widget.UserAvatar; import com.google.android.material.checkbox.MaterialCheckBox; @@ -66,7 +67,7 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup { holder.walletName.setText(wallet.ENSname); } - holder.walletAddress.setText(wallet.address); + holder.walletAddress.setText(Utils.formatAddress(wallet.address)); if (wallet.type == WalletType.NOT_DEFINED) { holder.walletAddress.setPaintFlags(holder.walletAddress.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); diff --git a/app/src/main/java/com/alphawallet/app/util/Wallets.java b/app/src/main/java/com/alphawallet/app/util/Wallets.java new file mode 100644 index 0000000000..eef15d2d77 --- /dev/null +++ b/app/src/main/java/com/alphawallet/app/util/Wallets.java @@ -0,0 +1,20 @@ +package com.alphawallet.app.util; + +import com.alphawallet.app.entity.Wallet; + +import java.util.ArrayList; + +public class Wallets +{ + public static Wallet[] filter(Wallet[] wallets) + { + ArrayList list = new ArrayList<>(); + for (Wallet w : wallets) + { + if (!w.watchOnly()) + list.add(w); + } + + return list.toArray(new Wallet[0]); + } +} diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/SignDialogViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/SignDialogViewModel.java index 329a4b9542..c2067ff8aa 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/SignDialogViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/SignDialogViewModel.java @@ -2,13 +2,16 @@ import android.app.Activity; +import androidx.core.util.Pair; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; +import com.alphawallet.app.R; import com.alphawallet.app.entity.SignAuthenticationCallback; import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.entity.cryptokeys.SignatureFromKey; import com.alphawallet.app.interact.GenericWalletInteract; +import com.alphawallet.app.repository.PreferenceRepositoryType; import com.alphawallet.app.repository.TransactionRepositoryType; import com.alphawallet.app.service.KeyService; import com.alphawallet.app.ui.widget.entity.ActionSheetCallback; @@ -26,15 +29,22 @@ @HiltViewModel public class SignDialogViewModel extends BaseViewModel { + private final PreferenceRepositoryType preferenceRepository; private final TransactionRepositoryType transactionRepositoryType; private final KeyService keyService; private final GenericWalletInteract walletInteract; private final MutableLiveData completed = new MutableLiveData<>(false); + private final MutableLiveData> message = new MutableLiveData<>(); private Wallet wallet; @Inject - public SignDialogViewModel(GenericWalletInteract walletInteract, TransactionRepositoryType transactionRepositoryType, KeyService keyService) + public SignDialogViewModel( + PreferenceRepositoryType preferenceRepository, + GenericWalletInteract walletInteract, + TransactionRepositoryType transactionRepositoryType, + KeyService keyService) { + this.preferenceRepository = preferenceRepository; this.transactionRepositoryType = transactionRepositoryType; this.keyService = keyService; this.walletInteract = walletInteract; @@ -45,6 +55,25 @@ public SignDialogViewModel(GenericWalletInteract walletInteract, TransactionRepo .subscribe(w -> wallet = w, this::onError); } + public LiveData completed() + { + return completed; + } + + public LiveData> message() + { + return message; + } + + private void compareToActiveWallet(String signingAddress) + { + String activeWallet = preferenceRepository.getCurrentWalletAddress(); + if (!activeWallet.equalsIgnoreCase(signingAddress)) + { + message.postValue(new Pair<>(R.string.message_wc_wallet_different_from_active_wallet, R.drawable.ic_red_warning)); + } + } + public void getAuthentication(Activity activity, SignAuthenticationCallback sCallback) { keyService.getAuthenticationForSignature(wallet, activity, sCallback); @@ -71,16 +100,13 @@ private void signFailed(Throwable error, Signable message, ActionSheetCallback a completed.postValue(false); } - public LiveData completed() - { - return completed; - } - public void setSigningWallet(String account) { disposable = walletInteract.findWallet(account) .observeOn(Schedulers.io()) .subscribeOn(Schedulers.io()) .subscribe(w -> wallet = w, this::onError); // TODO: If wallet not found then report error to user rather than trying to sign on default wallet + + compareToActiveWallet(account); } } diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectV2ViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectV2ViewModel.java index 9ceac34a04..d043a4a1e8 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectV2ViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/WalletConnectV2ViewModel.java @@ -1,13 +1,14 @@ package com.alphawallet.app.viewmodel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + import com.alphawallet.app.entity.Wallet; import com.alphawallet.app.interact.FetchWalletsInteract; import com.alphawallet.app.interact.GenericWalletInteract; import javax.inject.Inject; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; import dagger.hilt.android.lifecycle.HiltViewModel; @HiltViewModel @@ -19,22 +20,27 @@ public class WalletConnectV2ViewModel extends BaseViewModel private final FetchWalletsInteract fetchWalletsInteract; private final GenericWalletInteract genericWalletInteract; - public LiveData wallets() - { - return wallets; - } - @Inject - WalletConnectV2ViewModel(FetchWalletsInteract fetchWalletsInteract, GenericWalletInteract genericWalletInteract) + WalletConnectV2ViewModel(FetchWalletsInteract fetchWalletsInteract, + GenericWalletInteract genericWalletInteract) { this.fetchWalletsInteract = fetchWalletsInteract; this.genericWalletInteract = genericWalletInteract; - fetchWallets(); fetchDefaultWallet(); } - private void fetchDefaultWallet() + public LiveData wallets() + { + return wallets; + } + + public LiveData defaultWallet() + { + return defaultWallet; + } + + public void fetchDefaultWallet() { disposable = genericWalletInteract .find() @@ -57,9 +63,4 @@ private void onWallets(Wallet[] wallets) { this.wallets.postValue(wallets); } - - public LiveData defaultWallet() - { - return defaultWallet; - } } diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java b/app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java index 75ef560ccb..f159970199 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/TransactionDialogBuilder.java @@ -124,6 +124,7 @@ public ActivityResultLauncher gasSelectLauncher() return activityResultLauncher; } }); + actionSheetDialog.setSigningWallet(fromWallet.address); if (signOnly) { actionSheetDialog.setSignOnly(); diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java index c5769d1c1c..f224c9fe1b 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java @@ -734,4 +734,13 @@ private boolean has1559Gas() return false; } + + public void setSigningWallet(String address) + { + SharedPreferenceRepository prefs = new SharedPreferenceRepository(getContext()); + if (!prefs.getCurrentWalletAddress().equalsIgnoreCase(address)) + { + addressDetail.addMessage(getContext().getString(R.string.message_wc_wallet_different_from_active_wallet), R.drawable.ic_red_warning); + } + } } diff --git a/app/src/main/java/com/alphawallet/app/widget/ActionSheetSignDialog.java b/app/src/main/java/com/alphawallet/app/widget/ActionSheetSignDialog.java index 4af5bc6838..19cbfc05cc 100644 --- a/app/src/main/java/com/alphawallet/app/widget/ActionSheetSignDialog.java +++ b/app/src/main/java/com/alphawallet/app/widget/ActionSheetSignDialog.java @@ -1,14 +1,12 @@ package com.alphawallet.app.widget; -import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED; - import android.app.Activity; -import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.core.util.Pair; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelStoreOwner; @@ -22,7 +20,6 @@ import com.alphawallet.app.viewmodel.SignDialogViewModel; import com.alphawallet.token.entity.Signable; import com.bumptech.glide.Glide; -import com.google.android.material.bottomsheet.BottomSheetBehavior; import java.util.ArrayList; import java.util.Collections; @@ -35,6 +32,7 @@ public class ActionSheetSignDialog extends ActionSheet implements StandardFuncti private final SignDialogViewModel viewModel; private final BottomSheetToolbarView toolbar; private final ConfirmationWidget confirmationWidget; + private final AddressDetailView requesterDetail; private final AddressDetailView addressDetail; private final FunctionButtonBar functionBar; private final ActionSheetCallback actionSheetCallback; @@ -45,19 +43,19 @@ public class ActionSheetSignDialog extends ActionSheet implements StandardFuncti public ActionSheetSignDialog(@NonNull Activity callingActivity, ActionSheetCallback aCallback, Signable message) { super(callingActivity); - View view = LayoutInflater.from(callingActivity).inflate(R.layout.dialog_action_sheet_sign, null); + View view = View.inflate(callingActivity, R.layout.dialog_action_sheet_sign, null); setContentView(view); - toolbar = findViewById(R.id.bottom_sheet_toolbar); confirmationWidget = findViewById(R.id.confirmation_view); - addressDetail = findViewById(R.id.requester); + requesterDetail = findViewById(R.id.requester); + addressDetail = findViewById(R.id.wallet); functionBar = findViewById(R.id.layoutButtons); callbackId = message.getCallbackId(); activity = callingActivity; actionSheetCallback = aCallback; - addressDetail.setupRequester(message.getOrigin()); + requesterDetail.setupRequester(message.getOrigin()); SignDataWidget signWidget = findViewById(R.id.sign_widget); signWidget.setupSignData(message); @@ -73,6 +71,7 @@ public ActionSheetSignDialog(@NonNull Activity callingActivity, ActionSheetCallb viewModel = new ViewModelProvider((ViewModelStoreOwner) activity).get(SignDialogViewModel.class); viewModel.completed().observe((LifecycleOwner) activity, this::signComplete); + viewModel.message().observe((LifecycleOwner) activity, this::onMessage); setCanceledOnTouchOutside(false); } @@ -99,6 +98,13 @@ public void handleClick(String action, int id) public void setSigningWallet(String account) { viewModel.setSigningWallet(account); + addressDetail.setVisibility(View.VISIBLE); + addressDetail.setupAddress(account, "", null); + } + + private void onMessage(Pair res) + { + addressDetail.addMessage(getContext().getString(res.first), res.second); } public void success() diff --git a/app/src/main/java/com/alphawallet/app/widget/AddressDetailView.java b/app/src/main/java/com/alphawallet/app/widget/AddressDetailView.java index 688d5de6a8..7f16949cda 100644 --- a/app/src/main/java/com/alphawallet/app/widget/AddressDetailView.java +++ b/app/src/main/java/com/alphawallet/app/widget/AddressDetailView.java @@ -5,7 +5,6 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -24,10 +23,13 @@ public class AddressDetailView extends LinearLayout { private final TextView textAddressSummary; private final TextView textFullAddress; + private final TextView labelEnsName; private final TextView textEnsName; + private final TextView textMessage; private final ImageView recipientDetails; private final UserAvatar userAvatar; private final LinearLayout layoutDetails; + private final LinearLayout layoutEnsName; private final LinearLayout layoutHolder; public AddressDetailView(Context context, @Nullable AttributeSet attrs) @@ -36,10 +38,13 @@ public AddressDetailView(Context context, @Nullable AttributeSet attrs) inflate(context, R.layout.item_address_detail, this); textAddressSummary = findViewById(R.id.text_recipient); textFullAddress = findViewById(R.id.text_recipient_address); + labelEnsName = findViewById(R.id.label_ens_name); textEnsName = findViewById(R.id.text_ens_name); + textMessage = findViewById(R.id.message); recipientDetails = findViewById(R.id.image_more); userAvatar = findViewById(R.id.blockie); layoutDetails = findViewById(R.id.layout_detail); + layoutEnsName = findViewById(R.id.layout_ens_name); layoutHolder = findViewById(R.id.layout_holder); getAttrs(context, attrs); } @@ -55,19 +60,45 @@ private void getAttrs(Context context, AttributeSet attrs) recipientText.setText(a.getResourceId(R.styleable.InputView_label, R.string.recipient)); } + public void addMessage(String message, int drawableRes) + { + textMessage.setText(message); + textMessage.setVisibility(View.VISIBLE); + if (drawableRes > 0) + { + textAddressSummary.setCompoundDrawablesWithIntrinsicBounds(drawableRes, 0, 0, 0); + textMessage.setCompoundDrawablesWithIntrinsicBounds(drawableRes, 0, 0, 0); + } + } + public void setupAddress(String address, String ensName, Token destToken) { boolean hasEns = !TextUtils.isEmpty(ensName); - String destStr = (hasEns ? ensName + " | " : "") + (hasEns ? Utils.formatAddress(address) : address); + String destStr = (hasEns ? ensName + " | " : "") + Utils.formatAddress(address); textAddressSummary.setText(destStr); userAvatar.bind(new Wallet(address), wallet -> { /*NOP, here to enable lookup of ENS avatar*/ }); textFullAddress.setText(address); - textEnsName.setText(ensName); - if (TextUtils.isEmpty(ensName) && destToken != null && !destToken.isEthereum()) + if (TextUtils.isEmpty(ensName)) + { + if (destToken != null && !destToken.isEthereum()) + { + labelEnsName.setVisibility(View.VISIBLE); + layoutEnsName.setVisibility(View.VISIBLE); + labelEnsName.setText(R.string.token_text); + textEnsName.setText(destToken.getFullName()); + } + else + { + labelEnsName.setVisibility(View.GONE); + layoutEnsName.setVisibility(View.GONE); + } + } + else { - ((TextView)findViewById(R.id.label_ens)).setText(R.string.token_text); - textEnsName.setText(destToken.getFullName()); + labelEnsName.setVisibility(View.VISIBLE); + layoutEnsName.setVisibility(View.VISIBLE); + textEnsName.setText(ensName); } layoutHolder.setOnClickListener(v -> { @@ -89,12 +120,10 @@ public void setupAddress(String address, String ensName, Token destToken) public void setupRequester(String requesterUrl) { setVisibility(View.VISIBLE); - recipientDetails.setVisibility(View.GONE); + recipientDetails.setVisibility(View.INVISIBLE); //shorten requesterURL if required requesterUrl = abbreviateURL(requesterUrl); textAddressSummary.setText(requesterUrl); - ViewGroup.LayoutParams param = new LayoutParams(0, LayoutParams.WRAP_CONTENT, 3.4f); - textAddressSummary.setLayoutParams(param); } private String abbreviateURL(String inputURL) @@ -102,7 +131,7 @@ private String abbreviateURL(String inputURL) if (inputURL.length() > 32) { int index = inputURL.indexOf("/", 20); - return index >= 0 ? inputURL.substring(0,index) : inputURL; + return index >= 0 ? inputURL.substring(0, index) : inputURL; } else { diff --git a/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java b/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java index 1a137c2e4b..c66f7c9254 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java @@ -12,6 +12,9 @@ import androidx.annotation.Nullable; import com.alphawallet.app.R; +import com.alphawallet.app.entity.ActionSheetInterface; +import com.alphawallet.app.util.Hex; +import com.alphawallet.token.entity.SignMessageType; import com.alphawallet.token.entity.Signable; /** @@ -19,25 +22,24 @@ */ public class SignDataWidget extends LinearLayout { - private final TextView textSignDetails; - private final TextView textSignDetailsMax; + private final TextView previewText; + private final TextView messageText; private final LinearLayout layoutHolder; private final ImageView moreArrow; private final ScrollView scrollView; - private final TextView messageTitle; + private ActionSheetInterface sheetInterface; private Signable signable; public SignDataWidget(Context context, @Nullable AttributeSet attrs) { super(context, attrs); inflate(context, R.layout.item_sign_data, this); - textSignDetails = findViewById(R.id.text_sign_data); - textSignDetailsMax = findViewById(R.id.text_sign_data_max); + previewText = findViewById(R.id.text_preview); + messageText = findViewById(R.id.text_message); layoutHolder = findViewById(R.id.layout_holder); moreArrow = findViewById(R.id.image_more); scrollView = findViewById(R.id.scroll_view); - messageTitle = findViewById(R.id.text_message_title); - + TextView messageTitle = findViewById(R.id.text_message_title); boolean noTitle = getAttribute(context, attrs); if (noTitle) { @@ -57,32 +59,49 @@ private boolean getAttribute(Context context, AttributeSet attrs) return a.getBoolean(R.styleable.SignDataWidget_noTitle, false); } - public void setupSignData(Signable message) + public void setupSignData(Signable signable) { - this.signable = message; - textSignDetails.setText(message.getUserMessage()); - textSignDetailsMax.setText(message.getUserMessage()); + this.signable = signable; + String message; + if (signable.getMessageType() == SignMessageType.SIGN_PERSONAL_MESSAGE + || signable.getMessageType() == SignMessageType.SIGN_MESSAGE) + { + message = Hex.hexToUtf8(signable.getMessage()); + } + else + { + message = signable.getUserMessage().toString(); + } + previewText.setText(message); + messageText.setText(message); layoutHolder.setOnClickListener(v -> { - if (textSignDetails.getVisibility() == View.VISIBLE) + if (previewText.getVisibility() == View.VISIBLE) { - textSignDetails.setVisibility(View.GONE); + previewText.setVisibility(View.INVISIBLE); scrollView.setVisibility(View.VISIBLE); - messageTitle.setVisibility(View.GONE); + scrollView.setEnabled(true); moreArrow.setImageResource(R.drawable.ic_expand_less_black); + if (sheetInterface != null) sheetInterface.lockDragging(true); } else { - textSignDetails.setVisibility(View.VISIBLE); - messageTitle.setVisibility(View.VISIBLE); + previewText.setVisibility(View.VISIBLE); scrollView.setVisibility(View.GONE); + scrollView.setEnabled(false); moreArrow.setImageResource(R.drawable.ic_expand_more); + if (sheetInterface != null) sheetInterface.lockDragging(false); } }); } + public void setLockCallback(ActionSheetInterface asIf) + { + sheetInterface = asIf; + } + public Signable getSignable() { return signable; } -} +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_wallet_connect_v2.xml b/app/src/main/res/layout/activity_wallet_connect_v2.xml index 2a4c35b0e4..4ede5e5edb 100644 --- a/app/src/main/res/layout/activity_wallet_connect_v2.xml +++ b/app/src/main/res/layout/activity_wallet_connect_v2.xml @@ -7,156 +7,136 @@ - - - - - - - + + - - - - + android:layout_below="@id/toolbar" + android:layout_marginTop="@dimen/standard_16" + android:orientation="vertical" + android:visibility="visible"> - + android:layout_marginHorizontal="@dimen/standard_16" + android:layout_marginBottom="@dimen/mini_4" + android:text="@string/connected_to" /> + + + + + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_toEndOf="@id/icon" + android:orientation="vertical"> + android:text="@string/no_title" + tools:text="Sample Peer Name" /> - - + android:layout_height="wrap_content" + tools:text="https://samplepeer.com" /> + - + - + - - - + + + - + - + - - - - + - + - + + tools:visibility="visible" /> + android:visibility="gone" + tools:visibility="visible" /> diff --git a/app/src/main/res/layout/dialog_action_sheet_sign.xml b/app/src/main/res/layout/dialog_action_sheet_sign.xml index f9a07a5177..4d1b5c844e 100644 --- a/app/src/main/res/layout/dialog_action_sheet_sign.xml +++ b/app/src/main/res/layout/dialog_action_sheet_sign.xml @@ -17,6 +17,13 @@ android:layout_height="wrap_content" custom:label="@string/requester_url" /> + + + android:paddingVertical="@dimen/standard_16" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> + android:text="@string/signer_address" /> + android:text="@string/ens_name" + android:visibility="gone" + tools:visibility="visible" /> + android:orientation="horizontal" + android:visibility="gone" + tools:visibility="visible"> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_amount_display.xml b/app/src/main/res/layout/item_amount_display.xml index 2056f6a2ad..2d8ebab074 100644 --- a/app/src/main/res/layout/item_amount_display.xml +++ b/app/src/main/res/layout/item_amount_display.xml @@ -11,16 +11,17 @@ + android:orientation="horizontal" + android:paddingVertical="@dimen/standard_16" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> @@ -29,7 +30,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/small_12" - android:layout_weight="3.5" + android:layout_weight="@integer/widget_content" android:gravity="start" tools:text="1.234 ETH ≈ 500.23 USD" /> @@ -37,7 +38,8 @@ android:id="@+id/tokens_list" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_weight="3.5" + android:layout_marginHorizontal="@dimen/small_12" + android:layout_weight="@integer/widget_content" android:background="@color/transparent" android:orientation="horizontal" android:visibility="gone" @@ -47,8 +49,8 @@ + android:layout_weight="@integer/widget_control" + android:visibility="invisible" /> diff --git a/app/src/main/res/layout/item_asset_detail.xml b/app/src/main/res/layout/item_asset_detail.xml index cb620c3da8..73a79dfef3 100644 --- a/app/src/main/res/layout/item_asset_detail.xml +++ b/app/src/main/res/layout/item_asset_detail.xml @@ -14,16 +14,17 @@ + android:orientation="horizontal" + android:paddingVertical="@dimen/standard_16" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> @@ -32,7 +33,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/small_12" - android:layout_weight="3.5" + android:layout_weight="@integer/widget_content" android:gravity="start" tools:text="Self Portrait (2021)" /> @@ -41,7 +42,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="start" - android:layout_weight="0.6" + android:layout_weight="@integer/widget_control" android:background="@color/transparent" android:padding="@dimen/mini_4" android:scaleType="fitCenter" @@ -81,7 +82,7 @@ android:layout_width="wrap_content" android:layout_height="0dp" android:layout_marginTop="@dimen/small_12" - android:layout_weight="3.5" + android:layout_weight="@integer/widget_content" tools:text="Self Portrait (2021)" /> + android:orientation="horizontal" + android:paddingVertical="@dimen/standard_16" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> @@ -26,7 +28,8 @@ android:id="@+id/relativeLayout2" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_weight="3.4" + android:layout_marginHorizontal="@dimen/small_12" + android:layout_weight="@integer/widget_content" android:orientation="vertical" custom:layout_constraintBottom_toTopOf="@+id/text_new_balance" custom:layout_constraintTop_toTopOf="@+id/text_new_balance"> @@ -52,8 +55,8 @@ tools:text="35.4236 ETH" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_chain.xml b/app/src/main/res/layout/item_chain.xml index 79ce36a2f3..7f6d94b741 100644 --- a/app/src/main/res/layout/item_chain.xml +++ b/app/src/main/res/layout/item_chain.xml @@ -1,27 +1,27 @@ + tools:ignore="UseCompoundDrawables"> - + android:layout_marginStart="@dimen/tiny_8" + tools:text="@string/ethereum" /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_gas_settings.xml b/app/src/main/res/layout/item_gas_settings.xml index 91b3708a81..54fc6d8fec 100644 --- a/app/src/main/res/layout/item_gas_settings.xml +++ b/app/src/main/res/layout/item_gas_settings.xml @@ -10,15 +10,16 @@ + android:orientation="horizontal" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> @@ -28,7 +29,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/small_12" - android:layout_weight="3" + android:layout_weight="@integer/widget_content" android:orientation="horizontal" android:visibility="gone" tools:visibility="gone"> @@ -54,7 +55,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/small_12" - android:layout_weight="3" + android:layout_weight="@integer/widget_content" android:orientation="horizontal" android:visibility="gone" tools:visibility="gone"> @@ -81,7 +82,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/small_12" - android:layout_weight="3" + android:layout_weight="@integer/widget_content" android:gravity="start" android:text="@string/speed_average" /> @@ -90,27 +91,28 @@ style="@style/Aw.Typography.Control" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_weight="0.6" - android:gravity="end" + android:layout_weight="@integer/widget_control" + android:gravity="start" android:lines="1" android:orientation="horizontal" android:text="@string/edit" android:visibility="gone" - tools:visibility="visible"/> + tools:visibility="visible" /> + android:orientation="horizontal" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> + android:layout_weight="@integer/widget_label" /> + android:layout_height="1dp" + android:layout_weight="@integer/widget_control" /> - - - - \ No newline at end of file + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:paddingHorizontal="@dimen/standard_16" + tools:text="Method" /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_network_display.xml b/app/src/main/res/layout/item_network_display.xml index fb018f2634..d727de7efc 100644 --- a/app/src/main/res/layout/item_network_display.xml +++ b/app/src/main/res/layout/item_network_display.xml @@ -21,13 +21,13 @@ style="@style/Aw.Typography.Label" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_weight="1" + android:layout_weight="@integer/widget_label" android:text="@string/subtitle_network" /> @@ -45,6 +45,11 @@ tools:text="Ethereum" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_sign_data.xml b/app/src/main/res/layout/item_sign_data.xml index 4ad89b3b8f..58ebffc846 100644 --- a/app/src/main/res/layout/item_sign_data.xml +++ b/app/src/main/res/layout/item_sign_data.xml @@ -12,9 +12,11 @@ - - - - - @@ -62,11 +46,30 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="start" - android:layout_weight="0.6" + android:layout_weight="@integer/widget_control" android:background="@color/transparent" android:src="@drawable/ic_expand_more" app:tint="?colorControlNormal" /> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_simple_widget.xml b/app/src/main/res/layout/item_simple_widget.xml index acaa9f7537..83c69d6993 100644 --- a/app/src/main/res/layout/item_simple_widget.xml +++ b/app/src/main/res/layout/item_simple_widget.xml @@ -15,7 +15,9 @@ android:layout_centerVertical="true" android:gravity="center_vertical" android:orientation="horizontal" - android:padding="@dimen/standard_16"> + android:paddingVertical="@dimen/standard_16" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> @@ -49,6 +52,11 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_wallet.xml b/app/src/main/res/layout/item_wallet.xml index 36bd840f32..10a0c0d90a 100644 --- a/app/src/main/res/layout/item_wallet.xml +++ b/app/src/main/res/layout/item_wallet.xml @@ -1,32 +1,26 @@ + android:paddingHorizontal="@dimen/standard_16"> + android:orientation="horizontal"> + android:layout_width="@dimen/token_icon" + android:layout_height="@dimen/token_icon" /> @@ -43,11 +36,12 @@ + android:orientation="horizontal" + android:visibility="gone"> @@ -73,30 +67,30 @@ + @@ -108,6 +102,7 @@ android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:contentDescription="Selection" + android:visibility="gone" tools:ignore="HardcodedText" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/transaction_detail_widget.xml b/app/src/main/res/layout/transaction_detail_widget.xml index 2035a4dc12..5001d0f0ae 100644 --- a/app/src/main/res/layout/transaction_detail_widget.xml +++ b/app/src/main/res/layout/transaction_detail_widget.xml @@ -15,17 +15,17 @@ android:id="@+id/layout_summary" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="@dimen/standard_16" android:gravity="center_vertical" android:orientation="horizontal" - android:paddingTop="@dimen/standard_16" - android:paddingBottom="@dimen/standard_16"> + android:paddingVertical="@dimen/standard_16" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> @@ -41,7 +41,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="start" - android:layout_weight="0.6" + android:layout_weight="@integer/widget_control" android:background="@color/transparent" android:padding="@dimen/mini_4" android:src="@drawable/ic_expand_more" @@ -61,24 +61,31 @@ + android:paddingVertical="@dimen/standard_16" + android:paddingStart="@dimen/standard_16" + android:paddingEnd="@dimen/mini_4"> + + Seleccione al menos un intercambio. Obsoleta No se pudo realizar la acción en esta billetera de solo reloj. + (Sin título) + Detalles de la sesión + Propuesta de sesión + Monedero diferente del monedero activo. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index b32fcba1f0..a43dfa669c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -954,4 +954,8 @@ Sélectionnez au moins un échange. Obsolète Impossible d\'effectuer une action sur ce portefeuille Watch-only. + (Pas de titre) + Détails de la session + Proposition de séance + Portefeuille différent du portefeuille actif. diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 25371f7629..dfcdaf2374 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -944,4 +944,8 @@ Pilih setidaknya satu bursa. Tidak digunakan lagi Tidak dapat melakukan tindakan pada dompet khusus jam tangan ini. + (Tanpa judul) + Detail Sesi + Proposal Sesi + Dompet berbeda dengan dompet aktif. diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index d63e04560f..71cdb52e5a 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -975,4 +975,8 @@ အနည်းဆုံးလဲလှယ်မှုတစ်ခုကို ရွေးပါ။ ကန့်ကွက်ထားသည်။ ဤ Watch-only ပိုက်ဆံအိတ်တွင် လုပ်ဆောင်ချက်ကို မလုပ်ဆောင်နိုင်ပါ။ + (ခေါင်းစဉ်မရှိ။) + အပိုင်းအသေးစိတ် + Session အဆိုပြုချက် + ပိုက်ဆံအိတ်သည် တက်ကြွသောပိုက်ဆံအိတ်နှင့် ကွဲပြားသည်။ diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 1c3f529efd..8fa539d386 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -954,4 +954,8 @@ Chọn ít nhất một sàn giao dịch. Không được chấp nhận Không thể thực hiện hành động trên ví Chỉ xem này. + (Không tiêu đề) + Session Details + Chi tiết phiên + Ví khác với ví đang hoạt động. diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 94071aab69..4fd5ea9f27 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -941,4 +941,8 @@ 至少选择一个交易所。 已弃用 无法对这个仅限手表的钱包执行操作。 + (无题) + 会议详情 + 会议提案 + 钱包不同于活动钱包。 diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml new file mode 100644 index 0000000000..f90362827d --- /dev/null +++ b/app/src/main/res/values/integers.xml @@ -0,0 +1,7 @@ + + + + 1 + 3.5 + 0.6 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 076c0876ad..d19e89d67a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1016,4 +1016,8 @@ Select at least one exchange. Deprecated Could not perform action on this Watch-only wallet. + (No title) + Session Details + Session Proposal + Wallet different from active wallet. diff --git a/app/src/test/java/com/alphawallet/app/util/WalletsTest.java b/app/src/test/java/com/alphawallet/app/util/WalletsTest.java new file mode 100644 index 0000000000..a3f3316813 --- /dev/null +++ b/app/src/test/java/com/alphawallet/app/util/WalletsTest.java @@ -0,0 +1,30 @@ +package com.alphawallet.app.util; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; + +import com.alphawallet.app.entity.Wallet; +import com.alphawallet.app.entity.WalletType; + +import org.junit.Test; + +public class WalletsTest +{ + @Test + public void should_not_return_watch_wallets() + { + Wallet wallet = new Wallet("0x1"); + wallet.type = WalletType.WATCH; + Wallet wallet2 = new Wallet("0x2"); + wallet2.type = WalletType.KEYSTORE; + Wallet wallet3 = new Wallet("0x3"); + wallet3.type = WalletType.HDKEY; + + Wallet[] wallets = {wallet, wallet2, wallet3}; + Wallet[] filtered = Wallets.filter(wallets); + + assertThat(filtered.length, equalTo(2)); + assertThat(filtered[0].address, equalTo("0x2")); + assertThat(filtered[1].address, equalTo("0x3")); + } +} From 5861be8a818ea8adf8a8a1b499455983da061117 Mon Sep 17 00:00:00 2001 From: keval-finimble <110013677+keval-finimble@users.noreply.github.com> Date: Sat, 10 Dec 2022 05:36:29 +0530 Subject: [PATCH 163/183] Fix / Improve "Add Custom Token" (#2969) * Implemented the dialog and bottom-sheet dialog for AddCustomToken * Resolved clear list issue while pasting different key in Add Token. * Added user confirmation dialog when user selects unselected chains in Add Token. Co-authored-by: Keval Shukla --- .../alphawallet/app/ui/AddTokenActivity.java | 105 +++++++++++++++--- .../app/viewmodel/AddTokenViewModel.java | 52 +++++++-- app/src/main/res/values-es/strings.xml | 2 + app/src/main/res/values-fr/strings.xml | 2 + app/src/main/res/values-id/strings.xml | 2 + app/src/main/res/values-my/strings.xml | 2 + app/src/main/res/values-vi/strings.xml | 2 + app/src/main/res/values-zh/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 9 files changed, 148 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java b/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java index cc1631caf5..1ed24f7ec1 100644 --- a/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java +++ b/app/src/main/java/com/alphawallet/app/ui/AddTokenActivity.java @@ -44,6 +44,7 @@ import com.alphawallet.app.util.QRParser; import com.alphawallet.app.util.Utils; import com.alphawallet.app.viewmodel.AddTokenViewModel; +import com.alphawallet.app.widget.AWBottomSheetDialog; import com.alphawallet.app.widget.AWalletAlertDialog; import com.alphawallet.app.widget.FunctionButtonBar; import com.alphawallet.app.widget.InputAddress; @@ -56,9 +57,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import timber.log.Timber; - import dagger.hilt.android.AndroidEntryPoint; +import timber.log.Timber; @AndroidEntryPoint public class AddTokenActivity extends BaseActivity implements AddressReadyCallback, StandardFunctionInterface, TokensAdapterCallback @@ -80,8 +80,12 @@ public class AddTokenActivity extends BaseActivity implements AddressReadyCallba private TokensAdapter adapter; private RecyclerView recyclerView; + FunctionButtonBar functionBar; + + private boolean mainNetActive = true; private AWalletAlertDialog aDialog; + private AWBottomSheetDialog dialog; private final LongSparseArray tokenList = new LongSparseArray<>(); @Override @@ -319,30 +323,105 @@ private void onCheck(String address) lastCheck = address; showProgress(true); progressLayout.setVisibility(View.VISIBLE); + adapter.clear(); viewModel.testNetworks(address); } } - private void onSave() { - List selected = adapter.getSelected(); - List toSave = new ArrayList<>(); - for (TokenCardMeta tcm : selected) + private void onSave() + { + mainNetActive = viewModel.ethereumNetworkRepositoryType().isMainNetSelected(); + if (mainNetActive) { - Token matchingToken = tokenList.get(tcm.getChain()); - if (matchingToken != null) toSave.add(matchingToken); - } + List selected = adapter.getSelected(); - if (toSave.size() > 0) + if (selected.size() > 0) + { + onSelectedChains(selected); + } + else + { + finish(); + } + } + else { + showDialog(functionBar); + } + } + + private void onSelectedChains(List selected) + { + aDialog = new AWalletAlertDialog(this); + aDialog.setTitle(R.string.title_add_token); + aDialog.setIcon(AWalletAlertDialog.NONE); + aDialog.setMessage(getString(R.string.unselected_token)); + aDialog.setButtonText(R.string.dialog_ok); + aDialog.setButtonListener(v -> { + List toSave = new ArrayList<>(); + for (TokenCardMeta tcm : selected) + { + Token matchingToken = tokenList.get(tcm.getChain()); + if (matchingToken != null) toSave.add(matchingToken); + } viewModel.saveTokens(toSave); - onSaved(toSave.get(0)); + if (toSave.size() == 0) + { + Toast.makeText(this, R.string.toast_wait_to_scan_chains, Toast.LENGTH_SHORT).show(); + } + else + { + viewModel.saveTokens(toSave); + onSaved(toSave.get(0)); + aDialog.dismiss(); + } + + }); + aDialog.show(); + } + + private void showDialog(View view) + { + if (dialog == null) + { + dialog = createDialog(); } - else + + if (!dialog.isShowing()) { - finish(); + dialog.show(); } } + private AWBottomSheetDialog createDialog() + { + AWBottomSheetDialog dialog = new AWBottomSheetDialog(this, new AWBottomSheetDialog.Callback() + { + @Override + public void onClosed() + { + + } + + @Override + public void onConfirmed() + { + Intent i = new Intent(getApplication(), SelectNetworkFilterActivity.class); + startActivity(i); + } + + @Override + public void onCancelled() + { + + } + }); + dialog.setTitle(getString(R.string.button_switch_to_mainnet)); + dialog.setContent(getString(R.string.content_dialog_where_are_tokens)); + dialog.setConfirmButton(getString(R.string.button_switch_to_mainnet)); + return dialog; + } + private void onNoContractFound(Boolean noContract) { showProgress(false); diff --git a/app/src/main/java/com/alphawallet/app/viewmodel/AddTokenViewModel.java b/app/src/main/java/com/alphawallet/app/viewmodel/AddTokenViewModel.java index d9256cd899..1b51dc70d6 100644 --- a/app/src/main/java/com/alphawallet/app/viewmodel/AddTokenViewModel.java +++ b/app/src/main/java/com/alphawallet/app/viewmodel/AddTokenViewModel.java @@ -34,7 +34,8 @@ import io.reactivex.schedulers.Schedulers; @HiltViewModel -public class AddTokenViewModel extends BaseViewModel { +public class AddTokenViewModel extends BaseViewModel +{ private final MutableLiveData wallet = new MutableLiveData<>(); private final MutableLiveData switchNetwork = new MutableLiveData<>(); @@ -57,14 +58,35 @@ public class AddTokenViewModel extends BaseViewModel { private long primaryChainId = 1; private final List discoveredTokenList = new ArrayList<>(); - public MutableLiveData wallet() { + public MutableLiveData wallet() + { return wallet; } - public MutableLiveData tokenType() { return tokentype; } - public LiveData switchNetwork() { return switchNetwork; } - public LiveData chainScanCount() { return scanCount; } - public LiveData onToken() { return onToken; } - public LiveData allTokens() { return allTokens; } + + public MutableLiveData tokenType() + { + return tokentype; + } + + public LiveData switchNetwork() + { + return switchNetwork; + } + + public LiveData chainScanCount() + { + return scanCount; + } + + public LiveData onToken() + { + return onToken; + } + + public LiveData allTokens() + { + return allTokens; + } @Nullable Disposable scanNetworksDisposable; @@ -77,7 +99,8 @@ public MutableLiveData wallet() { EthereumNetworkRepositoryType ethereumNetworkRepository, FetchTransactionsInteract fetchTransactionsInteract, AssetDefinitionService assetDefinitionService, - TokensService tokensService) { + TokensService tokensService) + { this.genericWalletInteract = genericWalletInteract; this.ethereumNetworkRepository = ethereumNetworkRepository; this.fetchTransactionsInteract = fetchTransactionsInteract; @@ -140,7 +163,10 @@ private void resumeSend(Token token) finalisedToken.postValue(token); } - public NetworkInfo getNetworkInfo(long chainId) { return ethereumNetworkRepository.getNetworkByChain(chainId); } + public NetworkInfo getNetworkInfo(long chainId) + { + return ethereumNetworkRepository.getNetworkByChain(chainId); + } private void findWallet() { @@ -148,7 +174,8 @@ private void findWallet() .subscribe(wallet::setValue, this::onError); } - private void onTokensSetup(TokenInfo info) { + private void onTokensSetup(TokenInfo info) + { disposable = tokensService.addToken(info, wallet.getValue().address) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -304,4 +331,9 @@ public AssetDefinitionService getAssetDefinitionService() { return assetDefinitionService; } + + public EthereumNetworkRepositoryType ethereumNetworkRepositoryType() + { + return ethereumNetworkRepository; + } } diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2e888d9876..e2847f96b9 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -941,6 +941,8 @@ Seleccione al menos un intercambio. Obsoleta No se pudo realizar la acción en esta billetera de solo reloj. + Escaneo en curso: espere a que finalice + ¿Habilitar cadenas para tokens seleccionados? (Sin título) Detalles de la sesión Propuesta de sesión diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a43dfa669c..c711f10b3c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -954,6 +954,8 @@ Sélectionnez au moins un échange. Obsolète Impossible d\'effectuer une action sur ce portefeuille Watch-only. + Numérisation en cours : veuillez patienter jusqu\'à la fin + Activer les chaînes pour les jetons sélectionnés ? (Pas de titre) Détails de la session Proposition de séance diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index dfcdaf2374..9786a8ee40 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -944,6 +944,8 @@ Pilih setidaknya satu bursa. Tidak digunakan lagi Tidak dapat melakukan tindakan pada dompet khusus jam tangan ini. + Pemindaian sedang berlangsung: Harap tunggu hingga selesai + Aktifkan rantai untuk token yang dipilih? (Tanpa judul) Detail Sesi Proposal Sesi diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 71cdb52e5a..050a0806d5 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -975,6 +975,8 @@ အနည်းဆုံးလဲလှယ်မှုတစ်ခုကို ရွေးပါ။ ကန့်ကွက်ထားသည်။ ဤ Watch-only ပိုက်ဆံအိတ်တွင် လုပ်ဆောင်ချက်ကို မလုပ်ဆောင်နိုင်ပါ။ + စကင်န်လုပ်နေသည်- ပြီးစီးရန်စောင့်ဆိုင်းပါ။ + ရွေးချယ်ထားသော တိုကင်များအတွက် ကွင်းဆက်များကို ဖွင့်မလား။ (ခေါင်းစဉ်မရှိ။) အပိုင်းအသေးစိတ် Session အဆိုပြုချက် diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 8fa539d386..8ae58a5cb3 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -954,6 +954,8 @@ Chọn ít nhất một sàn giao dịch. Không được chấp nhận Không thể thực hiện hành động trên ví Chỉ xem này. + Đang quét: Vui lòng chờ hoàn thành + Kích hoạt chuỗi cho mã thông báo đã chọn? (Không tiêu đề) Session Details Chi tiết phiên diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 4fd5ea9f27..50ee612ae9 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -941,6 +941,8 @@ 至少选择一个交易所。 已弃用 无法对这个仅限手表的钱包执行操作。 + 掃描中:請等待完成 + 為選定的代幣啟用鏈? (无题) 会议详情 会议提案 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d19e89d67a..4fe9fdd2ac 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1016,6 +1016,8 @@ Select at least one exchange. Deprecated Could not perform action on this Watch-only wallet. + Scanning in progress: Please wait for completion + Enable chains for selected tokens? (No title) Session Details Session Proposal From 808930cecd646146566af9073ac1168cadc648a4 Mon Sep 17 00:00:00 2001 From: justindg Date: Sat, 10 Dec 2022 14:28:15 -0800 Subject: [PATCH 164/183] Fixed unnecessary conversion causing crash (#2997) --- .../com/alphawallet/app/widget/SignDataWidget.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java b/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java index c66f7c9254..99d1b55792 100644 --- a/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java +++ b/app/src/main/java/com/alphawallet/app/widget/SignDataWidget.java @@ -62,16 +62,7 @@ private boolean getAttribute(Context context, AttributeSet attrs) public void setupSignData(Signable signable) { this.signable = signable; - String message; - if (signable.getMessageType() == SignMessageType.SIGN_PERSONAL_MESSAGE - || signable.getMessageType() == SignMessageType.SIGN_MESSAGE) - { - message = Hex.hexToUtf8(signable.getMessage()); - } - else - { - message = signable.getUserMessage().toString(); - } + String message = signable.getUserMessage().toString(); previewText.setText(message); messageText.setText(message); From 9387cd011d08b2293e0bca471c1772cf6430716a Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Sun, 11 Dec 2022 23:33:12 +0100 Subject: [PATCH 165/183] Fix: typos (#3001) Fix: typos --- docs/overview.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/overview.md b/docs/overview.md index 5870ed1241..8aef732f37 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -1,6 +1,6 @@ # Modules -Each module has its own README. Please click the name of the module to go to the corrisponding README file. +Each module has its own README. Please click the name of the module to go to the corresponding README file. | [app](../app/README.md) | [lib](../lib/README.md) | [dmz](../dmz/README.md) | [util](../util/README.md) | | --- | --- | --- | --- | @@ -12,7 +12,7 @@ Every aWallet application has a connection to 3 types of hosts. | Public | Stormbird's | Asset Issuers' | | ------ | ----------- | -------------- | -| Ethereum nodes that belongs to the global Ethereum network. These must be pre-trusted due to the absence of SPV verification. Instead of maintaining these nodes, we use a secure and fast source (infura) so long as we can identify them through a safe source like a TLS fingerprint etc. | Stormbid operated servers. Now: A DMZ server for public access plus a secured Market Queue server. αWallet will own and maintain these. Market Queue provides accept-orders when its signer is offline. | One FeeMaster run by each asset issuers,for dealing with Universal Links for each asset type, for sending transactions on behalf of users who don't have ethers. The asset issuers secure these servers themselves and they are trusted to identify spam against their FeeMasters. | +| Ethereum nodes that belong to the global Ethereum network. These must be pre-trusted due to the absence of SPV verification. Instead of maintaining these nodes, we use a secure and fast source (infura) so long as we can identify them through a safe source like a TLS fingerprint etc. | Stormbid operated servers. Now: A DMZ server for public access plus a secured Market Queue server. αWallet will own and maintain these. Market Queue provides accept-orders when its signer is offline. | One FeeMaster run by each asset issuers, for dealing with Universal Links for each asset type, for sending transactions on behalf of users who don't have ethers. The asset issuers secure these servers themselves and they are trusted to identify spam against their FeeMasters. | | If Ethereum node fails, the app connects to the next in the known list. | If Market Queue fails, users can't access the market section of the app, but they can still buy and sell by Universal Link. If Stormbird's DMZ server fails, the user can't see the content of Universal Link unless they have the app | If an asset issuer's FeeMaster fail, that asset can't be transacted free of transaction fee. | ### The servers @@ -78,13 +78,13 @@ Their roles in handling Universal Link is: - DMZ server handles the link if the user doesn't have the app, introducing the user to install the app. - The app handles the link without any of the servers in the graph, if the user can cover the transaction fee. -- If the user can't cover the transaction fee, the wallet app forwards the link to FeeMaster of corrisponding asset-issuers, who may or may not send the transaction on behalf of its user. +- If the user can't cover the transaction fee, the wallet app forwards the link to FeeMaster of corresponding asset-issuers, who may or may not send the transaction on behalf of its user. - All of these servers are connected to Ethereum. DMZ server needs it to work out if the link has been used. How each of the servers functions: - When aWallet launches or redraws its interface, it enquires the Trusted Ethereum Node to obtain the current balance, update the transaction history and find any incoming unconfirmed transactions from its mempool to notify the user. For any Asset Definition downloaded (shipped), the wallet inquires the corresponding smart contract for its current and incoming unconfirmed transactions. -- When aWallet user browse the market (conceptually more like eBay than "token exchanges"), the wallet queries the Market Queue server to find the available orders. Each order is a signed message of the asset identifier. If the user decides to purchase such an asset, then she must send a transaction quoting the order (including signature) and includes the corresponding amount of ether to fulfil the deal. The user can also create a sell order by signing accept-orders and sending them to the Market Queue. +- When aWallet user browses the market (conceptually more like eBay than "token exchanges"), the wallet queries the Market Queue server to find the available orders. Each order is a signed message of the asset identifier. If the user decides to purchase such an asset, then she must send a transaction quoting the order (including signature) and includes the corresponding amount of ether to fulfil the deal. The user can also create a sell order by signing accept-orders and sending them to the Market Queue. - When a αWallet user uses a Universal Link, she can finalise the transaction herself by providing the amount of Ether required in the link as well as a transaction fee. She can also view the content of a UniversalLink by simply clicking it. In the case the amount required by the Universal Link is zero, she can ask the server to send the transaction to Ethereum on her behalf, paying the fee in the meanwhile. (The case which Universal Link requires zero Ether is documented in UniversalLink server document). From 2030d32659940a30f1fa46f1b6fec8198316ecf8 Mon Sep 17 00:00:00 2001 From: Seaborn Date: Thu, 15 Dec 2022 10:08:35 +0800 Subject: [PATCH 166/183] Fix wc2 integration issue (#3005) * Fix eth_signTypedData_v4 * Fix crash --- .../java/com/alphawallet/app/ui/WalletConnectV2Activity.java | 5 +++++ .../alphawallet/app/walletconnect/AWWalletConnectClient.java | 5 ++++- .../alphawallet/app/walletconnect/entity/EthSignRequest.java | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java b/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java index 82d78e753b..5ac50760c3 100644 --- a/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java +++ b/app/src/main/java/com/alphawallet/app/ui/WalletConnectV2Activity.java @@ -363,6 +363,11 @@ private List disabledNetworks(Map r private List findWallets(List addresses) { List result = new ArrayList<>(); + if (viewModel.wallets().getValue() == null) + { + return result; + } + Map map = toMap(Objects.requireNonNull(viewModel.wallets().getValue())); for (String address : addresses) { diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java b/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java index 5bcd8a81c4..4b8a73e788 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/AWWalletConnectClient.java @@ -107,6 +107,10 @@ private boolean validChainId(List chains) public void onSessionRequest(@NonNull Sign.Model.SessionRequest sessionRequest) { String method = sessionRequest.getRequest().getMethod(); + if ("eth_signTypedData_v4".equals(method)) + { + method = "eth_signTypedData"; + } if (!WCMethodChecker.includes(method)) { @@ -416,4 +420,3 @@ default void onSessionDisconnected() } } } - diff --git a/app/src/main/java/com/alphawallet/app/walletconnect/entity/EthSignRequest.java b/app/src/main/java/com/alphawallet/app/walletconnect/entity/EthSignRequest.java index 904b2c420a..c011268883 100644 --- a/app/src/main/java/com/alphawallet/app/walletconnect/entity/EthSignRequest.java +++ b/app/src/main/java/com/alphawallet/app/walletconnect/entity/EthSignRequest.java @@ -22,6 +22,7 @@ public static BaseRequest getSignRequest(Sign.Model.SessionRequest sessionReques signRequest = new SignPersonalMessageRequest(sessionRequest.getRequest().getParams()); break; case "eth_signTypedData": + case "eth_signTypedData_v4": signRequest = new SignTypedDataRequest(sessionRequest.getRequest().getParams()); break; default: From 576dd44481431f78a455f7aae2c1e0b45dda001f Mon Sep 17 00:00:00 2001 From: James Brown Date: Thu, 15 Dec 2022 13:09:33 +1100 Subject: [PATCH 167/183] Ensure video can still play in NFT detail view (#2994) * Ensure video can still play for NFT detail * Add flags to other activities displaying NFTs --- app/src/main/AndroidManifest.xml | 4 ++++ .../main/java/com/alphawallet/app/widget/NFTImageView.java | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 02a932abeb..6e8894867a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -186,6 +186,7 @@ Date: Wed, 14 Dec 2022 18:10:23 -0800 Subject: [PATCH 168/183] Fixed widget labels overflowing on long strings (#3000) * Adjust widget label dimens * Lock down label text size --- app/src/main/res/layout/item_address_detail.xml | 4 ++-- app/src/main/res/layout/item_amount_display.xml | 4 ++-- app/src/main/res/layout/item_asset_detail.xml | 4 ++-- app/src/main/res/layout/item_balance_display.xml | 4 ++-- app/src/main/res/layout/item_gas_settings.xml | 4 ++-- app/src/main/res/layout/item_network_display.xml | 3 ++- app/src/main/res/layout/item_sign_data.xml | 4 ++-- app/src/main/res/layout/item_simple_widget.xml | 2 +- app/src/main/res/layout/transaction_detail_widget.xml | 4 ++-- app/src/main/res/values/integers.xml | 4 ++-- app/src/main/res/values/typography.xml | 6 ++++++ 11 files changed, 25 insertions(+), 18 deletions(-) diff --git a/app/src/main/res/layout/item_address_detail.xml b/app/src/main/res/layout/item_address_detail.xml index 5276458083..f28f87f461 100644 --- a/app/src/main/res/layout/item_address_detail.xml +++ b/app/src/main/res/layout/item_address_detail.xml @@ -21,11 +21,11 @@ diff --git a/app/src/main/res/layout/item_network_display.xml b/app/src/main/res/layout/item_network_display.xml index d727de7efc..12bc36c82c 100644 --- a/app/src/main/res/layout/item_network_display.xml +++ b/app/src/main/res/layout/item_network_display.xml @@ -18,9 +18,10 @@ android:paddingHorizontal="@dimen/standard_16"> diff --git a/app/src/main/res/layout/item_sign_data.xml b/app/src/main/res/layout/item_sign_data.xml index 58ebffc846..add3046665 100644 --- a/app/src/main/res/layout/item_sign_data.xml +++ b/app/src/main/res/layout/item_sign_data.xml @@ -21,11 +21,11 @@ diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml index f90362827d..3b89ec335c 100644 --- a/app/src/main/res/values/integers.xml +++ b/app/src/main/res/values/integers.xml @@ -1,7 +1,7 @@ - 1 - 3.5 + 1.3 + 3.2 0.6 \ No newline at end of file diff --git a/app/src/main/res/values/typography.xml b/app/src/main/res/values/typography.xml index a4dbceec6b..fc9127f41e 100644 --- a/app/src/main/res/values/typography.xml +++ b/app/src/main/res/values/typography.xml @@ -70,6 +70,12 @@ ?android:textColorSecondary + +