mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Refactor and fix asset checks
This commit is contained in:
parent
c231750900
commit
fd87ff369c
@ -18,6 +18,7 @@
|
||||
package bisq.core.locale;
|
||||
|
||||
import bisq.core.app.BisqEnvironment;
|
||||
import bisq.core.btc.BaseCurrencyNetwork;
|
||||
|
||||
import bisq.common.app.DevEnv;
|
||||
|
||||
@ -34,6 +35,8 @@ import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
|
||||
|
||||
import bisq.asset.Asset;
|
||||
@ -108,8 +111,8 @@ public class CurrencyUtil {
|
||||
private static List<CryptoCurrency> createAllSortedCryptoCurrenciesList() {
|
||||
List<CryptoCurrency> result = assetRegistry.stream()
|
||||
.filter(CurrencyUtil::assetIsNotBaseCurrency)
|
||||
.filter(CurrencyUtil::isNotBsqOrBsqTradingActivated)
|
||||
.filter(CurrencyUtil::assetMatchesNetwork)
|
||||
.filter(asset -> isNotBsqOrBsqTradingActivated(asset, BisqEnvironment.getBaseCurrencyNetwork(), DevEnv.isDaoTradingActivated()))
|
||||
.filter(asset -> assetMatchesNetworkIfMainnet(asset, BisqEnvironment.getBaseCurrencyNetwork()))
|
||||
.map(CurrencyUtil::assetToCryptoCurrency)
|
||||
.sorted(TradeCurrency::compareTo)
|
||||
.collect(Collectors.toList());
|
||||
@ -367,21 +370,71 @@ public class CurrencyUtil {
|
||||
}
|
||||
|
||||
private static boolean assetIsNotBaseCurrency(Asset asset) {
|
||||
return !asset.getTickerSymbol().equals(baseCurrencyCode);
|
||||
return !assetMatchesCurrencyCode(asset, baseCurrencyCode);
|
||||
}
|
||||
|
||||
// TODO We handle assets of other types (Token, ERC20) as matching the network which is not correct.
|
||||
// We should add support for network property in those tokens as well.
|
||||
private static boolean assetMatchesNetwork(Asset asset) {
|
||||
public static boolean assetMatchesNetwork(Asset asset, BaseCurrencyNetwork baseCurrencyNetwork) {
|
||||
return !(asset instanceof Coin) ||
|
||||
((Coin) asset).getNetwork().name().equals(BisqEnvironment.getBaseCurrencyNetwork().getNetwork());
|
||||
((Coin) asset).getNetwork().name().equals(baseCurrencyNetwork.getNetwork());
|
||||
}
|
||||
|
||||
// We only check for coins not other types of assets (TODO network check should be supported for all assets)
|
||||
public static boolean assetMatchesNetworkIfMainnet(Asset asset, BaseCurrencyNetwork baseCurrencyNetwork) {
|
||||
return !(asset instanceof Coin) ||
|
||||
coinMatchesNetworkIfMainnet((Coin) asset, baseCurrencyNetwork);
|
||||
}
|
||||
|
||||
// We want all coins available also in testnet or regtest for testing purpose
|
||||
public static boolean coinMatchesNetworkIfMainnet(Coin coin, BaseCurrencyNetwork baseCurrencyNetwork) {
|
||||
boolean matchesNetwork = assetMatchesNetwork(coin, baseCurrencyNetwork);
|
||||
return !baseCurrencyNetwork.isMainnet() ||
|
||||
matchesNetwork;
|
||||
}
|
||||
|
||||
private static CryptoCurrency assetToCryptoCurrency(Asset asset) {
|
||||
return new CryptoCurrency(asset.getTickerSymbol(), asset.getName(), asset instanceof Token);
|
||||
}
|
||||
|
||||
private static boolean isNotBsqOrBsqTradingActivated(Asset asset) {
|
||||
return !(asset instanceof BSQ) || DevEnv.isDaoTradingActivated() && assetMatchesNetwork(asset);
|
||||
private static boolean isNotBsqOrBsqTradingActivated(Asset asset, BaseCurrencyNetwork baseCurrencyNetwork, boolean daoTradingActivated) {
|
||||
return !(asset instanceof BSQ) ||
|
||||
daoTradingActivated && assetMatchesNetwork(asset, baseCurrencyNetwork);
|
||||
}
|
||||
|
||||
public static boolean assetMatchesCurrencyCode(Asset asset, String currencyCode) {
|
||||
return currencyCode.equals(asset.getTickerSymbol());
|
||||
}
|
||||
|
||||
public static Optional<Asset> findAsset(AssetRegistry assetRegistry, String currencyCode,
|
||||
BaseCurrencyNetwork baseCurrencyNetwork, boolean daoTradingActivated) {
|
||||
List<Asset> assets = assetRegistry.stream()
|
||||
.filter(asset -> assetMatchesCurrencyCode(asset, currencyCode)).collect(Collectors.toList());
|
||||
|
||||
// If we don't have the ticker symbol we throw an exception
|
||||
if (!assets.stream().findFirst().isPresent())
|
||||
return Optional.empty();
|
||||
|
||||
if (currencyCode.equals("BSQ") && baseCurrencyNetwork.isMainnet() && !daoTradingActivated)
|
||||
return Optional.empty();
|
||||
|
||||
// We check for exact match with network, e.g. BTC$TESTNET
|
||||
Optional<Asset> optionalAssetMatchesNetwork = assets.stream()
|
||||
.filter(asset -> assetMatchesNetwork(asset, baseCurrencyNetwork))
|
||||
.findFirst();
|
||||
if (optionalAssetMatchesNetwork.isPresent())
|
||||
return optionalAssetMatchesNetwork;
|
||||
|
||||
// In testnet or regtest we want to show all coins as well. Most coins have only Mainnet defined so we deliver
|
||||
// that if no exact match was found in previous step
|
||||
if (!baseCurrencyNetwork.isMainnet()) {
|
||||
Optional<Asset> optionalAsset = assets.stream().findFirst();
|
||||
checkArgument(optionalAsset.isPresent(), "optionalAsset must be present as we checked for " +
|
||||
"not matching ticker symbols already above");
|
||||
return optionalAsset;
|
||||
}
|
||||
|
||||
// If we are in mainnet we need have a mainet asset defined.
|
||||
throw new IllegalArgumentException("We are on mainnet and we could not find an asset with network type mainnet");
|
||||
}
|
||||
}
|
||||
|
@ -18,22 +18,23 @@
|
||||
package bisq.core.payment.validation;
|
||||
|
||||
import bisq.core.app.BisqEnvironment;
|
||||
import bisq.core.btc.BaseCurrencyNetwork;
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.validation.InputValidator;
|
||||
|
||||
import bisq.common.app.DevEnv;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
|
||||
import bisq.asset.AddressValidationResult;
|
||||
import bisq.asset.Asset;
|
||||
import bisq.asset.AssetRegistry;
|
||||
import bisq.asset.Coin;
|
||||
|
||||
@Slf4j
|
||||
public final class AltCoinAddressValidator extends InputValidator {
|
||||
@ -56,30 +57,19 @@ public final class AltCoinAddressValidator extends InputValidator {
|
||||
if (!validationResult.isValid || currencyCode == null)
|
||||
return validationResult;
|
||||
|
||||
Asset asset = assetRegistry.stream()
|
||||
.filter(this::assetMatchesSelectedCurrencyCode)
|
||||
.filter(this::assetIsNotBaseCurrencyForDifferentNetwork)
|
||||
.findFirst()
|
||||
.orElseThrow(() ->
|
||||
new IllegalArgumentException(format("'%s' is not a registered asset", currencyCode)));
|
||||
Optional<Asset> optionalAsset = CurrencyUtil.findAsset(assetRegistry, currencyCode,
|
||||
BisqEnvironment.getBaseCurrencyNetwork(), DevEnv.isDaoTradingActivated());
|
||||
if (optionalAsset.isPresent()) {
|
||||
Asset asset = optionalAsset.get();
|
||||
AddressValidationResult result = asset.validateAddress(input);
|
||||
if (!result.isValid()) {
|
||||
return new ValidationResult(false, Res.get(result.getI18nKey(), asset.getTickerSymbol(),
|
||||
result.getMessage()));
|
||||
}
|
||||
|
||||
AddressValidationResult result = asset.validateAddress(input);
|
||||
if (!result.isValid())
|
||||
return new ValidationResult(false,
|
||||
Res.get(result.getI18nKey(), asset.getTickerSymbol(), result.getMessage()));
|
||||
|
||||
return new ValidationResult(true);
|
||||
}
|
||||
|
||||
private boolean assetMatchesSelectedCurrencyCode(Asset a) {
|
||||
return currencyCode.equals(a.getTickerSymbol());
|
||||
}
|
||||
|
||||
private boolean assetIsNotBaseCurrencyForDifferentNetwork(Asset asset) {
|
||||
BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
|
||||
|
||||
return !(asset instanceof Coin)
|
||||
|| !asset.getTickerSymbol().equals(baseCurrencyNetwork.getCurrencyCode())
|
||||
|| (((Coin) asset).getNetwork().name().equals(baseCurrencyNetwork.getNetwork()));
|
||||
return new ValidationResult(true);
|
||||
} else {
|
||||
return new ValidationResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,15 +17,30 @@
|
||||
|
||||
package bisq.core.locale;
|
||||
|
||||
import bisq.core.btc.BaseCurrencyNetwork;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
|
||||
import bisq.asset.Asset;
|
||||
import bisq.asset.AssetRegistry;
|
||||
import bisq.asset.Coin;
|
||||
import bisq.asset.coins.Ether;
|
||||
|
||||
public class CurrencyUtilTest {
|
||||
|
||||
@Before
|
||||
@ -39,9 +54,95 @@ public class CurrencyUtilTest {
|
||||
Optional<TradeCurrency> naira = CurrencyUtil.getTradeCurrency("NGN");
|
||||
Optional<TradeCurrency> fake = CurrencyUtil.getTradeCurrency("FAK");
|
||||
|
||||
|
||||
assertTrue(euro.isPresent());
|
||||
assertTrue(naira.isPresent());
|
||||
assertFalse("Fake currency shouldn't exist", fake.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAsset() {
|
||||
MockAssetRegistry assetRegistry = new MockAssetRegistry();
|
||||
|
||||
// test if code is matching
|
||||
boolean daoTradingActivated = false;
|
||||
// Test if BSQ on mainnet is failing
|
||||
Assert.assertFalse(CurrencyUtil.findAsset(assetRegistry, "BSQ",
|
||||
BaseCurrencyNetwork.BTC_MAINNET, daoTradingActivated).isPresent());
|
||||
|
||||
// on testnet/regtest it is allowed
|
||||
assertEquals(CurrencyUtil.findAsset(assetRegistry, "BSQ",
|
||||
BaseCurrencyNetwork.BTC_TESTNET, daoTradingActivated).get().getTickerSymbol(), "BSQ");
|
||||
|
||||
|
||||
daoTradingActivated = true;
|
||||
// With daoTradingActivated we can request BSQ
|
||||
assertEquals(CurrencyUtil.findAsset(assetRegistry, "BSQ",
|
||||
BaseCurrencyNetwork.BTC_MAINNET, daoTradingActivated).get().getTickerSymbol(), "BSQ");
|
||||
|
||||
// Test if not matching ticker is failing
|
||||
Assert.assertFalse(CurrencyUtil.findAsset(assetRegistry, "BSQ1",
|
||||
BaseCurrencyNetwork.BTC_MAINNET, daoTradingActivated).isPresent());
|
||||
|
||||
// Add a mock coin which has no mainnet version, needs to fail if we are on mainnet
|
||||
MockTestnetCoin.Testnet mockTestnetCoin = new MockTestnetCoin.Testnet();
|
||||
try {
|
||||
assetRegistry.addAsset(mockTestnetCoin);
|
||||
CurrencyUtil.findAsset(assetRegistry, "MOCK_COIN",
|
||||
BaseCurrencyNetwork.BTC_MAINNET, daoTradingActivated);
|
||||
Assert.fail("Expected an IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
String wantMessage = "We are on mainnet and we could not find an asset with network type mainnet";
|
||||
Assert.assertTrue("Unexpected exception, want message starting with " +
|
||||
"'" + wantMessage + "', got '" + e.getMessage() + "'", e.getMessage().startsWith(wantMessage));
|
||||
}
|
||||
|
||||
// For testnet its ok
|
||||
assertEquals(CurrencyUtil.findAsset(assetRegistry, "MOCK_COIN",
|
||||
BaseCurrencyNetwork.BTC_TESTNET, daoTradingActivated).get().getTickerSymbol(), "MOCK_COIN");
|
||||
assertEquals(Coin.Network.TESTNET, mockTestnetCoin.getNetwork());
|
||||
|
||||
// For regtest its still found
|
||||
assertEquals(CurrencyUtil.findAsset(assetRegistry, "MOCK_COIN",
|
||||
BaseCurrencyNetwork.BTC_REGTEST, daoTradingActivated).get().getTickerSymbol(), "MOCK_COIN");
|
||||
|
||||
|
||||
// We test if we are not on mainnet to get the mainnet coin
|
||||
Coin ether = new Ether();
|
||||
assertEquals(CurrencyUtil.findAsset(assetRegistry, "ETH",
|
||||
BaseCurrencyNetwork.BTC_TESTNET, daoTradingActivated).get().getTickerSymbol(), "ETH");
|
||||
assertEquals(CurrencyUtil.findAsset(assetRegistry, "ETH",
|
||||
BaseCurrencyNetwork.BTC_REGTEST, daoTradingActivated).get().getTickerSymbol(), "ETH");
|
||||
assertEquals(Coin.Network.MAINNET, ether.getNetwork());
|
||||
|
||||
// We test if network matches exactly if there are distinct network types defined like with BSQ
|
||||
Coin bsq = (Coin) CurrencyUtil.findAsset(assetRegistry, "BSQ", BaseCurrencyNetwork.BTC_MAINNET, daoTradingActivated).get();
|
||||
assertEquals("BSQ", bsq.getTickerSymbol());
|
||||
assertEquals(Coin.Network.MAINNET, bsq.getNetwork());
|
||||
|
||||
bsq = (Coin) CurrencyUtil.findAsset(assetRegistry, "BSQ", BaseCurrencyNetwork.BTC_TESTNET, daoTradingActivated).get();
|
||||
assertEquals("BSQ", bsq.getTickerSymbol());
|
||||
assertEquals(Coin.Network.TESTNET, bsq.getNetwork());
|
||||
|
||||
bsq = (Coin) CurrencyUtil.findAsset(assetRegistry, "BSQ", BaseCurrencyNetwork.BTC_REGTEST, daoTradingActivated).get();
|
||||
assertEquals("BSQ", bsq.getTickerSymbol());
|
||||
assertEquals(Coin.Network.REGTEST, bsq.getNetwork());
|
||||
}
|
||||
|
||||
class MockAssetRegistry extends AssetRegistry {
|
||||
private List<Asset> registeredAssets = new ArrayList<>();
|
||||
|
||||
MockAssetRegistry() {
|
||||
for (Asset asset : ServiceLoader.load(Asset.class)) {
|
||||
registeredAssets.add(asset);
|
||||
}
|
||||
}
|
||||
|
||||
void addAsset(Asset asset) {
|
||||
registeredAssets.add(asset);
|
||||
}
|
||||
|
||||
public Stream<Asset> stream() {
|
||||
return registeredAssets.stream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
69
core/src/test/java/bisq/core/locale/MockTestnetCoin.java
Normal file
69
core/src/test/java/bisq/core/locale/MockTestnetCoin.java
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.core.locale;
|
||||
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.params.MainNetParams;
|
||||
import org.bitcoinj.params.RegTestParams;
|
||||
import org.bitcoinj.params.TestNet3Params;
|
||||
|
||||
|
||||
|
||||
import bisq.asset.AddressValidationResult;
|
||||
import bisq.asset.Base58BitcoinAddressValidator;
|
||||
import bisq.asset.Coin;
|
||||
|
||||
public class MockTestnetCoin extends Coin {
|
||||
|
||||
public MockTestnetCoin(Network network, NetworkParameters networkParameters) {
|
||||
super("MockTestnetCoin", "MOCK_COIN", new BSQAddressValidator(networkParameters), network);
|
||||
}
|
||||
|
||||
public static class Mainnet extends MockTestnetCoin {
|
||||
|
||||
public Mainnet() {
|
||||
super(Network.MAINNET, MainNetParams.get());
|
||||
}
|
||||
}
|
||||
|
||||
public static class Testnet extends MockTestnetCoin {
|
||||
|
||||
public Testnet() {
|
||||
super(Network.TESTNET, TestNet3Params.get());
|
||||
}
|
||||
}
|
||||
|
||||
public static class Regtest extends MockTestnetCoin {
|
||||
|
||||
public Regtest() {
|
||||
super(Network.REGTEST, RegTestParams.get());
|
||||
}
|
||||
}
|
||||
|
||||
public static class BSQAddressValidator extends Base58BitcoinAddressValidator {
|
||||
|
||||
public BSQAddressValidator(NetworkParameters networkParameters) {
|
||||
super(networkParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressValidationResult validate(String address) {
|
||||
return super.validate(address);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user