diff --git a/src/main/java/org/qortal/api/resource/CrossChainResource.java b/src/main/java/org/qortal/api/resource/CrossChainResource.java index fdd74b7d..8733b9df 100644 --- a/src/main/java/org/qortal/api/resource/CrossChainResource.java +++ b/src/main/java/org/qortal/api/resource/CrossChainResource.java @@ -195,6 +195,10 @@ public class CrossChainResource { if (minimumTimestamp != null) { minimumFinalHeight = repository.getBlockRepository().getHeightFromTimestamp(minimumTimestamp); + if (minimumFinalHeight == 0) { + // Try the archive + minimumFinalHeight = repository.getBlockArchiveRepository().getHeightFromTimestamp(minimumTimestamp); + } if (minimumFinalHeight == 0) // We don't have any blocks since minimumTimestamp, let alone trades, so nothing to return @@ -222,6 +226,10 @@ public class CrossChainResource { // We also need block timestamp for use as trade timestamp long timestamp = repository.getBlockRepository().getTimestampFromHeight(atState.getHeight()); + if (timestamp == 0) { + // Try the archive + timestamp = repository.getBlockArchiveRepository().getTimestampFromHeight(atState.getHeight()); + } CrossChainTradeSummary crossChainTradeSummary = new CrossChainTradeSummary(crossChainTradeData, timestamp); crossChainTrades.add(crossChainTradeSummary); @@ -260,7 +268,12 @@ public class CrossChainResource { description = "Maximum number of trades to include in price calculation", example = "10", schema = @Schema(type = "integer", defaultValue = "10") - ) @QueryParam("maxtrades") Integer maxtrades) { + ) @QueryParam("maxtrades") Integer maxtrades, + @Parameter( + description = "Display price in terms of foreign currency per unit QORT", + example = "false", + schema = @Schema(type = "boolean", defaultValue = "false") + ) @QueryParam("inverse") Boolean inverse) { // foreignBlockchain is required if (foreignBlockchain == null) throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); @@ -291,7 +304,7 @@ public class CrossChainResource { } } - return Amounts.scaledDivide(totalQort, totalForeign); + return inverse ? Amounts.scaledDivide(totalForeign, totalQort) : Amounts.scaledDivide(totalQort, totalForeign); } catch (DataException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); } @@ -421,4 +434,4 @@ public class CrossChainResource { } } -} \ No newline at end of file +} diff --git a/src/main/java/org/qortal/crosschain/Bitcoin.java b/src/main/java/org/qortal/crosschain/Bitcoin.java index 2ce21d2f..6d904eb4 100644 --- a/src/main/java/org/qortal/crosschain/Bitcoin.java +++ b/src/main/java/org/qortal/crosschain/Bitcoin.java @@ -42,36 +42,30 @@ public class Bitcoin extends Bitcoiny { public Collection getServers() { return Arrays.asList( // Servers chosen on NO BASIS WHATSOEVER from various sources! - new Server("128.0.190.26", Server.ConnectionType.SSL, 50002), new Server("hodlers.beer", Server.ConnectionType.SSL, 50002), - new Server("electrumx.erbium.eu", Server.ConnectionType.TCP, 50001), - new Server("electrumx.erbium.eu", Server.ConnectionType.SSL, 50002), new Server("btc.lastingcoin.net", Server.ConnectionType.SSL, 50002), new Server("electrum.bitaroo.net", Server.ConnectionType.SSL, 50002), new Server("bitcoin.grey.pw", Server.ConnectionType.SSL, 50002), - new Server("2electrumx.hopto.me", Server.ConnectionType.SSL, 56022), new Server("185.64.116.15", Server.ConnectionType.SSL, 50002), - new Server("kirsche.emzy.de", Server.ConnectionType.SSL, 50002), new Server("alviss.coinjoined.com", Server.ConnectionType.SSL, 50002), - new Server("electrum.emzy.de", Server.ConnectionType.SSL, 50002), - new Server("electrum.emzy.de", Server.ConnectionType.TCP, 50001), - new Server("vmd71287.contaboserver.net", Server.ConnectionType.SSL, 50002), new Server("btc.litepay.ch", Server.ConnectionType.SSL, 50002), - new Server("electrum.stippy.com", Server.ConnectionType.SSL, 50002), new Server("xtrum.com", Server.ConnectionType.SSL, 50002), new Server("electrum.acinq.co", Server.ConnectionType.SSL, 50002), - new Server("electrum2.taborsky.cz", Server.ConnectionType.SSL, 50002), - new Server("vmd63185.contaboserver.net", Server.ConnectionType.SSL, 50002), - new Server("electrum2.privateservers.network", Server.ConnectionType.SSL, 50002), - new Server("electrumx.alexridevski.net", Server.ConnectionType.SSL, 50002), - new Server("192.166.219.200", Server.ConnectionType.SSL, 50002), - new Server("2ex.digitaleveryware.com", Server.ConnectionType.SSL, 50002), - new Server("dxm.no-ip.biz", Server.ConnectionType.SSL, 50002), new Server("caleb.vegas", Server.ConnectionType.SSL, 50002), - new Server("ecdsa.net", Server.ConnectionType.SSL, 110), - new Server("electrum.hsmiths.com", Server.ConnectionType.SSL, 995), - new Server("elec.luggs.co", Server.ConnectionType.SSL, 443), - new Server("btc.smsys.me", Server.ConnectionType.SSL, 995)); + new Server("electrum.coinext.com.br", Server.ConnectionType.TCP, 50001), + new Server("korea.electrum-server.com", Server.ConnectionType.TCP, 50001), + new Server("eai.coincited.net", Server.ConnectionType.TCP, 50001), + new Server("electrum.coinext.com.br", Server.ConnectionType.SSL, 50002), + new Server("node1.btccuracao.com", Server.ConnectionType.SSL, 50002), + new Server("korea.electrum-server.com", Server.ConnectionType.SSL, 50002), + new Server("btce.iiiiiii.biz", Server.ConnectionType.SSL, 50002), + new Server("bitcoin.lukechilds.co", Server.ConnectionType.SSL, 50002), + new Server("guichet.centure.cc", Server.ConnectionType.SSL, 50002), + new Server("electrumx.hodlwallet.com", Server.ConnectionType.SSL, 50002), + new Server("eai.coincited.net", Server.ConnectionType.SSL, 50002), + new Server("prospero.bitsrc.net", Server.ConnectionType.SSL, 50002), + new Server("gd42.org", Server.ConnectionType.SSL, 50002), + new Server("electrum.pabu.io", Server.ConnectionType.SSL, 50002)); } @Override diff --git a/src/main/java/org/qortal/repository/BlockArchiveRepository.java b/src/main/java/org/qortal/repository/BlockArchiveRepository.java index 45465e93..9859e137 100644 --- a/src/main/java/org/qortal/repository/BlockArchiveRepository.java +++ b/src/main/java/org/qortal/repository/BlockArchiveRepository.java @@ -71,6 +71,15 @@ public interface BlockArchiveRepository { */ public int getHeightFromTimestamp(long timestamp) throws DataException; + /** + * Returns block timestamp for a given height. + * + * @param height + * @return timestamp, or 0 if height is out of bounds. + * @throws DataException + */ + public long getTimestampFromHeight(int height) throws DataException; + /** * Returns block summaries for blocks signed by passed public key, or reward-share with minter with passed public key. */ diff --git a/src/main/java/org/qortal/repository/hsqldb/HSQLDBBlockArchiveRepository.java b/src/main/java/org/qortal/repository/hsqldb/HSQLDBBlockArchiveRepository.java index 46008c25..d8738f0d 100644 --- a/src/main/java/org/qortal/repository/hsqldb/HSQLDBBlockArchiveRepository.java +++ b/src/main/java/org/qortal/repository/hsqldb/HSQLDBBlockArchiveRepository.java @@ -103,6 +103,20 @@ public class HSQLDBBlockArchiveRepository implements BlockArchiveRepository { } } + @Override + public long getTimestampFromHeight(int height) throws DataException { + String sql = "SELECT minted_when FROM BlockArchive WHERE height = ?"; + + try (ResultSet resultSet = this.repository.checkedExecute(sql, height)) { + if (resultSet == null) + return 0; + + return resultSet.getLong(1); + } catch (SQLException e) { + throw new DataException("Error obtaining block timestamp by height from BlockArchive repository", e); + } + } + @Override public List getBlockSummariesBySigner(byte[] signerPublicKey, Integer limit, Integer offset, Boolean reverse) throws DataException { StringBuilder sql = new StringBuilder(512); diff --git a/src/main/resources/i18n/ApiError_de.properties b/src/main/resources/i18n/ApiError_de.properties index ab7da6b7..9ec2cd6d 100644 --- a/src/main/resources/i18n/ApiError_de.properties +++ b/src/main/resources/i18n/ApiError_de.properties @@ -4,68 +4,68 @@ # "localeLang": "de", ### Common ### -JSON = JSON nachricht konnte nicht geparsed werden +JSON = JSON Nachricht konnte nicht geparst werden INSUFFICIENT_BALANCE = insufficient balance -UNAUTHORIZED = API call unauthorized +UNAUTHORIZED = API-Aufruf nicht autorisiert -REPOSITORY_ISSUE = repository error +REPOSITORY_ISSUE = Repository-Fehler NON_PRODUCTION = this API call is not permitted for production systems BLOCKCHAIN_NEEDS_SYNC = blockchain needs to synchronize first -NO_TIME_SYNC = no clock synchronization yet +NO_TIME_SYNC = noch keine Uhrensynchronisation ### Validation ### -INVALID_SIGNATURE = ungültige signatur +INVALID_SIGNATURE = ungültige Signatur -INVALID_ADDRESS = ungültige adresse +INVALID_ADDRESS = ungültige Adresse INVALID_PUBLIC_KEY = ungültiger public key -INVALID_DATA = ungültige daten +INVALID_DATA = ungültige Daten -INVALID_NETWORK_ADDRESS = invalid network address +INVALID_NETWORK_ADDRESS = ungültige Netzwerk Adresse -ADDRESS_UNKNOWN = account address unknown +ADDRESS_UNKNOWN = Account Adresse unbekannt -INVALID_CRITERIA = invalid search criteria +INVALID_CRITERIA = ungültige Suchkriterien -INVALID_REFERENCE = invalid reference +INVALID_REFERENCE = ungültige Referenz -TRANSFORMATION_ERROR = could not transform JSON into transaction +TRANSFORMATION_ERROR = konnte JSON nicht in eine Transaktion umwandeln -INVALID_PRIVATE_KEY = invalid private key +INVALID_PRIVATE_KEY = ungültiger private key -INVALID_HEIGHT = invalid block height +INVALID_HEIGHT = ungültige block height -CANNOT_MINT = account cannot mint +CANNOT_MINT = Account kann nicht minten ### Blocks ### -BLOCK_UNKNOWN = block unknown +BLOCK_UNKNOWN = block unbekannt ### Transactions ### -TRANSACTION_UNKNOWN = transaction unknown +TRANSACTION_UNKNOWN = Transaktion unbekannt PUBLIC_KEY_NOT_FOUND = public key wurde nicht gefunden # this one is special in that caller expected to pass two additional strings, hence the two %s -TRANSACTION_INVALID = transaction invalid: %s (%s) +TRANSACTION_INVALID = Transaktion ungültig: %s (%s) ### Naming ### -NAME_UNKNOWN = name unknown +NAME_UNKNOWN = Name unbekannt ### Asset ### INVALID_ASSET_ID = ungültige asset ID -INVALID_ORDER_ID = invalid asset order ID +INVALID_ORDER_ID = ungültige asset order ID -ORDER_UNKNOWN = unknown asset order ID +ORDER_UNKNOWN = unbekannte asset order ID ### Groups ### -GROUP_UNKNOWN = group unknown +GROUP_UNKNOWN = Gruppe unbekannt ### Foreign Blockchain ### FOREIGN_BLOCKCHAIN_NETWORK_ISSUE = foreign blokchain or ElectrumX network issue @@ -78,6 +78,7 @@ FOREIGN_BLOCKCHAIN_TOO_SOON = too soon to broadcast foreign blockchain transacti ORDER_SIZE_TOO_SMALL = order amount too low ### Data ### -FILE_NOT_FOUND = file not found +FILE_NOT_FOUND = Datei nicht gefunden + +NO_REPLY = peer did not reply with data -NO_REPLY = peer did not reply with data \ No newline at end of file diff --git a/src/main/resources/i18n/SysTray_de.properties b/src/main/resources/i18n/SysTray_de.properties new file mode 100644 index 00000000..0f2a93dc --- /dev/null +++ b/src/main/resources/i18n/SysTray_de.properties @@ -0,0 +1,40 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) +# SysTray pop-up menu + +AUTO_UPDATE = Automatisches Update + +APPLYING_UPDATE_AND_RESTARTING = Automatisches Update anwenden und neu starten … + +BLOCK_HEIGHT = height + +BUILD_VERSION = Build-Version + +CHECK_TIME_ACCURACY = Prüfe Zeitgenauigkeit + +CONNECTING = Verbindung wird hergestellt + +CONNECTION = Verbindung + +CONNECTIONS = Verbindungen + +CREATING_BACKUP_OF_DB_FILES = Erstellen Backup von Datenbank Dateien … + +DB_BACKUP = Datenbank Backup + +DB_CHECKPOINT = Datenbank Kontrollpunkt + +EXIT = Verlassen + +MINTING_DISABLED = NOT minting + +MINTING_ENABLED = \u2714 Minting + +OPEN_UI = Öffne UI + +PERFORMING_DB_CHECKPOINT = Speichern nicht übergebener Datenbank Änderungen … + +SYNCHRONIZE_CLOCK = Synchronisiere Uhr + +SYNCHRONIZING_BLOCKCHAIN = Synchronisierung + +SYNCHRONIZING_CLOCK = Synchronisierung Uhr diff --git a/src/test/java/org/qortal/test/BootstrapTests.java b/src/test/java/org/qortal/test/BootstrapTests.java index 70852b68..6baa57ac 100644 --- a/src/test/java/org/qortal/test/BootstrapTests.java +++ b/src/test/java/org/qortal/test/BootstrapTests.java @@ -208,8 +208,11 @@ public class BootstrapTests extends Common { private void deleteBootstraps() throws IOException { try { - Path path = Paths.get(String.format("%s%s", Settings.getInstance().getBootstrapFilenamePrefix(), "bootstrap-archive.7z")); - Files.delete(path); + Path archivePath = Paths.get(String.format("%s%s", Settings.getInstance().getBootstrapFilenamePrefix(), "bootstrap-archive.7z")); + Files.delete(archivePath); + + Path sha256Path = Paths.get(String.format("%s%s", Settings.getInstance().getBootstrapFilenamePrefix(), "bootstrap-archive.7z.sha256")); + Files.delete(sha256Path); } catch (NoSuchFileException e) { // Nothing to delete