Compare commits

...

27 commits

Author SHA1 Message Date
62c423ce9c Update docker/Dockerfile.core
Some checks failed
CI / build (macos-13) (push) Has been cancelled
CI / build (ubuntu-22.04) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
Codacy Coverage Reporter / Publish coverage (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
2025-06-26 13:56:09 +00:00
d3945fff7e alter release date
Some checks failed
CI / build (macos-13) (push) Has been cancelled
CI / build (ubuntu-22.04) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
Codacy Coverage Reporter / Publish coverage (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
2025-06-20 05:07:57 +07:00
34cc564f18 no
Some checks are pending
CI / build (macos-13) (push) Waiting to run
CI / build (ubuntu-22.04) (push) Waiting to run
CI / build (windows-latest) (push) Waiting to run
Codacy Coverage Reporter / Publish coverage (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
2025-06-20 05:05:58 +07:00
1be47b7646 completing merge
Some checks are pending
CI / build (macos-13) (push) Waiting to run
CI / build (ubuntu-22.04) (push) Waiting to run
CI / build (windows-latest) (push) Waiting to run
Codacy Coverage Reporter / Publish coverage (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
2025-06-20 05:01:21 +07:00
97c349f6b3 minor fixes 2025-06-20 04:55:34 +07:00
401b363d07 Update README.md
Some checks are pending
CI / build (macos-13) (push) Waiting to run
CI / build (ubuntu-22.04) (push) Waiting to run
CI / build (windows-latest) (push) Waiting to run
Codacy Coverage Reporter / Publish coverage (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
2025-06-19 11:22:26 +00:00
ac4b7c597c seednodes 2025-06-19 11:40:12 +07:00
30460f05f4 serialization network ID set via env var and docker improvements
Some checks are pending
CI / build (macos-13) (push) Waiting to run
CI / build (ubuntu-22.04) (push) Waiting to run
CI / build (windows-latest) (push) Waiting to run
Codacy Coverage Reporter / Publish coverage (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
2025-06-19 11:22:18 +07:00
893fa2ec90 trialing some new grpc stuff
Some checks are pending
CI / build (macos-13) (push) Waiting to run
CI / build (ubuntu-22.04) (push) Waiting to run
CI / build (windows-latest) (push) Waiting to run
Codacy Coverage Reporter / Publish coverage (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
2025-06-19 03:28:21 +07:00
dc062984b3 update 2025-06-09 23:50:06 +07:00
16c2d87cea hi 2025-06-09 22:57:52 +07:00
52bdd156f3 Merge branch 'my-next-version' into 'master'
My next version

See merge request haveno/haveno!8
2025-06-09 14:56:09 +00:00
648165b368 AlertM 2025-06-09 20:14:50 +07:00
36a371ef34 bumped to 1.1.2 2025-06-09 20:11:17 +07:00
woodser
e4e118f70c
rename logos with dark_mode and light_mode postfix 2025-06-09 07:06:43 -04:00
woodser
53e2c5cc24
center the top nav buttons when window is small 2025-06-09 07:06:00 -04:00
woodser
62d5eb4bc3
fix distorted confirm payment sent checkbox in windows dark mode 2025-06-09 07:05:46 -04:00
woodser
183782982c
fix display name of non-fiat traditional currencies 2025-06-09 06:51:59 -04:00
13b201b020 Merge branch 'master' of https://git.haveno.com/haveno/haveno 2025-06-09 15:51:22 +07:00
01db30156a remove bot 2025-06-09 15:45:05 +07:00
f3c4d987dc WIP: old changes I want to merge forward 2025-06-09 15:43:21 +07:00
woodser
ee49324fbb
fix divide by zero error opening trade summary with no history 2025-06-08 10:14:27 -04:00
6a2672893c Merge branch 'master' of https://git.haveno.com/haveno/haveno 2025-01-25 23:47:01 +00:00
86d557c669 trying seednodes in file 2024-12-12 18:57:26 +00:00
36667f0b09 trying seednodes in file 2024-12-12 13:09:05 +00:00
a2f537ebf4 removed root bundle extraction 2024-12-11 19:10:02 +00:00
8e1c629abd protocol ready 2024-11-29 07:24:24 +00:00
40 changed files with 851 additions and 287 deletions

1
.gitignore vendored
View file

@ -39,3 +39,4 @@ deploy
*/.factorypath
.flatpak-builder
exchange.haveno.Haveno.yaml
hs_ed25519_secret_key

View file

@ -595,3 +595,15 @@ user3-desktop-mainnet:
--apiPort=1204 \
--useNativeXmrWallet=false \
--ignoreLocalXmrNode=false \
parner1-bot-stagenet:
./haveno-bot$(APP_EXT) \
--baseCurrencyNetwork=XMR_STAGENET \
--useLocalhostForP2P=false \
--useDevPrivilegeKeys=false \
--nodePort=9999 \
--appName=haveno-XMR_STAGENET_user3 \
--apiPassword=apitest \
--apiPort=1204 \
--useNativeXmrWallet=false \
--ignoreLocalXmrNode=false \

View file

@ -1,83 +1 @@
<div align="center">
<img src="https://raw.githubusercontent.com/haveno-dex/haveno-meta/721e52919b28b44d12b6e1e5dac57265f1c05cda/logo/haveno_logo_landscape.svg" alt="Haveno logo">
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/haveno-dex/haveno/build.yml?branch=master)
[![GitHub issues with bounty](https://img.shields.io/github/issues-search/haveno-dex/haveno?color=%23fef2c0&label=Issues%20with%20bounties&query=is%3Aopen+is%3Aissue+label%3A%F0%9F%92%B0bounty)](https://github.com/haveno-dex/haveno/issues?q=is%3Aopen+is%3Aissue+label%3A%F0%9F%92%B0bounty)
[![Twitter Follow](https://img.shields.io/twitter/follow/HavenoDEX?style=social)](https://twitter.com/havenodex)
[![Matrix rooms](https://img.shields.io/badge/Matrix%20room-%23haveno-blue)](https://matrix.to/#/#haveno:monero.social) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/haveno-dex/.github/blob/master/CODE_OF_CONDUCT.md)
</div>
## What is Haveno?
Haveno (pronounced ha‧ve‧no) is an open source platform to exchange [Monero](https://getmonero.org) for fiat currencies like USD, EUR, and GBP or other cryptocurrencies like BTC, ETH, and BCH.
Main features:
- Communications are routed through **Tor**, to preserve your privacy.
- Trades are **peer-to-peer**: trades on Haveno happen between people only, there is no central authority.
- Trades are **non-custodial**: Haveno supports arbitration in case something goes wrong during the trade, but arbitrators never have access to your funds.
- There is **No token**, because it's not needed. Transactions between traders are secured by non-custodial multisignature transactions on the Monero network.
See the [FAQ on our website](https://haveno.exchange/faq/) for more information.
## Haveno Demo
https://github.com/user-attachments/assets/eb6b3af0-78ce-46a7-bfa1-2aacd8649d47
## Installing Haveno
Haveno can be installed on Linux, macOS, and Windows by using a third party installer and network.
> [!note]
> The official Haveno repository does not support making real trades directly.
>
> To make real trades with Haveno, first find a third party network, and then use their installer or build their repository. We do not endorse any networks at this time.
A test network is also available for users to make test trades using Monero's stagenet. See the [instructions](https://github.com/haveno-dex/haveno/blob/master/docs/installing.md) to build Haveno and connect to the test network.
Alternatively, you can [create your own mainnet network](https://github.com/haveno-dex/haveno/blob/master/docs/create-mainnet.md).
Note that Haveno is being actively developed. If you find issues or bugs, please let us know.
## Main repositories
- **[haveno](https://github.com/haveno-dex/haveno)** - This repository. The core of Haveno.
- **[haveno-ts](https://github.com/haveno-dex/haveno-ts)** - TypeScript library for using Haveno.
- **[haveno-ui](https://github.com/haveno-dex/haveno-ui)** - A new user interface (WIP).
- **[haveno-meta](https://github.com/haveno-dex/haveno-meta)** - For project-wide discussions and proposals.
If you wish to help, take a look at the repositories above and look for open issues. We run a bounty program to incentivize development. See [Bounties](#bounties).
## Keep in touch and help out!
Haveno is a community-driven project. For it to be successful it's fundamental to have the support and help of the community. Join the community rooms on our Matrix server:
- General discussions: **Haveno** ([#haveno:monero.social](https://matrix.to/#/#haveno:monero.social)) relayed on IRC/Libera (`#haveno`)
- Development discussions: **Haveno Development** ([#haveno-development:monero.social](https://matrix.to/#/#haveno-development:monero.social)) relayed on IRC/Libera (`#haveno-development`)
Email: contact@haveno.exchange
Website: [haveno.exchange](https://haveno.exchange)
## Contributing to Haveno
See the [developer guide](docs/developer-guide.md) to get started developing for Haveno.
See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) for our styling guides.
If you are not able to contribute code and want to contribute development resources, [donations](#support-and-sponsorships) fund development bounties.
## Bounties
To incentivize development and reward contributors, we adopt a simple bounty system. Contributors may be awarded bounties after completing a task (resolving an issue). Take a look at the [issues labeled '💰bounty'](https://github.com/haveno-dex/haveno/issues?q=is%3Aopen+is%3Aissue+label%3A%F0%9F%92%B0bounty) in the main `haveno` repository. [Details and conditions for receiving a bounty](docs/bounties.md).
## Support
To bring Haveno to life, we need resources. If you have the possibility, please consider donating to the project:
<p align="center">
<img src="https://raw.githubusercontent.com/haveno-dex/haveno/master/media/donate_monero.png" alt="Donate Monero" width="115" height="115"><br>
<code>47fo8N5m2VVW4uojadGQVJ34LFR9yXwDrZDRugjvVSjcTWV2WFSoc1XfNpHmxwmVtfNY9wMBch6259G6BXXFmhU49YG1zfB</code>
</p>
The original Haveno core fork from haveno-dex/haveno adapted for the multiplatform app.

View file

@ -0,0 +1,47 @@
/*
* 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 haveno.bot.app;
import com.google.inject.Injector;
import haveno.core.app.misc.AppSetup;
import haveno.core.app.misc.AppSetupWithP2P;
import haveno.core.network.p2p.inventory.GetInventoryRequestHandler;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class HavenoBot {
@Setter
private Injector injector;
private AppSetup appSetup;
private GetInventoryRequestHandler getInventoryRequestHandler;
public HavenoBot() {
}
public void startApplication() {
appSetup = injector.getInstance(AppSetupWithP2P.class);
appSetup.start();
getInventoryRequestHandler = injector.getInstance(GetInventoryRequestHandler.class);
}
public void shutDown() {
getInventoryRequestHandler.shutDown();
}
}

View file

@ -0,0 +1,187 @@
/*
* 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 haveno.bot.app;
import haveno.common.UserThread;
import haveno.common.app.AppModule;
import haveno.common.handlers.ResultHandler;
import lombok.extern.slf4j.Slf4j;
import haveno.common.Timer;
import haveno.common.config.BaseCurrencyNetwork;
import haveno.common.config.Config;
import haveno.core.app.TorSetup;
import haveno.core.app.misc.ExecutableForAppWithP2p;
import haveno.core.app.misc.ModuleForAppWithP2p;
import haveno.core.user.Cookie;
import haveno.core.user.CookieKey;
import haveno.core.user.User;
import haveno.network.p2p.P2PService;
import haveno.network.p2p.P2PServiceListener;
import haveno.network.p2p.peers.PeerManager;
@Slf4j
public class HavenoBotMain extends ExecutableForAppWithP2p {
private static final long CHECK_CONNECTION_LOSS_SEC = 30;
private static final String VERSION = "1.1.2";
private HavenoBot bot;
private Timer checkConnectionLossTime;
public HavenoBotMain() {
super("Haveno Bot", "haveno-bot", "haveno_bot", VERSION);
}
public static void main(String[] args) {
System.out.println("HavenoBot.VERSION: " + VERSION);
new HavenoBotMain().execute(args);
}
@Override
protected int doExecute() {
super.doExecute();
checkMemory(config, this);
return keepRunning();
}
@Override
protected void addCapabilities() {
}
@Override
protected void launchApplication() {
UserThread.execute(() -> {
try {
bot = new HavenoBot();
UserThread.execute(this::onApplicationLaunched);
} catch (Exception e) {
log.error("Error launching haveno bot: {}\n", e.toString(), e);
}
});
}
@Override
protected void onApplicationLaunched() {
super.onApplicationLaunched();
}
///////////////////////////////////////////////////////////////////////////////////////////
// We continue with a series of synchronous execution tasks
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected AppModule getModule() {
return new ModuleForAppWithP2p(config);
}
@Override
protected void applyInjector() {
super.applyInjector();
bot.setInjector(injector);
}
@Override
protected void startApplication() {
Cookie cookie = injector.getInstance(User.class).getCookie();
cookie.getAsOptionalBoolean(CookieKey.CLEAN_TOR_DIR_AT_RESTART).ifPresent(wasCleanTorDirSet -> {
if (wasCleanTorDirSet) {
injector.getInstance(TorSetup.class).cleanupTorFiles(() -> {
log.info("Tor directory reset");
cookie.remove(CookieKey.CLEAN_TOR_DIR_AT_RESTART);
}, log::error);
}
});
bot.startApplication();
injector.getInstance(P2PService.class).addP2PServiceListener(new P2PServiceListener() {
@Override
public void onDataReceived() {
// Do nothing
}
@Override
public void onNoSeedNodeAvailable() {
// Do nothing
}
@Override
public void onNoPeersAvailable() {
// Do nothing
}
@Override
public void onUpdatedDataReceived() {
// Do nothing
}
@Override
public void onTorNodeReady() {
// Do nothing
}
@Override
public void onHiddenServicePublished() {
UserThread.runAfter(() -> setupConnectionLossCheck(), 60);
}
@Override
public void onSetupFailed(Throwable throwable) {
// Do nothing
}
@Override
public void onRequestCustomBridges() {
// Do nothing
}
});
}
private void setupConnectionLossCheck() {
// For dev testing (usually on XMR_LOCAL) we don't want to get the seed shut
// down as it is normal that the seed is the only actively running node.
if (Config.baseCurrencyNetwork() != BaseCurrencyNetwork.XMR_MAINNET) {
return;
}
if (checkConnectionLossTime != null) {
return;
}
checkConnectionLossTime = UserThread.runPeriodically(() -> {
if (injector.getInstance(PeerManager.class).getNumAllConnectionsLostEvents() > 1) {
// We set a flag to clear tor cache files at re-start. We cannot clear it now as Tor is used and
// that can cause problems.
injector.getInstance(User.class).getCookie().putAsBoolean(CookieKey.CLEAN_TOR_DIR_AT_RESTART, true);
shutDown(this);
}
}, CHECK_CONNECTION_LOSS_SEC);
}
@Override
public void gracefulShutDown(ResultHandler resultHandler) {
bot.shutDown();
super.gracefulShutDown(resultHandler);
}
}

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<conversionRule conversionWord="hl2" converterClass="haveno.common.app.LogHighlighter" />
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%hl2(%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{40}: %msg %xEx%n)</pattern>
</encoder>
</appender>
<root level="TRACE">
<appender-ref ref="CONSOLE_APPENDER"/>
</root>
<logger name="io.grpc.netty" level="WARN"/>
<logger name="org.apache" level="WARN" />
</configuration>

View file

@ -132,7 +132,9 @@ configure([project(':cli'),
project(':seednode'),
project(':statsnode'),
project(':inventory'),
project(':apitest')]) {
project(':apitest'),
//project(':bot')
]) {
apply plugin: 'application'
@ -452,123 +454,6 @@ configure(project(':core')) {
mainClass = 'haveno.core.util.GenerateKeyPairs'
classpath = sourceSets.main.runtimeClasspath
}
task havenoDeps {
doLast {
// get monero binaries download url
Map moneroBinaries = [
'linux-x86_64' : 'https://github.com/haveno-dex/monero/releases/download/release6/monero-bins-haveno-linux-x86_64.tar.gz',
'linux-x86_64-sha256' : '44470a3cf2dd9be7f3371a8cc89a34cf9a7e88c442739d87ef9a0ec3ccb65208',
'linux-aarch64' : 'https://github.com/haveno-dex/monero/releases/download/release6/monero-bins-haveno-linux-aarch64.tar.gz',
'linux-aarch64-sha256' : 'c9505524689b0d7a020b8d2fd449c3cb9f8fd546747f9bdcf36cac795179f71c',
'mac' : 'https://github.com/haveno-dex/monero/releases/download/release6/monero-bins-haveno-mac.tar.gz',
'mac-sha256' : 'dea6eddefa09630cfff7504609bd5d7981316336c64e5458e242440694187df8',
'windows' : 'https://github.com/haveno-dex/monero/releases/download/release6/monero-bins-haveno-windows.zip',
'windows-sha256' : '284820e28c4770d7065fad7863e66fe0058053ca2372b78345d83c222edc572d'
]
String osKey
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
osKey = 'windows'
} else if (Os.isFamily(Os.FAMILY_MAC)) {
osKey = 'mac'
} else {
String architecture = System.getProperty("os.arch").toLowerCase()
if (architecture.contains('aarch64') || architecture.contains('arm')) {
osKey = 'linux-aarch64'
} else {
osKey = 'linux-x86_64'
}
}
String moneroDownloadUrl = moneroBinaries[osKey]
String moneroSHA256Hash = moneroBinaries[osKey + '-sha256']
String moneroArchiveFileName = moneroDownloadUrl.tokenize('/').last()
String localnetDirName = '.localnet'
File localnetDir = new File(project.rootDir, localnetDirName)
localnetDir.mkdirs()
File moneroArchiveFile = new File(localnetDir, moneroArchiveFileName)
ext.downloadAndVerifyDependencies(moneroDownloadUrl, moneroSHA256Hash, moneroArchiveFile)
// extract if dependencies are missing or if archive was updated
File monerodFile
File moneroRpcFile
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
monerodFile = new File(localnetDir, 'monerod.exe')
moneroRpcFile = new File(localnetDir, 'monero-wallet-rpc.exe')
} else {
monerodFile = new File(localnetDir, 'monerod')
moneroRpcFile = new File(localnetDir, 'monero-wallet-rpc')
}
if (ext.dependencyDownloadedAndVerified || !monerodFile.exists() || !moneroRpcFile.exists()) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
ext.extractArchiveZip(moneroArchiveFile, localnetDir)
} else {
ext.extractArchiveTarGz(moneroArchiveFile, localnetDir)
}
}
// add the current platform's monero dependencies into the resources folder for installation
copy {
from "${monerodFile}"
into "${project(':core').projectDir}/src/main/resources/bin"
}
copy {
from "${moneroRpcFile}"
into "${project(':core').projectDir}/src/main/resources/bin"
}
}
ext.extractArchiveTarGz = { File tarGzFile, File destinationDir ->
println "Extracting tar.gz ${tarGzFile}"
// Gradle's tar extraction preserves permissions (crucial for jpackage to function correctly)
copy {
from tarTree(resources.gzip(tarGzFile))
into destinationDir
}
println "Extracted to ${destinationDir}"
}
ext.extractArchiveZip = { File zipFile, File destinationDir ->
println "Extracting zip ${zipFile}..."
ant.unzip(src: zipFile, dest: destinationDir)
println "Extracted to ${destinationDir}"
}
ext.downloadAndVerifyDependencies = { String archiveURL, String archiveSHA256, File destinationArchiveFile ->
ext.dependencyDownloadedAndVerified = false
// if archive exists, check to see if its already up to date
if (destinationArchiveFile.exists()) {
println "Verifying existing archive ${destinationArchiveFile}"
ant.archiveHash = archiveSHA256
ant.checksum(file: destinationArchiveFile, algorithm: 'SHA-256', property: '${archiveHash}', verifyProperty: 'existingHashMatches')
if (ant.properties['existingHashMatches'] != 'true') {
println "Existing archive does not match hash ${archiveSHA256}"
} else {
println "Existing archive matches hash"
return
}
}
// download archives
println "Downloading ${archiveURL}"
ant.get(src: archiveURL, dest: destinationArchiveFile)
println 'Download saved to ' + destinationArchiveFile
// verify checksum
println 'Verifying checksum for downloaded binary ...'
ant.archiveHash = archiveSHA256
ant.checksum(file: destinationArchiveFile, algorithm: 'SHA-256', property: '${archiveHash}', verifyProperty: 'downloadedHashMatches') // use a different verifyProperty name from existing verification or it will always fail
if (ant.properties['downloadedHashMatches'] != 'true') {
ant.fail('Checksum mismatch: Downloaded archive has a different checksum than expected')
}
println 'Checksum verified'
ext.dependencyDownloadedAndVerified = true
}
}
processResources.dependsOn havenoDeps // before both test and build
}
configure(project(':cli')) {
@ -787,7 +672,12 @@ configure(project(':statsnode')) {
}
configure(project(':daemon')) {
mainClassName = 'haveno.daemon.app.HavenoDaemonMain'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'application'
application {
mainClass = 'haveno.daemon.app.HavenoDaemonMain'
}
dependencies {
implementation project(':proto')
@ -847,6 +737,72 @@ configure(project(':daemon')) {
}
}
//configure(project(':bot')) {
// apply plugin: 'com.github.johnrengelman.shadow'
// apply plugin: 'application'
//
// application {
// mainClass = 'haveno.bot.app.HavenoBotMain'
// }
//
// dependencies {
// implementation project(':proto')
// implementation project(':common')
// implementation project(':p2p')
// implementation project(':core')
// annotationProcessor "org.projectlombok:lombok:$lombokVersion"
// compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
// compileOnly "org.projectlombok:lombok:$lombokVersion"
// implementation "ch.qos.logback:logback-classic:$logbackVersion"
// implementation "ch.qos.logback:logback-core:$logbackVersion"
// implementation "com.google.code.gson:gson:$gsonVersion"
// implementation "com.google.guava:guava:$guavaVersion"
// implementation "com.google.protobuf:protobuf-java:$protobufVersion"
// implementation "org.apache.commons:commons-lang3:$langVersion"
// implementation "org.jetbrains:annotations:$jetbrainsAnnotationsVersion"
// implementation "org.slf4j:slf4j-api:$slf4jVersion"
// implementation("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
// exclude(module: 'bcprov-jdk15on')
// exclude(module: 'guava')
// exclude(module: 'jsr305')
// exclude(module: 'okhttp')
// exclude(module: 'okio')
// exclude(module: 'protobuf-java')
// exclude(module: 'slf4j-api')
// }
// implementation("com.google.inject:guice:$guiceVersion") {
// exclude(module: 'guava')
// }
// implementation("io.grpc:grpc-protobuf:$grpcVersion") {
// exclude(module: 'animal-sniffer-annotations')
// exclude(module: 'guava')
// }
// implementation("io.grpc:grpc-stub:$grpcVersion") {
// exclude(module: 'animal-sniffer-annotations')
// exclude(module: 'guava')
// }
// runtimeOnly("io.grpc:grpc-netty-shaded:$grpcVersion") {
// exclude(module: 'animal-sniffer-annotations')
// exclude(module: 'guava')
// }
// testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
// testCompileOnly "org.projectlombok:lombok:$lombokVersion"
// testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
// testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
// testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
//
// implementation("io.github.woodser:monero-java:$moneroJavaVersion") {
// exclude(module: 'jackson-core')
// exclude(module: 'jackson-annotations')
// exclude(module: 'jackson-databind')
// exclude(module: 'bcprov-jdk15on')
// exclude(group: 'org.slf4j', module: 'slf4j-simple')
// }
// implementation "org.openjfx:javafx-base:$javafxVersion:$os"
// implementation "org.openjfx:javafx-graphics:$javafxVersion:$os"
// }
//}
configure(project(':inventory')) {
apply plugin: 'com.github.johnrengelman.shadow'

View file

@ -99,7 +99,7 @@ public class Version {
// The version no. for the objects sent over the network. A change will break the serialization of old objects.
// If objects are used for both network and database the network version is applied.
public static final String P2P_NETWORK_VERSION = "A";
public static final String P2P_NETWORK_VERSION = System.getenv().getOrDefault("P2P_NETWORK_VERSION", "X");
// The version no. of the serialized data stored to disc. A change will break the serialization of old objects.
// VERSION = 0.5.0 -> LOCAL_DB_VERSION = 1

View file

@ -97,25 +97,13 @@ public class AlertManager {
}
protected List<String> getPubKeyList() {
if (useDevPrivilegeKeys) return List.of(DevEnv.DEV_PRIVILEGE_PUB_KEY);
switch (Config.baseCurrencyNetwork()) {
case XMR_LOCAL:
return List.of(
"027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee",
"024baabdba90e7cc0dc4626ef73ea9d722ea7085d1104491da8c76f28187513492");
case XMR_STAGENET:
return List.of(
"036d8a1dfcb406886037d2381da006358722823e1940acc2598c844bbc0fd1026f",
"026c581ad773d987e6bd10785ac7f7e0e64864aedeb8bce5af37046de812a37854",
"025b058c9f2c60d839669dbfa5578cf5a8117d60e6b70e2f0946f8a691273c6a36");
case XMR_MAINNET:
return List.of();
default:
throw new RuntimeException("Unhandled base currency network: " + Config.baseCurrencyNetwork());
}
return List.of(
"0326b14f3a55d02575dceed5202b8b125f458cbe0fdceeee294b443bf1a8d8cf78",
"03d62d14438adbe7aea688ade1f73933c6f0a705f238c02c5b54b83dd1e4fca225",
"023c8fdea9ff2d03daef54337907e70a7b0e20084a75fcc3ad2f0c28d8b691dea1"
);
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -96,22 +96,11 @@ public class PrivateNotificationManager implements MessageListener {
}
protected List<String> getPubKeyList() {
if (useDevPrivilegeKeys) return List.of(DevEnv.DEV_PRIVILEGE_PUB_KEY);
switch (Config.baseCurrencyNetwork()) {
case XMR_LOCAL:
return List.of(
"027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee",
"024baabdba90e7cc0dc4626ef73ea9d722ea7085d1104491da8c76f28187513492");
case XMR_STAGENET:
return List.of(
"02ba7c5de295adfe57b60029f3637a2c6b1d0e969a8aaefb9e0ddc3a7963f26925",
"026c581ad773d987e6bd10785ac7f7e0e64864aedeb8bce5af37046de812a37854",
"025b058c9f2c60d839669dbfa5578cf5a8117d60e6b70e2f0946f8a691273c6a36");
case XMR_MAINNET:
return List.of();
default:
throw new RuntimeException("Unhandled base currency network: " + Config.baseCurrencyNetwork());
}
return List.of(
"0326b14f3a55d02575dceed5202b8b125f458cbe0fdceeee294b443bf1a8d8cf78",
"03d62d14438adbe7aea688ade1f73933c6f0a705f238c02c5b54b83dd1e4fca225",
"023c8fdea9ff2d03daef54337907e70a7b0e20084a75fcc3ad2f0c28d8b691dea1"
);
}
private void handleMessage(DecryptedMessageWithPubKey decryptedMessageWithPubKey, NodeAddress senderNodeAddress) {

View file

@ -114,11 +114,11 @@ public class FilterManager {
this.providersRepository = providersRepository;
this.ignoreDevMsg = ignoreDevMsg;
publicKeys = useDevPrivilegeKeys ?
Collections.singletonList(DevEnv.DEV_PRIVILEGE_PUB_KEY) :
List.of("0358d47858acdc41910325fce266571540681ef83a0d6fedce312bef9810793a27",
"029340c3e7d4bb0f9e651b5f590b434fecb6175aeaa57145c7804ff05d210e534f",
"034dc7530bf66ffd9580aa98031ea9a18ac2d269f7c56c0e71eca06105b9ed69f9");
publicKeys = List.of(
"0326b14f3a55d02575dceed5202b8b125f458cbe0fdceeee294b443bf1a8d8cf78",
"03d62d14438adbe7aea688ade1f73933c6f0a705f238c02c5b54b83dd1e4fca225",
"023c8fdea9ff2d03daef54337907e70a7b0e20084a75fcc3ad2f0c28d8b691dea1"
);
banFilter.setBannedNodePredicate(this::isNodeAddressBannedFromNetwork);
}

View file

@ -406,6 +406,13 @@ public class CurrencyUtil {
removedCryptoCurrency.isPresent() ? removedCryptoCurrency.get().getName() : Res.get("shared.na");
return getCryptoCurrency(currencyCode).map(TradeCurrency::getName).orElse(xmrOrRemovedAsset);
}
if (isTraditionalNonFiatCurrency(currencyCode)) {
return getTraditionalNonFiatCurrencies().stream()
.filter(currency -> currency.getCode().equals(currencyCode))
.findAny()
.map(TradeCurrency::getName)
.orElse(currencyCode);
}
try {
return Currency.getInstance(currencyCode).getDisplayName();
} catch (Throwable t) {

View file

@ -59,29 +59,11 @@ public class ArbitratorManager extends DisputeAgentManager<Arbitrator> {
@Override
protected List<String> getPubKeyList() {
switch (Config.baseCurrencyNetwork()) {
case XMR_LOCAL:
return List.of(
"027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee",
"024baabdba90e7cc0dc4626ef73ea9d722ea7085d1104491da8c76f28187513492",
"026eeec3c119dd6d537249d74e5752a642dd2c3cc5b6a9b44588eb58344f29b519");
case XMR_STAGENET:
return List.of(
"03bb559ce207a4deb51d4c705076c95b85ad8581d35936b2a422dcb504eaf7cdb0",
"026c581ad773d987e6bd10785ac7f7e0e64864aedeb8bce5af37046de812a37854",
"025b058c9f2c60d839669dbfa5578cf5a8117d60e6b70e2f0946f8a691273c6a36",
"036c7d3f4bf05ef39b9d1b0a5d453a18210de36220c3d83cd16e59bd6132b037ad",
"030f7122a10ff73cd73808bddace95be77a94189c8a0eb24586265e125ce5ce6b9",
"03aa23e062afa0dda465f46986f8aa8d0374ad3e3f256141b05681dcb1e39c3859",
"02d3beb1293ca2ca14e6d42ca8bd18089a62aac62fd6bb23923ee6ead46ac60fba",
"03fa0f38f27bdd324db6f933f7e57851dadf3b911e4db6b19dd0950492c4525a31",
"02a1a458df5acf4ab08fdca748e28f33a955a30854c8c1a831ee733dca7f0d2fcd",
"0374dd70f3fa6e47ec5ab97932e1cec6233e98e6ae3129036b17118650c44fd3de");
case XMR_MAINNET:
return List.of();
default:
throw new RuntimeException("Unhandled base currency network: " + Config.baseCurrencyNetwork());
}
return List.of(
"0326b14f3a55d02575dceed5202b8b125f458cbe0fdceeee294b443bf1a8d8cf78",
"03d62d14438adbe7aea688ade1f73933c6f0a705f238c02c5b54b83dd1e4fca225",
"023c8fdea9ff2d03daef54337907e70a7b0e20084a75fcc3ad2f0c28d8b691dea1"
);
}
@Override

View file

@ -76,7 +76,7 @@ public class ClosedTradableFormatter {
}
public String getTotalTxFeeAsString(BigInteger totalTradeAmount, BigInteger totalTxFee) {
double percentage = HavenoUtils.divide(totalTxFee, totalTradeAmount);
double percentage = totalTradeAmount.equals(BigInteger.ZERO) ? 0 : HavenoUtils.divide(totalTxFee, totalTradeAmount);
return Res.get(I18N_KEY_TOTAL_TX_FEE,
HavenoUtils.formatXmr(totalTxFee, true),
formatToPercentWithSymbol(percentage));
@ -104,7 +104,7 @@ public class ClosedTradableFormatter {
}
public String getTotalTradeFeeAsString(BigInteger totalTradeAmount, BigInteger totalTradeFee) {
double percentage = HavenoUtils.divide(totalTradeFee, totalTradeAmount);
double percentage = totalTradeAmount.equals(BigInteger.ZERO) ? 0 : HavenoUtils.divide(totalTradeFee, totalTradeAmount);
return Res.get(I18N_KEY_TOTAL_TRADE_FEE_BTC,
HavenoUtils.formatXmr(totalTradeFee, true),
formatToPercentWithSymbol(percentage));

View file

@ -85,13 +85,13 @@ import org.bitcoinj.core.Coin;
public class HavenoUtils {
// configure release date
private static final String RELEASE_DATE = "25-05-2024 00:00:00"; // optionally set to release date of the network in format dd-mm-yyyy to impose temporary limits, etc. e.g. "25-05-2024 00:00:00"
private static final String RELEASE_DATE = "18-06-2025 00:00:00"; // optionally set to release date of the network in format dd-mm-yyyy to impose temporary limits, etc. e.g. "25-05-2024 00:00:00"
public static final int RELEASE_LIMIT_DAYS = 60; // number of days to limit sell offers to max buy limit for new accounts
public static final int WARN_ON_OFFER_EXCEEDS_UNSIGNED_BUY_LIMIT_DAYS = 182; // number of days to warn if sell offer exceeds unsigned buy limit
public static final int ARBITRATOR_ACK_TIMEOUT_SECONDS = 60;
// configure fees
public static final boolean ARBITRATOR_ASSIGNS_TRADE_FEE_ADDRESS = true;
public static final boolean ARBITRATOR_ASSIGNS_TRADE_FEE_ADDRESS = false;
public static final double PENALTY_FEE_PCT = 0.02; // 2%
public static final double MAKER_FEE_PCT = 0.0015; // 0.15%
public static final double TAKER_FEE_PCT = 0.0075; // 0.75%
@ -476,9 +476,9 @@ public class HavenoUtils {
case XMR_STAGENET:
return "5B11hTJdG2XDNwjdKGLRxwSLwDhkbGg7C7UEAZBxjE6FbCeRMjudrpNACmDNtWPiSnNfjDQf39QRjdtdgoL69txv81qc2Mc";
case XMR_MAINNET:
throw new RuntimeException("Mainnet fee address not implemented");
return "8BTqDom6yukimzKTaLX7d4EgxznKUqTLjebpvUySkWGcg9irMqUwiHKccCTZ8dMu7CG3Ac89H7kqifpCwjCeWd2GUhhxy1F";
default:
throw new RuntimeException("Unhandled base currency network: " + Config.baseCurrencyNetwork());
return "8BTqDom6yukimzKTaLX7d4EgxznKUqTLjebpvUySkWGcg9irMqUwiHKccCTZ8dMu7CG3Ac89H7kqifpCwjCeWd2GUhhxy1F";
}
}

View file

@ -111,7 +111,7 @@ public class XmrWalletService extends XmrWalletBase {
public static final String MONERO_WALLET_RPC_NAME = Utilities.isWindows() ? "monero-wallet-rpc.exe" : "monero-wallet-rpc";
public static final String MONERO_WALLET_RPC_PATH = MONERO_BINS_DIR + File.separator + MONERO_WALLET_RPC_NAME;
public static final MoneroTxPriority PROTOCOL_FEE_PRIORITY = MoneroTxPriority.DEFAULT;
public static final int MONERO_LOG_LEVEL = -1; // monero library log level, -1 to disable
public static final int MONERO_LOG_LEVEL = 1; // monero library log level, -1 to disable
private static final MoneroNetworkType MONERO_NETWORK_TYPE = getMoneroNetworkType();
private static final MoneroWalletRpcManager MONERO_WALLET_RPC_MANAGER = new MoneroWalletRpcManager();
private static final String MONERO_WALLET_RPC_USERNAME = "haveno_user";
@ -120,8 +120,8 @@ public class XmrWalletService extends XmrWalletBase {
private static final String KEYS_FILE_POSTFIX = ".keys";
private static final String ADDRESS_FILE_POSTFIX = ".address.txt";
private static final int NUM_MAX_WALLET_BACKUPS = 2;
private static final int MAX_SYNC_ATTEMPTS = 3;
private static final boolean PRINT_RPC_STACK_TRACE = false;
private static final int MAX_SYNC_ATTEMPTS = 5;
private static final boolean PRINT_RPC_STACK_TRACE = true;
private static final String THREAD_ID = XmrWalletService.class.getSimpleName();
private static final long SHUTDOWN_TIMEOUT_MS = 60000;
private static final long NUM_BLOCKS_BEHIND_TOLERANCE = 5;

View file

@ -93,7 +93,7 @@ grant {
/* user data dir for Mac, Linux, Windows */
permission "java.io.FilePermission" "${user.home}${/}Library${/}Application Support${/}-", "read,write,delete";
permission "java.io.FilePermission" "${user.home}${/}.local${/}share${/}haveno-", "read,write,delete";
permission "java.io.FilePermission" "${user.home}${/}.local${/}share${/}-", "read,write,delete";
permission "java.io.FilePermission" "${appdata}${/}haveno-", "read,write,delete";
/* temp dir Mac, Linux, Windows TODO */

View file

@ -1,2 +1,4 @@
# nodeaddress.onion:port [(@owner,@backup)]
placeholder.onion:8000 (@placeholder)
# nodeaddress.onion:port [(@owner,@backup)]
5i6blbmuflq4s4im6zby26a7g22oef6kyp7vbwyru6oq5e36akzo3ayd.onion:2001 (@op1)
dx4ktxyiemjc354imehuaswbhqlidhy62b4ifzigk5p2rb37lxqbveqd.onion:2002 (@op2)
ajbqx4clnjlr7lmzoftuvpvmqafdiilidsgocvokx6bqj3okk56ccfqd.onion:2003 (@op3)

View file

@ -1,3 +1 @@
# nodeaddress.onion:port [(@owner)]
dl57jitswby4yhzpqpu7pwq6iyqg2x6vkio73araparbftlqoqxhvqad.onion:2002 (@devtest1)
3cqlkowdu766sto5wrdqpntpsi7kezwkkakc532i6jeiyu7hha726ead.onion:3003 (@devtest1)
# nodeaddress.onion:port [(@owner)]

View file

@ -216,7 +216,7 @@ public class HavenoAppMain extends HavenoExecutable {
// Set the dialog content
VBox vbox = new VBox(10);
ImageView logoImageView = new ImageView(ImageUtil.getImageByPath("logo_splash_light.png"));
ImageView logoImageView = new ImageView(ImageUtil.getImageByPath("logo_splash_light_mode.png"));
logoImageView.setFitWidth(342);
logoImageView.setPreserveRatio(true);
vbox.getChildren().addAll(logoImageView, passwordField, errorMessageField, versionField);

View file

@ -2283,6 +2283,7 @@ textfield */
-fx-background-insets: 44;
-fx-background-radius: 15;
-fx-border-radius: 15;
-fx-effect: dropshadow(gaussian, -bs-text-color-dropshadow-light-mode, 44, 0, 0, 0);
}
.notification-popup-bg, .peer-info-popup-bg {

View file

@ -305,8 +305,12 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
}
});
// add spacer to center the nav buttons when window is small
Region rightSpacer = new Region();
HBox.setHgrow(rightSpacer, Priority.ALWAYS);
HBox primaryNav = new HBox(getLogoPane(), marketButton, getNavigationSpacer(), buyButton, getNavigationSpacer(),
sellButton, getNavigationSpacer(), portfolioButtonWithBadge, getNavigationSpacer(), fundsButton);
sellButton, getNavigationSpacer(), portfolioButtonWithBadge, getNavigationSpacer(), fundsButton, rightSpacer);
primaryNav.setAlignment(Pos.CENTER_LEFT);
primaryNav.getStyleClass().add("nav-primary");

View file

@ -578,15 +578,15 @@
}
#image-logo-splash {
-fx-image: url("../../images/logo_splash_dark.png");
-fx-image: url("../../images/logo_splash_dark_mode.png");
}
#image-logo-splash-testnet {
-fx-image: url("../../images/logo_splash_testnet_dark.png");
-fx-image: url("../../images/logo_splash_testnet_dark_mode.png");
}
#image-logo-landscape {
-fx-image: url("../../images/logo_landscape_dark.png");
-fx-image: url("../../images/logo_landscape_dark_mode.png");
}
.table-view .placeholder {

View file

@ -144,15 +144,15 @@
}
#image-logo-splash {
-fx-image: url("../../images/logo_splash_light.png");
-fx-image: url("../../images/logo_splash_light_mode.png");
}
#image-logo-splash-testnet {
-fx-image: url("../../images/logo_splash_testnet_light.png");
-fx-image: url("../../images/logo_splash_testnet_light_mode.png");
}
#image-logo-landscape {
-fx-image: url("../../images/logo_landscape_light.png");
-fx-image: url("../../images/logo_landscape_light_mode.png");
}
#charts .default-color0.chart-series-area-fill {

View file

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View file

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View file

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

32
docker/Dockerfile.core Normal file
View file

@ -0,0 +1,32 @@
FROM openjdk:21-jdk-bullseye
RUN set -ex && \
apt update && \
apt --no-install-recommends --yes install \
make \
git \
tor
RUN set -ex && adduser --system --group --disabled-password haveno && \
mkdir -p /home/haveno && \
chown -R haveno:haveno /home/haveno
USER haveno
WORKDIR /home/haveno
RUN set -ex && git clone https://foss.haveno.com/haveno-network/haveno-core.git
WORKDIR /home/haveno/haveno-core
RUN git checkout master && \
git reset --hard
RUN make clean && make skip-tests
WORKDIR /home/haveno/haveno-core
ENTRYPOINT [ "./haveno-seednode" ]
## CMDs are conditional based on type
CMD ["--baseCurrencyNetwork=XMR_MAINNET", "--useLocalhostForP2P=false", "--useDevPrivilegeKeys=false", "--nodePort=2002"]

View file

@ -0,0 +1 @@
ajbqx4clnjlr7lmzoftuvpvmqafdiilidsgocvokx6bqj3okk56ccfqd.onion

3
docker/daemon/.env Normal file
View file

@ -0,0 +1,3 @@
NETWORK_VERSION_TAG=1.1.2
BASE_NETWORK=MAINNET
P2P_NETWORK_VERSION="X"

View file

@ -0,0 +1,28 @@
version: '3'
services:
haveno-daemon:
image: haveno-core
build:
context: ../
ports:
- "127.0.0.1:3201:3201"
environment:
- P2P_NETWORK_VERSION=X
- NETWORK_VERSION_TAG=${NETWORK_VERSION_TAG}
- BASE_CURRENCY_NETWORK=XMR_${BASE_NETWORK}
- USE_LOCALHOST_FOR_P2P=false
- USE_DEV_PRIVILEGE_KEYS=false
- NODE_PORT=9999
- APP_NAME=haveno-XMR_${BASE_NETWORK}_DAEMON
- EXPORT_SHADOW=yes
- EXPORT_SHADOW_PATH=daemon/build/libs/daemon-all.sh # Leave this blank in most cases
entrypoint: ["./haveno-daemon"]
command:
- "--baseCurrencyNetwork=XMR_${BASE_NETWORK}"
- "--useLocalhostForP2P=false"
- "--useDevPrivilegeKeys=false"
- "--nodePort=9999"
- "--appName=XMR_${BASE_NETWORK}_DAEMON"
- "--seedNodes=5i6blbmuflq4s4im6zby26a7g22oef6kyp7vbwyru6oq5e36akzo3ayd.onion:2001,dx4ktxyiemjc354imehuaswbhqlidhy62b4ifzigk5p2rb37lxqbveqd.onion:2002,ajbqx4clnjlr7lmzoftuvpvmqafdiilidsgocvokx6bqj3okk56ccfqd.onion:2003"
restart: unless-stopped

2
docker/seednode/.env Normal file
View file

@ -0,0 +1,2 @@
BASE_NETWORK=MAINNET
P2P_NETWORK_VERSION="X"

View file

@ -0,0 +1,79 @@
version: '3.8'
services:
haveno-core:
image: haveno-core
build:
context: ../
dockerfile: Dockerfile.core
# No ports, this one just builds the image
entrypoint: ["true"] # No need to run
haveno-seednode_2001:
image: haveno-core
depends_on:
- haveno-core
ports:
- "127.0.0.1:2001:2001"
environment:
- BASE_CURRENCY_NETWORK=XMR_${BASE_NETWORK}
- USE_LOCALHOST_FOR_P2P=false
- USE_DEV_PRIVILEGE_KEYS=false
- NODE_PORT=2001
- APP_NAME=haveno-XMR_${BASE_NETWORK}_Seed_2001
entrypoint: ["./haveno-seednode"]
command:
- "--baseCurrencyNetwork=XMR_${BASE_NETWORK}"
- "--useLocalhostForP2P=false"
- "--useDevPrivilegeKeys=false"
- "--nodePort=2001"
- "--appName=haveno-XMR_${BASE_NETWORK}_Seed_2001"
- "--hiddenServiceAddress=5i6blbmuflq4s4im6zby26a7g22oef6kyp7vbwyru6oq5e36akzo3ayd.onion"
- "--seedNodes=5i6blbmuflq4s4im6zby26a7g22oef6kyp7vbwyru6oq5e36akzo3ayd.onion:2001,dx4ktxyiemjc354imehuaswbhqlidhy62b4ifzigk5p2rb37lxqbveqd.onion:2002,ajbqx4clnjlr7lmzoftuvpvmqafdiilidsgocvokx6bqj3okk56ccfqd.onion:2003"
restart: unless-stopped
haveno-seednode_2002:
image: haveno-core
depends_on:
- haveno-core
ports:
- "127.0.0.1:2002:2002"
environment:
- BASE_CURRENCY_NETWORK=XMR_${BASE_NETWORK}
- USE_LOCALHOST_FOR_P2P=false
- USE_DEV_PRIVILEGE_KEYS=false
- NODE_PORT=2002
- APP_NAME=haveno-XMR_${BASE_NETWORK}_Seed_2002
entrypoint: ["./haveno-seednode"]
command:
- "--baseCurrencyNetwork=XMR_${BASE_NETWORK}"
- "--useLocalhostForP2P=false"
- "--useDevPrivilegeKeys=false"
- "--nodePort=2002"
- "--appName=haveno-XMR_${BASE_NETWORK}_Seed_2002"
- "--hiddenServiceAddress=dx4ktxyiemjc354imehuaswbhqlidhy62b4ifzigk5p2rb37lxqbveqd.onion"
- "--seedNodes=5i6blbmuflq4s4im6zby26a7g22oef6kyp7vbwyru6oq5e36akzo3ayd.onion:2001,dx4ktxyiemjc354imehuaswbhqlidhy62b4ifzigk5p2rb37lxqbveqd.onion:2002,ajbqx4clnjlr7lmzoftuvpvmqafdiilidsgocvokx6bqj3okk56ccfqd.onion:2003"
restart: unless-stopped
haveno-seednode_2003:
image: haveno-core
depends_on:
- haveno-core
ports:
- "127.0.0.1:2003:2003"
environment:
- BASE_CURRENCY_NETWORK=XMR_${BASE_NETWORK}
- USE_LOCALHOST_FOR_P2P=false
- USE_DEV_PRIVILEGE_KEYS=false
- NODE_PORT=2003
- APP_NAME=haveno-XMR_${BASE_NETWORK}_Seed_2003
entrypoint: ["./haveno-seednode"]
command:
- "--baseCurrencyNetwork=XMR_${BASE_NETWORK}"
- "--useLocalhostForP2P=false"
- "--useDevPrivilegeKeys=false"
- "--nodePort=2003"
- "--appName=haveno-XMR_${BASE_NETWORK}_Seed_2003"
- "--hiddenServiceAddress=ajbqx4clnjlr7lmzoftuvpvmqafdiilidsgocvokx6bqj3okk56ccfqd.onion"
- "--seedNodes=5i6blbmuflq4s4im6zby26a7g22oef6kyp7vbwyru6oq5e36akzo3ayd.onion:2001,dx4ktxyiemjc354imehuaswbhqlidhy62b4ifzigk5p2rb37lxqbveqd.onion:2002,ajbqx4clnjlr7lmzoftuvpvmqafdiilidsgocvokx6bqj3okk56ccfqd.onion:2003"
restart: unless-stopped

109
docker/torrc Normal file
View file

@ -0,0 +1,109 @@
## Configuration file for Haveno Seednode
##
## Tor opens a socks proxy on port 9050 by default -- even if you don't
## configure one below. Set "SocksPort 0" if you plan to run Tor only
## as a relay, and not make any local application connections yourself.
#SocksPort 9050 # Default: Bind to localhost:9050 for local connections.
# ### SocksPort flag: OnionTrafficOnly ###
## Tell the tor client to only connect to .onion addresses in response to SOCKS5 requests on this connection.
## This is equivalent to NoDNSRequest, NoIPv4Traffic, NoIPv6Traffic.
# ### SocksPort flag: ExtendedErrors ###
## Return extended error code in the SOCKS reply. So far, the possible errors are:
# X'F0' Onion Service Descriptor Can Not be Found
# X'F1' Onion Service Descriptor Is Invalid
# X'F2' Onion Service Introduction Failed
# X'F3' Onion Service Rendezvous Failed
# X'F4' Onion Service Missing Client Authorization
# X'F5' Onion Service Wrong Client Authorization
# X'F6' Onion Service Invalid Address
# X'F7' Onion Service Introduction Timed Out
SocksPort 9050 OnionTrafficOnly ExtendedErrors
## Entry policies to allow/deny SOCKS requests based on IP address.
## First entry that matches wins. If no SocksPolicy is set, we accept
## all (and only) requests that reach a SocksPort. Untrusted users who
## can access your SocksPort may be able to learn about the connections
## you make.
SocksPolicy accept 127.0.0.1
SocksPolicy accept6 [::1]
SocksPolicy reject *
## Tor will reject application connections that use unsafe variants of the socks protocol
##ones that only provide an IP address, meaning the application is doing a DNS resolve first.
## Specifically, these are socks4 and socks5 when not doing remote DNS. (Default: 0)
#SafeSocks 1
## Tor will make a notice-level log entry for each connection to the Socks port indicating
## whether the request used a safe socks protocol or an unsafe one (see above entry on SafeSocks).
## This helps to determine whether an application using Tor is possibly leaking DNS requests. (Default: 0)
TestSocks 1
## Logs go to stdout at level "notice" unless redirected by something
## else, like one of the below lines. You can have as many Log lines as
## you want.
##
## We advise using "notice" in most cases, since anything more verbose
## may provide sensitive information to an attacker who obtains the logs.
##
## Send all messages of level 'notice' or higher to /var/log/tor/notices.log
#Log notice file /var/log/tor/notices.log
## Send every possible message to /var/log/tor/debug.log
#Log debug file /var/log/tor/debug.log
## Use the system log instead of Tor's logfiles (This is default)
#Log notice syslog
## To send all messages to stderr:
#Log debug stderr
# Try to write to disk less frequently than we would otherwise. This is useful when running on flash memory.
AvoidDiskWrites 1
HiddenServiceStatistics 0
## Compute the hash of a password with "tor --hash-password password".
HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C
#CookieAuthentication 0 # (Default: 1)
## MetricsPort provides an interface to the underlying Tor relay metrics.
## Exposing publicly is dangerous, set a very strict access policy.
## Retrieve the metrics with: curl http://127.0.0.1:9035/metrics
MetricsPort 127.0.0.1:9035
MetricsPortPolicy accept 127.0.0.1
MetricsPortPolicy accept [::1]
HiddenServiceDir /var/lib/tor/haveno_seednode_2001
HiddenServicePort 2001 127.0.0.1:2001
HiddenServicePort 2001 [::1]:2001
HiddenServiceEnableIntroDoSDefense 1
HiddenServicePoWDefensesEnabled 1
HiddenServicePoWQueueRate 50 # (Default: 250)
HiddenServicePoWQueueBurst 250 # (Default: 2500)
HiddenServiceMaxStreams 25
HiddenServiceDir /var/lib/tor/haveno_seednode_2002
HiddenServicePort 2002 127.0.0.1:2002
HiddenServicePort 2002 [::1]:2002
HiddenServiceEnableIntroDoSDefense 1
#HiddenServiceEnableIntroDoSRatePerSec 25 # (Default: 25)
#HiddenServiceEnableIntroDoSBurstPerSec 200 # (Default: 200)
HiddenServicePoWDefensesEnabled 1
HiddenServicePoWQueueRate 50 # (Default: 250)
HiddenServicePoWQueueBurst 250 # (Default: 2500)
HiddenServiceMaxStreams 25
#HiddenServiceMaxStreamsCloseCircuit 1
HiddenServiceDir /var/lib/tor/haveno_seednode_2003
HiddenServicePort 2003 127.0.0.1:2003
HiddenServicePort 2003 [::1]:2003
HiddenServiceEnableIntroDoSDefense 1
#HiddenServiceEnableIntroDoSRatePerSec 25 # (Default: 25)
#HiddenServiceEnableIntroDoSBurstPerSec 200 # (Default: 200)
#HiddenServiceNumIntroductionPoints 3 # (Default: 3)
HiddenServicePoWDefensesEnabled 1
HiddenServicePoWQueueRate 50 # (Default: 250)
HiddenServicePoWQueueBurst 250 # (Default: 2500)
HiddenServiceMaxStreams 25
#HiddenServiceMaxStreamsCloseCircuit 1
LongLivedPorts 2001,2002,2003

View file

@ -1124,3 +1124,201 @@ message AddressBalanceInfo {
int64 num_confirmations = 3;
bool is_address_unused = 4;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Marketplace Protospec
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Orders
///////////////////////////////////////////////////////////////////////////////////////////
service Orders {
rpc GetOrder (GetOrderRequest) returns (GetOrderReply) {
}
rpc GetOrders (GetOrdersRequest) returns (GetOrdersReply) {
}
rpc MakeOrder (MakeOrderRequest) returns (MakeOrderReply) {
}
rpc ConfirmOrderAccepted (ConfirmOrderAcceptedRequest) returns (ConfirmOrderAcceptedReply) {
}
rpc ConfirmOrderProcessing (ConfirmOrderProcessingRequest) returns (ConfirmOrderProcessingReply) {
}
rpc ConfirmOrderShipped (ConfirmOrderShippedRequest) returns (ConfirmOrderShippedReply) {
}
rpc FinalizeOrder (FinalizeOrderRequest) returns (FinalizeOrderReply) {
}
rpc GetChatMessages (GetChatMessagesRequest) returns (GetChatMessagesReply) {
}
rpc SendChatMessage (SendChatMessageRequest) returns (SendChatMessageReply) {
}
}
message GetMyOrderRequest {
string id = 1;
}
message GetMyOrderReply {
OrderInfo order = 1;
}
message GetOrdersRequest {
string direction = 1;
string currency_code = 2;
}
message GetOrdersReply {
repeated OfferInfo orders = 1;
}
message GetMyOrdersRequest {
}
message GetMyOrdersReply {
repeated OfferInfo orders = 1;
}
message MakeOrderRequest {
string currency_code = 1;
string direction = 2;
string price = 3;
bool use_market_based_price = 4;
double market_price_margin_pct = 5;
uint64 amount = 6 [jstype = JS_STRING];
uint64 min_amount = 7 [jstype = JS_STRING];
double security_deposit_pct = 8;
string trigger_price = 9;
bool reserve_exact_amount = 10;
string payment_account_id = 11;
bool is_private_order = 12;
bool buyer_as_taker_without_deposit = 13;
string extra_info = 14;
string source_order_id = 15;
}
message MakeOrderReply {
OrderInfo order = 1;
}
message CancelOrderRequest {
string id = 1;
}
message CancelOrderReply {
}
message ConfirmOrderAcceptedRequest {
string id = 1;
}
message ConfirmOrderAcceptedReply {
OrderInfo offer = 1;
}
message ConfirmOrderProcessingRequest {
string id = 1;
}
message ConfirmOrderProcessingReply {
OrderInfo order = 1;
}
message ConfirmOrderShippedRequest {
string id = 1;
}
message ConfirmOrderShippedReply {
OrderInfo order = 1;
}
message FinalizeOrderRequest {
string id = 1;
}
message FinalizeOrderReply {
OrderInfo order = 1;
}
message OrderInfo {
string id = 1;
string category = 2;
string purchase_price = 3;
bool use_market_based_price = 4;
double market_price_margin_pct = 5;
uint64 amount = 6 [jstype = JS_STRING];
uint64 quantity = 7 [jstype = JS_STRING];
double buyer_fee_pct = 8;
double seller_fee_pct = 9;
double penalty_fee_pct = 10;
double buyer_security_deposit_pct = 11;
double seller_security_deposit_pct = 12;
string max_purchase_quantity = 13;
ShippingOptionInfo shipping_option = 14;
string trigger_price = 15;
string payment_account_id = 16;
string payment_method_id = 17;
string payment_method_short_name = 18;
string base_currency_code = 19;
string seller_public_key = 20;
uint64 date = 21;
string state = 22;
bool is_activated = 23;
bool is_my_order = 24;
string store_node_address = 25;
string pub_key_ring = 26;
string version_nr = 27;
int32 protocol_version = 28;
string arbitrator_signer = 29;
string split_output_tx_hash = 30;
uint64 split_output_tx_fee = 31 [jstype = JS_STRING];
bool is_private_order = 32;
string challenge = 33;
string extra_info = 34;
}
message GetOrderRequest {
string id = 1;
}
message GetOrderReply {
OrderInfo order = 1;
}
message ShippingOptionInfo {
string id = 1;
string label = 2;
string price = 3;
StoreInfo store = 4;
}
message GetShippingOptionRequest {
string id = 1;
}
message GetShippingOptionReply {
ShippingOptionInfo shipping_option = 1;
}
message StoreInfo {
string id = 1;
string label = 2;
string name = 3;
bool is_active = 4;
double cost = 5;
uint64 estimated_days = 6 [jstype = JS_STRING];
uint64 quantity = 7 [jstype = JS_STRING];
StoreInfo store = 8;
}
message GetStoreRequest {
string store_id = 1;
}
message GetStoreReply {
StoreInfo store = 1;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Products
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -12,5 +12,6 @@ include 'seednode'
include 'statsnode'
include 'inventory'
include 'apitest'
//include 'bot'
rootProject.name = 'haveno'