From 1d69010b28c06404030a9081cb83c1ed26dc67c3 Mon Sep 17 00:00:00 2001 From: Samuel Tessian Date: Mon, 20 Nov 2023 12:36:46 +1100 Subject: [PATCH] MultiversX provider improvement - get chosen ESDTs --- README.md | 20 ++++ .../allmycoins/balance/multiversx/ESDT.java | 103 ++++++++++++++++++ .../allmycoins/balance/multiversx/ESDTs.java | 24 ++++ .../MultiversXAddressBalanceJson.java | 2 +- .../MultiversXAddressBalanceRequest.java | 3 +- .../MultiversXBalanceRequestJson.java | 2 +- .../multiversx/MultiversXDelegationJson.java | 2 +- .../MultiversXDelegationsRequest.java | 2 +- .../multiversx/MultiversXEsdtBalanceJson.java | 28 +++++ .../MultiversXEsdtBalancesRequest.java | 44 ++++++++ .../multiversx/MultiversXProvider.java | 56 +++++++--- .../multiversx/UserUndelegatedJson.java | 2 +- .../balance/MultiversXProviderTest.java | 4 +- 13 files changed, 266 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/allmycoins/balance/multiversx/ESDT.java create mode 100644 src/main/java/com/allmycoins/balance/multiversx/ESDTs.java create mode 100644 src/main/java/com/allmycoins/balance/multiversx/MultiversXEsdtBalanceJson.java create mode 100644 src/main/java/com/allmycoins/balance/multiversx/MultiversXEsdtBalancesRequest.java diff --git a/README.md b/README.md index f380249..291fd22 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,26 @@ AllMyCoins is a simple crypto portfolio manager. - Lum Lum - Desmos Desmos +##### MultiversX ecosystem +* Elrond MultiversX +From the public address, retrieves: +* EGLD: wallet balance, staking delegation, WEGLD, SEGLD, HSEGLD (not deposited in collateral) +* EDSTs: + - WBTC + - WETH + - USDC + - BUSD + - USDT + - MEX, XMEX + - UTK (+ staked on XExchange) + - HTM (+ staked on XExchange) + - ASH + - RIDE (+ staked on XExchange) + - ITHEUM (+ staked on XExchange) + - CRT (+ staked on XExchange) + - BHAT (+ staked on XExchange) + - ZPAY (+ staked on XExchange) + ## Display AllMyCoins Window diff --git a/src/main/java/com/allmycoins/balance/multiversx/ESDT.java b/src/main/java/com/allmycoins/balance/multiversx/ESDT.java new file mode 100644 index 0000000..919f754 --- /dev/null +++ b/src/main/java/com/allmycoins/balance/multiversx/ESDT.java @@ -0,0 +1,103 @@ +package com.allmycoins.balance.multiversx; + +enum ESDT { + /* BTC. */ + ASH("ASH", "ASH-a642d1"), + /* BHAT. */ + BHAT("BHAT", "BHAT-c1fde3"), + /* BTC. */ + BTC("WBTC", "WBTC-5349b3"), + /* BUSD. */ + BUSD("BUSD", "BUSD-40b57e"), + /* CRT. */ + CRT("CRT", "CRT-52decf"), + /* ETH. */ + ETH("WETH", "WETH-b4ca29"), + /* HSEGLD - Deposited Hatom Staked EGLD. */ + HSEGLD("EGLD", "HSEGLD", "HSEGLD-c13a4e", "HSEGLD"), + /* HTM. */ + HTM("HTM", "HTM-f51d55"), + /* ITHEUM. */ + ITHEUM("ITHEUM", "ITHEUM-df6f26"), + /* MEX. */ + MEX("MEX", "MEX-455c57"), + /* SUTK. */ + RIDE("RIDE", "RIDE-7d18e9"), + /* SBHAT. */ + SBHAT("BHAT", "SBHAT", "SBHAT-89efd3", "Staked BHAT"), + /* SCRT. */ + SCRT("CRT", "SCRT", "SCRT-acbd64", "Staked CRT"), + /* SHTM. */ + SHTM("HTM", "SHTM", "SHTM-b8b430", "Staked HTM"), + /* SEGLD - Hatom Staked EGLD. */ + SEGLD("EGLD", "SEGLD", "SEGLD-3ad2d0", "SEGLD"), + /* SITHEUM. */ + SITHEUM("ITHEUM", "SITHEUM", "SITHEUM-e05083"), + /* SRIDE. */ + SRIDE("RIDE", "SRIDE", "SRIDE-4ab1d4", "Staked RIDE"), + /* SUTK. */ + SUTK("UTK", "SUTK", "SUTK-ba35f3", "Staked UTK"), + /* SZPAY. */ + SZPAY("ZPAY", "SZPAY", "SZPAY-9f1b39", "Staked ZPAY"), + /* USDT. */ + USDC("USDC", "USDC-c76f1f"), + /* USDT. */ + USDT("USDT", "USDT-f8c08c"), + /* UTK. */ + UTK("UTK", "UTK-2f80e9"), + /* WEGLD. */ + WEGLD("EGLD", "WEGLD", "WEGLD-bd4d79"), + /* XMEX. */ + XMEX("MEX", "XMEX", "XMEX-fda355"), + /* SZPAY. */ + ZPAY("ZPAY", "ZPAY-247875"); + + /* + * Multiple ESDTs can be different version of the same coin. For simplicity, + * they are gathered under the reference token. + */ + private String referenceSymbol; + + private String ticker; + + private String identifier; + + private String source; + + ESDT(String aTicker, String aIdentifier) { + referenceSymbol = null; + ticker = aTicker; + identifier = aIdentifier; + source = null; + } + + ESDT(String aReferenceSymbol, String aTicker, String aIdentifier) { + referenceSymbol = aReferenceSymbol; + ticker = aTicker; + identifier = aIdentifier; + source = null; + } + + ESDT(String aReferenceSymbol, String aTicker, String aIdentifier, String aSource) { + referenceSymbol = aReferenceSymbol; + ticker = aTicker; + identifier = aIdentifier; + source = aSource; + } + + public String getTicker() { + return ticker; + } + + public String getIdentifier() { + return identifier; + } + + public String getReferenceSymbol() { + return referenceSymbol != null ? referenceSymbol : ticker; + } + + public String getSource() { + return source == null ? "MVX W" : source; + } +} diff --git a/src/main/java/com/allmycoins/balance/multiversx/ESDTs.java b/src/main/java/com/allmycoins/balance/multiversx/ESDTs.java new file mode 100644 index 0000000..e59f6f9 --- /dev/null +++ b/src/main/java/com/allmycoins/balance/multiversx/ESDTs.java @@ -0,0 +1,24 @@ +package com.allmycoins.balance.multiversx; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Utility class for ESDT tokens. + */ +final class ESDTs { + + private static final List ESDTS = List.of(ESDT.values()); + + private ESDTs() { + /* Empty. */ + } + + static final List getIdentifiers() { + return ESDTS.stream().map(ESDT::getIdentifier).collect(Collectors.toList()); + } + + static final ESDT getEsdt(final String ticker) { + return ESDTS.stream().filter(esdt -> esdt.getTicker().equals(ticker)).findFirst().get(); + } +} diff --git a/src/main/java/com/allmycoins/balance/multiversx/MultiversXAddressBalanceJson.java b/src/main/java/com/allmycoins/balance/multiversx/MultiversXAddressBalanceJson.java index 8bbc445..5a4f232 100644 --- a/src/main/java/com/allmycoins/balance/multiversx/MultiversXAddressBalanceJson.java +++ b/src/main/java/com/allmycoins/balance/multiversx/MultiversXAddressBalanceJson.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public final class MultiversXAddressBalanceJson { +final class MultiversXAddressBalanceJson { private BigDecimal balance; diff --git a/src/main/java/com/allmycoins/balance/multiversx/MultiversXAddressBalanceRequest.java b/src/main/java/com/allmycoins/balance/multiversx/MultiversXAddressBalanceRequest.java index 9925c8b..42b7090 100644 --- a/src/main/java/com/allmycoins/balance/multiversx/MultiversXAddressBalanceRequest.java +++ b/src/main/java/com/allmycoins/balance/multiversx/MultiversXAddressBalanceRequest.java @@ -5,7 +5,7 @@ import com.allmycoins.request.GetRequest; -public final class MultiversXAddressBalanceRequest implements GetRequest { +final class MultiversXAddressBalanceRequest implements GetRequest { private final String address; @@ -37,5 +37,4 @@ public Class jsonResponseClass() { public String parameters() { return ""; } - } diff --git a/src/main/java/com/allmycoins/balance/multiversx/MultiversXBalanceRequestJson.java b/src/main/java/com/allmycoins/balance/multiversx/MultiversXBalanceRequestJson.java index 4d53fc1..52f01de 100644 --- a/src/main/java/com/allmycoins/balance/multiversx/MultiversXBalanceRequestJson.java +++ b/src/main/java/com/allmycoins/balance/multiversx/MultiversXBalanceRequestJson.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public final class MultiversXBalanceRequestJson { +final class MultiversXBalanceRequestJson { private MultiversXAddressBalanceJson data; diff --git a/src/main/java/com/allmycoins/balance/multiversx/MultiversXDelegationJson.java b/src/main/java/com/allmycoins/balance/multiversx/MultiversXDelegationJson.java index 04d8896..a5c6a1e 100644 --- a/src/main/java/com/allmycoins/balance/multiversx/MultiversXDelegationJson.java +++ b/src/main/java/com/allmycoins/balance/multiversx/MultiversXDelegationJson.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public final class MultiversXDelegationJson { +final class MultiversXDelegationJson { private BigDecimal userActiveStake; private BigDecimal claimableRewards; diff --git a/src/main/java/com/allmycoins/balance/multiversx/MultiversXDelegationsRequest.java b/src/main/java/com/allmycoins/balance/multiversx/MultiversXDelegationsRequest.java index d7c7704..56a05ed 100644 --- a/src/main/java/com/allmycoins/balance/multiversx/MultiversXDelegationsRequest.java +++ b/src/main/java/com/allmycoins/balance/multiversx/MultiversXDelegationsRequest.java @@ -5,7 +5,7 @@ import com.allmycoins.request.GetRequest; -public final class MultiversXDelegationsRequest implements GetRequest { +final class MultiversXDelegationsRequest implements GetRequest { private final String address; diff --git a/src/main/java/com/allmycoins/balance/multiversx/MultiversXEsdtBalanceJson.java b/src/main/java/com/allmycoins/balance/multiversx/MultiversXEsdtBalanceJson.java new file mode 100644 index 0000000..5c4a190 --- /dev/null +++ b/src/main/java/com/allmycoins/balance/multiversx/MultiversXEsdtBalanceJson.java @@ -0,0 +1,28 @@ +package com.allmycoins.balance.multiversx; + +import java.math.BigDecimal; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +final class MultiversXEsdtBalanceJson { + + private String ticker; + + private Long decimals; + + private BigDecimal balance; + + public BigDecimal getBalance() { + return balance; + } + + public String getTicker() { + return ticker; + } + + public Long getDecimals() { + return decimals; + } + +} diff --git a/src/main/java/com/allmycoins/balance/multiversx/MultiversXEsdtBalancesRequest.java b/src/main/java/com/allmycoins/balance/multiversx/MultiversXEsdtBalancesRequest.java new file mode 100644 index 0000000..d6e6558 --- /dev/null +++ b/src/main/java/com/allmycoins/balance/multiversx/MultiversXEsdtBalancesRequest.java @@ -0,0 +1,44 @@ +package com.allmycoins.balance.multiversx; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import com.allmycoins.request.GetRequest; + +public final class MultiversXEsdtBalancesRequest implements GetRequest { + + private final String address; + + public MultiversXEsdtBalancesRequest(String pAddress) { + address = pAddress; + } + + @Override + public String baseUrl() { + return "https://api.multiversx.com"; + } + + @Override + public String endPoint() { + return "/accounts/" + address + "/tokens"; + } + + @Override + public Map headers() { + return Collections.emptyMap(); + } + + @Override + public Class jsonResponseClass() { + return MultiversXEsdtBalanceJson[].class; + } + + @Override + public String parameters() { + String meta = "includeMetaESDT=true"; + String fields = "fields=ticker,decimals,balance"; + String identifiers = "identifiers=" + String.join(",", ESDTs.getIdentifiers()); + return String.join("&", List.of(meta, fields, identifiers)); + } +} diff --git a/src/main/java/com/allmycoins/balance/multiversx/MultiversXProvider.java b/src/main/java/com/allmycoins/balance/multiversx/MultiversXProvider.java index 7be29a6..3be4747 100644 --- a/src/main/java/com/allmycoins/balance/multiversx/MultiversXProvider.java +++ b/src/main/java/com/allmycoins/balance/multiversx/MultiversXProvider.java @@ -5,38 +5,53 @@ import java.math.BigDecimal; import java.util.Arrays; -import java.util.concurrent.Future; +import java.util.List; +import java.util.stream.Collectors; -import com.allmycoins.balance.PublicAddressSingleBalanceProvider; +import com.allmycoins.balance.PublicAddressBalanceProvider; import com.allmycoins.json.BalanceJson; import com.allmycoins.utils.BigDecimalUtils; -import com.allmycoins.utils.FutureUtils; import com.allmycoins.utils.RequestUtils; -public final class MultiversXProvider implements PublicAddressSingleBalanceProvider { +public final class MultiversXProvider implements PublicAddressBalanceProvider { @Override public String privateConfigKey() { return "MULTIVERSX_ADDRESS"; } - @Override - public BalanceJson singleBalance(String publicAddress) { - Future multiversXBalanceRequestJsonF = RequestUtils - .sendRequestFuture(new MultiversXAddressBalanceRequest(publicAddress)); + private BalanceJson getEgldBalance(String publicAddress) { + BigDecimal egldWalletBalance = getEgldWalletBalance(publicAddress); + BigDecimal delegationBalance = getEgldDelegationBalance(publicAddress); - Future multiversXDelegationsJsonF = RequestUtils - .sendRequestFuture(new MultiversXDelegationsRequest(publicAddress)); + BigDecimal allEGLDs = egldWalletBalance.add(delegationBalance); + float qty = BigDecimalUtils.decimal18(allEGLDs); - var multiversXBalanceRequestJson = FutureUtils.futureResult(multiversXBalanceRequestJsonF); - MultiversXDelegationJson[] multiversXDelegationsJson = FutureUtils.futureResult(multiversXDelegationsJsonF); + return new BalanceJson("EGLD", qty, "MVX W"); + } - BigDecimal delegation = Arrays.stream(multiversXDelegationsJson).map(this::sumBalances).reduce(ZERO, - BIG_DECIMAL_SUM); + private List getEgldWalletEsdtBalances(String publicAddress) { + MultiversXEsdtBalanceJson[] esdtBalanceJsons = RequestUtils + .sendRequest(new MultiversXEsdtBalancesRequest(publicAddress)); + + return List.of(esdtBalanceJsons).stream().map(this::toBalanceJson).collect(Collectors.toList()); + } + + private BalanceJson toBalanceJson(MultiversXEsdtBalanceJson balance) { + ESDT esdt = ESDTs.getEsdt(balance.getTicker()); + return new BalanceJson(esdt.getReferenceSymbol(), + BigDecimalUtils.decimal(balance.getBalance(), balance.getDecimals().intValue()), esdt.getSource()); + } + + private BigDecimal getEgldWalletBalance(String publicAddress) { + return RequestUtils.sendRequest(new MultiversXAddressBalanceRequest(publicAddress)).getData().getBalance(); + } + + private BigDecimal getEgldDelegationBalance(String publicAddress) { + MultiversXDelegationJson[] multiversXDelegationsJson = RequestUtils + .sendRequest(new MultiversXDelegationsRequest(publicAddress)); + return Arrays.stream(multiversXDelegationsJson).map(this::sumBalances).reduce(ZERO, BIG_DECIMAL_SUM); - BigDecimal allEGLDs = multiversXBalanceRequestJson.getData().getBalance().add(delegation); - float qty = BigDecimalUtils.decimal18(allEGLDs); - return new BalanceJson("EGLD", qty, "MultiversX wallet"); } private BigDecimal sumBalances(MultiversXDelegationJson delegation) { @@ -44,4 +59,11 @@ private BigDecimal sumBalances(MultiversXDelegationJson delegation) { .reduce(ZERO, BIG_DECIMAL_SUM); return delegation.getUserActiveStake().add(delegation.getClaimableRewards()).add(undelegated); } + + @Override + public List balance(String publicAddress) { + List balances = getEgldWalletEsdtBalances(publicAddress); + balances.add(0, getEgldBalance(publicAddress)); + return balances; + } } diff --git a/src/main/java/com/allmycoins/balance/multiversx/UserUndelegatedJson.java b/src/main/java/com/allmycoins/balance/multiversx/UserUndelegatedJson.java index 9c81151..51c1a91 100644 --- a/src/main/java/com/allmycoins/balance/multiversx/UserUndelegatedJson.java +++ b/src/main/java/com/allmycoins/balance/multiversx/UserUndelegatedJson.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public final class UserUndelegatedJson { +final class UserUndelegatedJson { private BigDecimal amount; diff --git a/src/test/java/com/allmycoins/balance/MultiversXProviderTest.java b/src/test/java/com/allmycoins/balance/MultiversXProviderTest.java index df46171..97cf2ab 100644 --- a/src/test/java/com/allmycoins/balance/MultiversXProviderTest.java +++ b/src/test/java/com/allmycoins/balance/MultiversXProviderTest.java @@ -19,11 +19,11 @@ void testBalances() { MultiversXProvider provider = new MultiversXProvider(); List balance = provider.balances(); - assertEquals(1, balance.size()); + assertTrue(balance.size() >= 1); BalanceJson balanceJson = balance.get(0); assertEquals("EGLD", balanceJson.getAsset()); - assertEquals("MultiversX wallet", balanceJson.getSrc()); + assertEquals("MVX W", balanceJson.getSrc()); assertTrue(balanceJson.getQty() >= 0.0f); }