diff --git a/apitest/scripts/mainnet-test.sh b/apitest/scripts/mainnet-test.sh
index bfab9fc3b5f..5ade2b55f41 100755
--- a/apitest/scripts/mainnet-test.sh
+++ b/apitest/scripts/mainnet-test.sh
@@ -45,17 +45,19 @@
}
@test "test getversion call with quoted password" {
+ load 'version-parser'
run ./bisq-cli --password="xyz" getversion
[ "$status" -eq 0 ]
echo "actual output: $output" >&2
- [ "$output" = "1.3.9" ]
+ [ "$output" = "$CURRENT_VERSION" ]
}
@test "test getversion" {
+ load 'version-parser'
run ./bisq-cli --password=xyz getversion
[ "$status" -eq 0 ]
echo "actual output: $output" >&2
- [ "$output" = "1.3.9" ]
+ [ "$output" = "$CURRENT_VERSION" ]
}
@test "test setwalletpassword \"a b c\"" {
diff --git a/apitest/scripts/version-parser.bash b/apitest/scripts/version-parser.bash
new file mode 100755
index 00000000000..ba7f2c2d0f7
--- /dev/null
+++ b/apitest/scripts/version-parser.bash
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# Bats helper script for parsing current version from Version.java.
+
+export CURRENT_VERSION=$(grep "String VERSION =" common/src/main/java/bisq/common/app/Version.java | sed 's/[^0-9.]*//g')
diff --git a/apitest/src/test/java/bisq/apitest/method/CreateOfferTest.java b/apitest/src/test/java/bisq/apitest/method/CreateOfferTest.java
new file mode 100644
index 00000000000..233daa5a780
--- /dev/null
+++ b/apitest/src/test/java/bisq/apitest/method/CreateOfferTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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 .
+ */
+
+package bisq.apitest.method;
+
+import bisq.core.btc.wallet.Restrictions;
+
+import bisq.proto.grpc.CreateOfferRequest;
+import bisq.proto.grpc.GetOffersRequest;
+import bisq.proto.grpc.OfferInfo;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind;
+import static bisq.apitest.config.BisqAppConfig.alicedaemon;
+import static bisq.apitest.config.BisqAppConfig.arbdaemon;
+import static bisq.apitest.config.BisqAppConfig.seednode;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
+
+
+@Slf4j
+@TestMethodOrder(OrderAnnotation.class)
+public class CreateOfferTest extends MethodTest {
+
+ @BeforeAll
+ public static void setUp() {
+ try {
+ // setUpScaffold(new String[]{"--supportingApps", "bitcoind,seednode,arbdaemon,alicedaemon", "--enableBisqDebugging", "true"});
+ setUpScaffold(bitcoind, seednode, arbdaemon, alicedaemon);
+
+ // Generate 1 regtest block for alice's wallet to show 10 BTC balance,
+ // and give alicedaemon time to parse the new block.
+ bitcoinCli.generateBlocks(1);
+ MILLISECONDS.sleep(1500);
+ } catch (Exception ex) {
+ fail(ex);
+ }
+ }
+
+ @Test
+ @Order(1)
+ public void testCreateBuyOffer() {
+ var paymentAccount = getDefaultPerfectDummyPaymentAccount(alicedaemon);
+ var req = CreateOfferRequest.newBuilder()
+ .setCurrencyCode("USD")
+ .setDirection("BUY")
+ .setPrice(0)
+ .setUseMarketBasedPrice(true)
+ .setMarketPriceMargin(0.00)
+ .setAmount(10000000)
+ .setMinAmount(10000000)
+ .setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
+ .setPaymentAccountId(paymentAccount.getId())
+ .build();
+ var newOffer = grpcStubs(alicedaemon).offersService.createOffer(req).getOffer();
+ assertEquals("BUY", newOffer.getDirection());
+ assertTrue(newOffer.getUseMarketBasedPrice());
+ assertEquals(10000000, newOffer.getAmount());
+ assertEquals(10000000, newOffer.getMinAmount());
+ assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
+ assertEquals(paymentAccount.getId(), newOffer.getPaymentAccountId());
+ assertEquals("BTC", newOffer.getBaseCurrencyCode());
+ assertEquals("USD", newOffer.getCounterCurrencyCode());
+ }
+
+ @Test
+ @Order(2)
+ public void testGetNewBuyOffer() {
+ var req = GetOffersRequest.newBuilder().setDirection("BUY").setCurrencyCode("USD").build();
+ var reply = grpcStubs(alicedaemon).offersService.getOffers(req);
+
+ assertEquals(1, reply.getOffersCount());
+ OfferInfo offer = reply.getOffersList().get(0);
+ assertEquals("BUY", offer.getDirection());
+ assertTrue(offer.getUseMarketBasedPrice());
+ assertEquals(10000000, offer.getAmount());
+ assertEquals(10000000, offer.getMinAmount());
+ assertEquals(1500000, offer.getBuyerSecurityDeposit());
+ assertEquals("", offer.getPaymentAccountId());
+ assertEquals("BTC", offer.getBaseCurrencyCode());
+ assertEquals("USD", offer.getCounterCurrencyCode());
+ }
+
+ @AfterAll
+ public static void tearDown() {
+ tearDownScaffold();
+ }
+}
diff --git a/apitest/src/test/java/bisq/apitest/method/CreatePaymentAccountTest.java b/apitest/src/test/java/bisq/apitest/method/CreatePaymentAccountTest.java
new file mode 100644
index 00000000000..661205c74d3
--- /dev/null
+++ b/apitest/src/test/java/bisq/apitest/method/CreatePaymentAccountTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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 .
+ */
+
+package bisq.apitest.method;
+
+import bisq.proto.grpc.GetPaymentAccountsRequest;
+
+import protobuf.PaymentAccount;
+import protobuf.PerfectMoneyAccountPayload;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind;
+import static bisq.apitest.config.BisqAppConfig.alicedaemon;
+import static java.util.Comparator.comparing;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
+
+
+@Slf4j
+@TestMethodOrder(OrderAnnotation.class)
+public class CreatePaymentAccountTest extends MethodTest {
+
+ static final String PERFECT_MONEY_ACCT_NAME = "Perfect Money USD";
+ static final String PERFECT_MONEY_ACCT_NUMBER = "0123456789";
+
+ @BeforeAll
+ public static void setUp() {
+ try {
+ setUpScaffold(bitcoind, alicedaemon);
+ } catch (Exception ex) {
+ fail(ex);
+ }
+ }
+
+ @Test
+ @Order(1)
+ public void testCreatePerfectMoneyUSDPaymentAccount() {
+ var perfectMoneyPaymentAccountRequest = createCreatePerfectMoneyPaymentAccountRequest(
+ PERFECT_MONEY_ACCT_NAME,
+ PERFECT_MONEY_ACCT_NUMBER,
+ "USD");
+ //noinspection ResultOfMethodCallIgnored
+ grpcStubs(alicedaemon).paymentAccountsService.createPaymentAccount(perfectMoneyPaymentAccountRequest);
+
+ var getPaymentAccountsRequest = GetPaymentAccountsRequest.newBuilder().build();
+ var reply = grpcStubs(alicedaemon).paymentAccountsService.getPaymentAccounts(getPaymentAccountsRequest);
+
+ // The daemon is running against the regtest/dao setup files, and was set up with
+ // two dummy accounts ("PerfectMoney dummy", "ETH dummy") before any tests ran.
+ // We just added 1 test account, making 3 total.
+ assertEquals(3, reply.getPaymentAccountsCount());
+
+ // Sort the returned list by creation date; the last item in the sorted
+ // list will be the payment acct we just created.
+ List paymentAccountList = reply.getPaymentAccountsList().stream()
+ .sorted(comparing(PaymentAccount::getCreationDate))
+ .collect(Collectors.toList());
+ PaymentAccount paymentAccount = paymentAccountList.get(2);
+ PerfectMoneyAccountPayload perfectMoneyAccount = paymentAccount
+ .getPaymentAccountPayload()
+ .getPerfectMoneyAccountPayload();
+
+ assertEquals(PERFECT_MONEY_ACCT_NAME, paymentAccount.getAccountName());
+ assertEquals("USD",
+ paymentAccount.getSelectedTradeCurrency().getFiatCurrency().getCurrency().getCurrencyCode());
+ assertEquals(PERFECT_MONEY_ACCT_NUMBER, perfectMoneyAccount.getAccountNr());
+ }
+
+ @AfterAll
+ public static void tearDown() {
+ tearDownScaffold();
+ }
+}
diff --git a/apitest/src/test/java/bisq/apitest/method/MethodTest.java b/apitest/src/test/java/bisq/apitest/method/MethodTest.java
index 3437ac59c94..3f9f2cec1c7 100644
--- a/apitest/src/test/java/bisq/apitest/method/MethodTest.java
+++ b/apitest/src/test/java/bisq/apitest/method/MethodTest.java
@@ -17,15 +17,26 @@
package bisq.apitest.method;
+import bisq.proto.grpc.CreatePaymentAccountRequest;
import bisq.proto.grpc.GetBalanceRequest;
import bisq.proto.grpc.GetFundingAddressesRequest;
+import bisq.proto.grpc.GetPaymentAccountsRequest;
import bisq.proto.grpc.LockWalletRequest;
import bisq.proto.grpc.RegisterDisputeAgentRequest;
import bisq.proto.grpc.RemoveWalletPasswordRequest;
import bisq.proto.grpc.SetWalletPasswordRequest;
import bisq.proto.grpc.UnlockWalletRequest;
+import protobuf.PaymentAccount;
+
+import java.util.stream.Collectors;
+
import static bisq.common.app.DevEnv.DEV_PRIVILEGE_PRIV_KEY;
+import static bisq.core.payment.payload.PaymentMethod.PERFECT_MONEY;
+import static bisq.core.support.dispute.agent.DisputeAgent.DisputeAgentType.MEDIATOR;
+import static bisq.core.support.dispute.agent.DisputeAgent.DisputeAgentType.REFUNDAGENT;
+import static java.util.Comparator.comparing;
+import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -64,12 +75,6 @@ protected final GetFundingAddressesRequest createGetFundingAddressesRequest() {
return GetFundingAddressesRequest.newBuilder().build();
}
- protected final RegisterDisputeAgentRequest createRegisterDisputeAgentRequest(String disputeAgentType) {
- return RegisterDisputeAgentRequest.newBuilder()
- .setDisputeAgentType(disputeAgentType)
- .setRegistrationKey(DEV_PRIVILEGE_PRIV_KEY).build();
- }
-
// Convenience methods for calling frequently used & thoroughly tested gRPC services.
protected final long getBalance(BisqAppConfig bisqAppConfig) {
@@ -96,4 +101,43 @@ protected final String getUnusedBtcAddress(BisqAppConfig bisqAppConfig) {
.get()
.getAddress();
}
+
+ protected final CreatePaymentAccountRequest createCreatePerfectMoneyPaymentAccountRequest(
+ String accountName,
+ String accountNumber,
+ String currencyCode) {
+ return CreatePaymentAccountRequest.newBuilder()
+ .setPaymentMethodId(PERFECT_MONEY.getId())
+ .setAccountName(accountName)
+ .setAccountNumber(accountNumber)
+ .setCurrencyCode(currencyCode)
+ .build();
+ }
+
+ protected final PaymentAccount getDefaultPerfectDummyPaymentAccount(BisqAppConfig bisqAppConfig) {
+ var getPaymentAccountsRequest = GetPaymentAccountsRequest.newBuilder().build();
+ var paymentAccountsService = grpcStubs(bisqAppConfig).paymentAccountsService;
+ PaymentAccount paymentAccount = paymentAccountsService.getPaymentAccounts(getPaymentAccountsRequest)
+ .getPaymentAccountsList()
+ .stream()
+ .sorted(comparing(PaymentAccount::getCreationDate))
+ .collect(Collectors.toList()).get(0);
+ assertEquals("PerfectMoney dummy", paymentAccount.getAccountName());
+ return paymentAccount;
+ }
+
+ // Static conveniences for test methods and test case fixture setups.
+
+ protected static RegisterDisputeAgentRequest createRegisterDisputeAgentRequest(String disputeAgentType) {
+ return RegisterDisputeAgentRequest.newBuilder()
+ .setDisputeAgentType(disputeAgentType.toLowerCase())
+ .setRegistrationKey(DEV_PRIVILEGE_PRIV_KEY).build();
+ }
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ protected static void registerDisputeAgents(BisqAppConfig bisqAppConfig) {
+ var disputeAgentsService = grpcStubs(bisqAppConfig).disputeAgentsService;
+ disputeAgentsService.registerDisputeAgent(createRegisterDisputeAgentRequest(MEDIATOR.name()));
+ disputeAgentsService.registerDisputeAgent(createRegisterDisputeAgentRequest(REFUNDAGENT.name()));
+ }
}
diff --git a/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java b/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java
index e09de2b061e..de6c195f961 100644
--- a/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java
+++ b/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java
@@ -33,6 +33,9 @@
import static bisq.apitest.config.BisqAppConfig.arbdaemon;
import static bisq.apitest.config.BisqAppConfig.seednode;
import static bisq.common.app.DevEnv.DEV_PRIVILEGE_PRIV_KEY;
+import static bisq.core.support.dispute.agent.DisputeAgent.DisputeAgentType.ARBITRATOR;
+import static bisq.core.support.dispute.agent.DisputeAgent.DisputeAgentType.MEDIATOR;
+import static bisq.core.support.dispute.agent.DisputeAgent.DisputeAgentType.REFUNDAGENT;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.fail;
@@ -44,10 +47,6 @@
@TestMethodOrder(OrderAnnotation.class)
public class RegisterDisputeAgentsTest extends MethodTest {
- private static final String ARBITRATOR = "arbitrator";
- private static final String MEDIATOR = "mediator";
- private static final String REFUNDAGENT = "refundagent";
-
@BeforeAll
public static void setUp() {
try {
@@ -61,7 +60,7 @@ public static void setUp() {
@Order(1)
public void testRegisterArbitratorShouldThrowException() {
var req =
- createRegisterDisputeAgentRequest(ARBITRATOR);
+ createRegisterDisputeAgentRequest(ARBITRATOR.name());
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req));
assertEquals("INVALID_ARGUMENT: arbitrators must be registered in a Bisq UI",
@@ -83,7 +82,7 @@ public void testInvalidDisputeAgentTypeArgShouldThrowException() {
@Order(3)
public void testInvalidRegistrationKeyArgShouldThrowException() {
var req = RegisterDisputeAgentRequest.newBuilder()
- .setDisputeAgentType(REFUNDAGENT)
+ .setDisputeAgentType(REFUNDAGENT.name().toLowerCase())
.setRegistrationKey("invalid" + DEV_PRIVILEGE_PRIV_KEY).build();
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req));
@@ -95,7 +94,7 @@ public void testInvalidRegistrationKeyArgShouldThrowException() {
@Order(4)
public void testRegisterMediator() {
var req =
- createRegisterDisputeAgentRequest(MEDIATOR);
+ createRegisterDisputeAgentRequest(MEDIATOR.name());
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req);
}
@@ -103,7 +102,7 @@ public void testRegisterMediator() {
@Order(5)
public void testRegisterRefundAgent() {
var req =
- createRegisterDisputeAgentRequest(REFUNDAGENT);
+ createRegisterDisputeAgentRequest(REFUNDAGENT.name());
grpcStubs(arbdaemon).disputeAgentsService.registerDisputeAgent(req);
}
diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java
index 341420666d2..1de508a15fc 100644
--- a/cli/src/main/java/bisq/cli/CliMain.java
+++ b/cli/src/main/java/bisq/cli/CliMain.java
@@ -60,6 +60,7 @@
public class CliMain {
private enum Method {
+ createoffer,
getoffers,
createpaymentacct,
getpaymentaccts,
@@ -167,6 +168,11 @@ public static void run(String[] args) {
out.println(formatAddressBalanceTbl(reply.getAddressBalanceInfoList()));
return;
}
+ case createoffer: {
+ // TODO
+ out.println("offer created");
+ return;
+ }
case getoffers: {
if (nonOptionArgs.size() < 3)
throw new IllegalArgumentException("incorrect parameter count,"
@@ -303,6 +309,7 @@ private static void printHelp(OptionParser parser, PrintStream stream) {
stream.format("%-22s%-50s%s%n", "getbalance", "", "Get server wallet balance");
stream.format("%-22s%-50s%s%n", "getaddressbalance", "address", "Get server wallet address balance");
stream.format("%-22s%-50s%s%n", "getfundingaddresses", "", "Get BTC funding addresses");
+ stream.format("%-22s%-50s%s%n", "createoffer", "", "Create and place an offer");
stream.format("%-22s%-50s%s%n", "getoffers", "buy | sell, fiat currency code", "Get current offers");
stream.format("%-22s%-50s%s%n", "createpaymentacct", "account name, account number, currency code", "Create PerfectMoney dummy account");
stream.format("%-22s%-50s%s%n", "getpaymentaccts", "", "Get user payment accounts");
diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java
index 81af1fae0f3..27f234a225c 100644
--- a/core/src/main/java/bisq/core/api/CoreApi.java
+++ b/core/src/main/java/bisq/core/api/CoreApi.java
@@ -87,17 +87,17 @@ public List getOffers(String direction, String fiatCurrencyCode) {
return coreOffersService.getOffers(direction, fiatCurrencyCode);
}
- public void createOffer(String currencyCode,
- String directionAsString,
- long priceAsLong,
- boolean useMarketBasedPrice,
- double marketPriceMargin,
- long amountAsLong,
- long minAmountAsLong,
- double buyerSecurityDeposit,
- String paymentAccountId,
- TransactionResultHandler resultHandler) {
- coreOffersService.createOffer(currencyCode,
+ public Offer createOffer(String currencyCode,
+ String directionAsString,
+ long priceAsLong,
+ boolean useMarketBasedPrice,
+ double marketPriceMargin,
+ long amountAsLong,
+ long minAmountAsLong,
+ double buyerSecurityDeposit,
+ String paymentAccountId,
+ TransactionResultHandler resultHandler) {
+ return coreOffersService.createOffer(currencyCode,
directionAsString,
priceAsLong,
useMarketBasedPrice,
@@ -109,19 +109,19 @@ public void createOffer(String currencyCode,
resultHandler);
}
- public void createOffer(String offerId,
- String currencyCode,
- OfferPayload.Direction direction,
- Price price,
- boolean useMarketBasedPrice,
- double marketPriceMargin,
- Coin amount,
- Coin minAmount,
- double buyerSecurityDeposit,
- PaymentAccount paymentAccount,
- boolean useSavingsWallet,
- TransactionResultHandler resultHandler) {
- coreOffersService.createOffer(offerId,
+ public Offer createOffer(String offerId,
+ String currencyCode,
+ OfferPayload.Direction direction,
+ Price price,
+ boolean useMarketBasedPrice,
+ double marketPriceMargin,
+ Coin amount,
+ Coin minAmount,
+ double buyerSecurityDeposit,
+ PaymentAccount paymentAccount,
+ boolean useSavingsWallet,
+ TransactionResultHandler resultHandler) {
+ return coreOffersService.createOffer(offerId,
currencyCode,
direction,
price,
diff --git a/core/src/main/java/bisq/core/api/CoreOffersService.java b/core/src/main/java/bisq/core/api/CoreOffersService.java
index 61ee0e006db..a1f60e4c760 100644
--- a/core/src/main/java/bisq/core/api/CoreOffersService.java
+++ b/core/src/main/java/bisq/core/api/CoreOffersService.java
@@ -77,16 +77,16 @@ List getOffers(String direction, String fiatCurrencyCode) {
return offers;
}
- void createOffer(String currencyCode,
- String directionAsString,
- long priceAsLong,
- boolean useMarketBasedPrice,
- double marketPriceMargin,
- long amountAsLong,
- long minAmountAsLong,
- double buyerSecurityDeposit,
- String paymentAccountId,
- TransactionResultHandler resultHandler) {
+ Offer createOffer(String currencyCode,
+ String directionAsString,
+ long priceAsLong,
+ boolean useMarketBasedPrice,
+ double marketPriceMargin,
+ long amountAsLong,
+ long minAmountAsLong,
+ double buyerSecurityDeposit,
+ String paymentAccountId,
+ TransactionResultHandler resultHandler) {
String offerId = createOfferService.getRandomOfferId();
OfferPayload.Direction direction = OfferPayload.Direction.valueOf(directionAsString);
Price price = Price.valueOf(currencyCode, priceAsLong);
@@ -97,7 +97,7 @@ void createOffer(String currencyCode,
boolean useSavingsWallet = true;
//noinspection ConstantConditions
- createOffer(offerId,
+ return createAndPlaceOffer(offerId,
currencyCode,
direction,
price,
@@ -111,19 +111,56 @@ void createOffer(String currencyCode,
resultHandler);
}
- void createOffer(String offerId,
- String currencyCode,
- OfferPayload.Direction direction,
- Price price,
- boolean useMarketBasedPrice,
- double marketPriceMargin,
- Coin amount,
- Coin minAmount,
- double buyerSecurityDeposit,
- PaymentAccount paymentAccount,
- boolean useSavingsWallet,
- TransactionResultHandler resultHandler) {
+ Offer createAndPlaceOffer(String offerId,
+ String currencyCode,
+ OfferPayload.Direction direction,
+ Price price,
+ boolean useMarketBasedPrice,
+ double marketPriceMargin,
+ Coin amount,
+ Coin minAmount,
+ double buyerSecurityDeposit,
+ PaymentAccount paymentAccount,
+ boolean useSavingsWallet,
+ TransactionResultHandler resultHandler) {
Coin useDefaultTxFee = Coin.ZERO;
+
+ Offer offer = createOfferService.createAndGetOffer(offerId,
+ direction,
+ currencyCode,
+ amount,
+ minAmount,
+ price,
+ useDefaultTxFee,
+ useMarketBasedPrice,
+ marketPriceMargin,
+ buyerSecurityDeposit,
+ paymentAccount);
+
+ // TODO give user chance to examine offer before placing it (placeoffer)
+ openOfferManager.placeOffer(offer,
+ buyerSecurityDeposit,
+ useSavingsWallet,
+ resultHandler,
+ log::error);
+
+ return offer;
+ }
+
+ Offer createOffer(String offerId,
+ String currencyCode,
+ OfferPayload.Direction direction,
+ Price price,
+ boolean useMarketBasedPrice,
+ double marketPriceMargin,
+ Coin amount,
+ Coin minAmount,
+ double buyerSecurityDeposit,
+ PaymentAccount paymentAccount,
+ boolean useSavingsWallet,
+ TransactionResultHandler resultHandler) {
+ Coin useDefaultTxFee = Coin.ZERO;
+
Offer offer = createOfferService.createAndGetOffer(offerId,
direction,
currencyCode,
@@ -141,5 +178,7 @@ void createOffer(String offerId,
useSavingsWallet,
resultHandler,
log::error);
+
+ return offer;
}
}
diff --git a/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java b/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java
index b49c57a23f9..a202b0dbdb4 100644
--- a/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java
+++ b/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java
@@ -62,8 +62,6 @@ void createPaymentAccount(String paymentMethodId,
accountNumber,
currencyCode);
- // TODO not sure if there is more to do at account creation.
- // Need to check all the flow when its created from UI.
user.addPaymentAccountIfNotExists(paymentAccount);
// Don't do this on mainnet until thoroughly tested.
diff --git a/core/src/main/java/bisq/core/support/dispute/agent/DisputeAgent.java b/core/src/main/java/bisq/core/support/dispute/agent/DisputeAgent.java
index aa583d04de8..acd7d5367ee 100644
--- a/core/src/main/java/bisq/core/support/dispute/agent/DisputeAgent.java
+++ b/core/src/main/java/bisq/core/support/dispute/agent/DisputeAgent.java
@@ -43,6 +43,12 @@
public abstract class DisputeAgent implements ProtectedStoragePayload, ExpirablePayload {
public static final long TTL = TimeUnit.DAYS.toMillis(10);
+ public enum DisputeAgentType {
+ ARBITRATOR,
+ MEDIATOR,
+ REFUNDAGENT
+ }
+
protected final NodeAddress nodeAddress;
protected final PubKeyRing pubKeyRing;
protected final List languageCodes;
diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java
index b8b00f6d123..fd9e41a772b 100644
--- a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java
+++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java
@@ -19,6 +19,7 @@
import bisq.core.api.CoreApi;
import bisq.core.api.model.OfferInfo;
+import bisq.core.offer.Offer;
import bisq.core.trade.handlers.TransactionResultHandler;
import bisq.proto.grpc.CreateOfferReply;
@@ -27,11 +28,14 @@
import bisq.proto.grpc.GetOffersRequest;
import bisq.proto.grpc.OffersGrpc;
+import io.grpc.Status;
+import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;
import javax.inject.Inject;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
@@ -86,21 +90,53 @@ public void getOffers(GetOffersRequest req,
@Override
public void createOffer(CreateOfferRequest req,
StreamObserver responseObserver) {
- TransactionResultHandler resultHandler = transaction -> {
- CreateOfferReply reply = CreateOfferReply.newBuilder().setResult(true).build();
+ CountDownLatch latch = new CountDownLatch(1);
+ try {
+ TransactionResultHandler resultHandler = transaction -> {
+ latch.countDown();
+ };
+ Offer offer = coreApi.createOffer(
+ req.getCurrencyCode(),
+ req.getDirection(),
+ req.getPrice(),
+ req.getUseMarketBasedPrice(),
+ req.getMarketPriceMargin(),
+ req.getAmount(),
+ req.getMinAmount(),
+ req.getBuyerSecurityDeposit(),
+ req.getPaymentAccountId(),
+ resultHandler);
+ try {
+ latch.await();
+ } catch (InterruptedException ignored) {
+ // empty
+ }
+
+ OfferInfo offerInfo = new OfferInfo.OfferInfoBuilder()
+ .withId(offer.getId())
+ .withDirection(offer.getDirection().name())
+ .withPrice(offer.getPrice().getValue())
+ .withUseMarketBasedPrice(offer.isUseMarketBasedPrice())
+ .withMarketPriceMargin(offer.getMarketPriceMargin())
+ .withAmount(offer.getAmount().value)
+ .withMinAmount(offer.getMinAmount().value)
+ .withVolume(offer.getVolume().getValue())
+ .withMinVolume(offer.getMinVolume().getValue())
+ .withBuyerSecurityDeposit(offer.getBuyerSecurityDeposit().value)
+ .withPaymentAccountId(offer.getMakerPaymentAccountId())
+ .withPaymentMethodId(offer.getPaymentMethod().getId())
+ .withPaymentMethodShortName(offer.getPaymentMethod().getShortName())
+ .withBaseCurrencyCode(offer.getOfferPayload().getBaseCurrencyCode())
+ .withCounterCurrencyCode(offer.getOfferPayload().getCounterCurrencyCode())
+ .withDate(offer.getDate().getTime())
+ .build();
+ CreateOfferReply reply = CreateOfferReply.newBuilder().setOffer(offerInfo.toProtoMessage()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
- };
- coreApi.createOffer(
- req.getCurrencyCode(),
- req.getDirection(),
- req.getPrice(),
- req.getUseMarketBasedPrice(),
- req.getMarketPriceMargin(),
- req.getAmount(),
- req.getMinAmount(),
- req.getBuyerSecurityDeposit(),
- req.getPaymentAccountId(),
- resultHandler);
+ } catch (IllegalStateException | IllegalArgumentException cause) {
+ var ex = new StatusRuntimeException(Status.UNKNOWN.withDescription(cause.getMessage()));
+ responseObserver.onError(ex);
+ throw ex;
+ }
}
}
diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto
index 21c59b8643d..c0477fb5fbc 100644
--- a/proto/src/main/proto/grpc.proto
+++ b/proto/src/main/proto/grpc.proto
@@ -73,7 +73,7 @@ message CreateOfferRequest {
}
message CreateOfferReply {
- bool result = 1;
+ OfferInfo offer = 1;
}
message OfferInfo {
@@ -107,7 +107,7 @@ service PaymentAccounts {
}
message CreatePaymentAccountRequest {
-string paymentMethodId = 1;
+ string paymentMethodId = 1;
string accountName = 2;
string accountNumber = 3;
// TODO Support all currencies. Maybe add a repeated and if only one is used its a singletonList.