Merge pull request #5056 from ghubstan/add-getmyoffers-api-method

Add new api methods 'getmyoffers' and 'getmyoffer'
This commit is contained in:
sqrrm 2021-01-07 22:51:33 +01:00 committed by GitHub
commit 76e2330b15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 297 additions and 88 deletions

View File

@ -19,6 +19,7 @@ package bisq.apitest.method;
import bisq.core.api.model.PaymentAccountForm;
import bisq.core.api.model.TxFeeRateInfo;
import bisq.core.payment.F2FAccount;
import bisq.core.proto.CoreProtoResolver;
import bisq.common.util.Utilities;
@ -34,6 +35,7 @@ import bisq.proto.grpc.CreatePaymentAccountRequest;
import bisq.proto.grpc.GetAddressBalanceRequest;
import bisq.proto.grpc.GetBalancesRequest;
import bisq.proto.grpc.GetFundingAddressesRequest;
import bisq.proto.grpc.GetMyOfferRequest;
import bisq.proto.grpc.GetOfferRequest;
import bisq.proto.grpc.GetPaymentAccountFormRequest;
import bisq.proto.grpc.GetPaymentAccountsRequest;
@ -134,8 +136,8 @@ public class MethodTest extends ApiTestCase {
}
protected static void doPostStartup(boolean registerDisputeAgents,
boolean generateBtcBlock,
Enum<?>... supportingApps) {
boolean generateBtcBlock,
Enum<?>... supportingApps) {
if (registerDisputeAgents) {
registerDisputeAgents(arbdaemon);
}
@ -223,6 +225,10 @@ public class MethodTest extends ApiTestCase {
return GetOfferRequest.newBuilder().setId(offerId).build();
}
protected final GetMyOfferRequest createGetMyOfferRequest(String offerId) {
return GetMyOfferRequest.newBuilder().setId(offerId).build();
}
protected final CancelOfferRequest createCancelOfferRequest(String offerId) {
return CancelOfferRequest.newBuilder().setId(offerId).build();
}
@ -401,6 +407,11 @@ public class MethodTest extends ApiTestCase {
return grpcStubs(bisqAppConfig).offersService.getOffer(req).getOffer();
}
protected final OfferInfo getMyOffer(BisqAppConfig bisqAppConfig, String offerId) {
var req = createGetMyOfferRequest(offerId);
return grpcStubs(bisqAppConfig).offersService.getMyOffer(req).getOffer();
}
@SuppressWarnings("ResultOfMethodCallIgnored")
protected final void cancelOffer(BisqAppConfig bisqAppConfig, String offerId) {
var req = createCancelOfferRequest(offerId);
@ -464,6 +475,21 @@ public class MethodTest extends ApiTestCase {
return grpcStubs(bisqAppConfig).walletsService.getTransaction(req).getTxInfo();
}
public bisq.core.payment.PaymentAccount createDummyF2FAccount(BisqAppConfig bisqAppConfig,
String countryCode) {
String f2fAccountJsonString = "{\n" +
" \"_COMMENTS_\": \"This is a dummy account.\",\n" +
" \"paymentMethodId\": \"F2F\",\n" +
" \"accountName\": \"Dummy " + countryCode.toUpperCase() + " F2F Account\",\n" +
" \"city\": \"Anytown\",\n" +
" \"contact\": \"Morse Code\",\n" +
" \"country\": \"" + countryCode.toUpperCase() + "\",\n" +
" \"extraInfo\": \"Salt Lick #213\"\n" +
"}\n";
F2FAccount f2FAccount = (F2FAccount) createPaymentAccount(bisqAppConfig, f2fAccountJsonString);
return f2FAccount;
}
// Static conveniences for test methods and test case fixture setups.
protected static RegisterDisputeAgentRequest createRegisterDisputeAgentRequest(String disputeAgentType) {

View File

@ -18,13 +18,13 @@
package bisq.apitest.method.offer;
import bisq.core.monetary.Altcoin;
import bisq.core.payment.PaymentAccount;
import bisq.proto.grpc.CreateOfferRequest;
import bisq.proto.grpc.GetMyOffersRequest;
import bisq.proto.grpc.GetOffersRequest;
import bisq.proto.grpc.OfferInfo;
import protobuf.PaymentAccount;
import org.bitcoinj.utils.Fiat;
import java.math.BigDecimal;
@ -121,6 +121,10 @@ public abstract class AbstractOfferTest extends MethodTest {
return aliceStubs.offersService.getOffer(createGetOfferRequest(offerId)).getOffer();
}
protected final OfferInfo getMyOffer(String offerId) {
return aliceStubs.offersService.getMyOffer(createGetMyOfferRequest(offerId)).getOffer();
}
@SuppressWarnings("ResultOfMethodCallIgnored")
protected final void cancelOffer(GrpcStubs grpcStubs, String offerId) {
grpcStubs.offersService.cancelOffer(createCancelOfferRequest(offerId));
@ -134,11 +138,9 @@ public abstract class AbstractOfferTest extends MethodTest {
return offerInfoList.get(offerInfoList.size() - 1);
}
protected final int getOpenOffersCount(GrpcStubs grpcStubs, String direction, String currencyCode) {
return getOffersSortedByDate(grpcStubs, direction, currencyCode).size();
}
protected final List<OfferInfo> getOffersSortedByDate(GrpcStubs grpcStubs, String direction, String currencyCode) {
protected final List<OfferInfo> getOffersSortedByDate(GrpcStubs grpcStubs,
String direction,
String currencyCode) {
var req = GetOffersRequest.newBuilder()
.setDirection(direction)
.setCurrencyCode(currencyCode).build();
@ -146,6 +148,16 @@ public abstract class AbstractOfferTest extends MethodTest {
return sortOffersByDate(reply.getOffersList());
}
protected final List<OfferInfo> getMyOffersSortedByDate(GrpcStubs grpcStubs,
String direction,
String currencyCode) {
var req = GetMyOffersRequest.newBuilder()
.setDirection(direction)
.setCurrencyCode(currencyCode).build();
var reply = grpcStubs.offersService.getMyOffers(req);
return sortOffersByDate(reply.getOffersList());
}
protected final List<OfferInfo> sortOffersByDate(List<OfferInfo> offerInfoList) {
return offerInfoList.stream()
.sorted(comparing(OfferInfo::getDate))

View File

@ -18,6 +18,7 @@
package bisq.apitest.method.offer;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.payment.PaymentAccount;
import bisq.proto.grpc.CreateOfferRequest;
import bisq.proto.grpc.OfferInfo;
@ -32,6 +33,7 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Disabled
@ -39,15 +41,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class CancelOfferTest extends AbstractOfferTest {
private static final String DIRECTION = "buy";
private static final String CURRENCY_CODE = "cad";
private static final int MAX_OFFERS = 3;
@Test
@Order(1)
public void testCancelOffer() {
PaymentAccount cadAccount = createDummyF2FAccount(alicedaemon, "CA");
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setDirection("buy")
.setCurrencyCode("cad")
.setPaymentAccountId(cadAccount.getId())
.setDirection(DIRECTION)
.setCurrencyCode(CURRENCY_CODE)
.setAmount(10000000)
.setMinAmount(10000000)
.setUseMarketBasedPrice(true)
@ -66,18 +71,19 @@ public class CancelOfferTest extends AbstractOfferTest {
sleep(2500);
}
List<OfferInfo> offers = getOffersSortedByDate(aliceStubs, "buy", "cad");
List<OfferInfo> offers = getMyOffersSortedByDate(aliceStubs, DIRECTION, CURRENCY_CODE);
assertEquals(MAX_OFFERS, offers.size());
// Cancel the offers, checking the open offer count after each offer removal.
for (int i = 1; i <= MAX_OFFERS; i++) {
cancelOffer(aliceStubs, offers.remove(0).getId());
assertEquals(MAX_OFFERS - i, getOpenOffersCount(aliceStubs, "buy", "cad"));
offers = getMyOffersSortedByDate(aliceStubs, DIRECTION, CURRENCY_CODE);
assertEquals(MAX_OFFERS - i, offers.size());
}
sleep(1000); // wait for offer removal
offers = getOffersSortedByDate(aliceStubs, "buy", "cad");
offers = getMyOffersSortedByDate(aliceStubs, DIRECTION, CURRENCY_CODE);
assertEquals(0, offers.size());
}
}

View File

@ -17,7 +17,7 @@
package bisq.apitest.method.offer;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.payment.PaymentAccount;
import bisq.proto.grpc.CreateOfferRequest;
@ -29,6 +29,8 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static bisq.core.btc.wallet.Restrictions.getDefaultBuyerSecurityDepositAsPercent;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@ -43,16 +45,17 @@ public class CreateOfferUsingFixedPriceTest extends AbstractOfferTest {
@Test
@Order(1)
public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() {
PaymentAccount audAccount = createDummyF2FAccount(alicedaemon, "AU");
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setPaymentAccountId(audAccount.getId())
.setDirection("buy")
.setCurrencyCode("aud")
.setAmount(10000000)
.setMinAmount(10000000)
.setUseMarketBasedPrice(false)
.setMarketPriceMargin(0.00)
.setPrice("16000")
.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
.setPrice("36000")
.setBuyerSecurityDeposit(getDefaultBuyerSecurityDepositAsPercent())
.setMakerFeeCurrencyCode(MAKER_FEE_CURRENCY_CODE)
.build();
var newOffer = aliceStubs.offersService.createOffer(req).getOffer();
@ -60,24 +63,24 @@ public class CreateOfferUsingFixedPriceTest extends AbstractOfferTest {
assertNotEquals("", newOfferId);
assertEquals("BUY", newOffer.getDirection());
assertFalse(newOffer.getUseMarketBasedPrice());
assertEquals(160000000, newOffer.getPrice());
assertEquals(360000000, newOffer.getPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(audAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("AUD", newOffer.getCounterCurrencyCode());
assertFalse(newOffer.getIsCurrencyForMakerFeeBtc());
newOffer = getOffer(newOfferId);
newOffer = getMyOffer(newOfferId);
assertEquals(newOfferId, newOffer.getId());
assertEquals("BUY", newOffer.getDirection());
assertFalse(newOffer.getUseMarketBasedPrice());
assertEquals(160000000, newOffer.getPrice());
assertEquals(360000000, newOffer.getPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(audAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("AUD", newOffer.getCounterCurrencyCode());
assertFalse(newOffer.getIsCurrencyForMakerFeeBtc());
@ -86,16 +89,17 @@ public class CreateOfferUsingFixedPriceTest extends AbstractOfferTest {
@Test
@Order(2)
public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() {
PaymentAccount usdAccount = createDummyF2FAccount(alicedaemon, "US");
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setPaymentAccountId(usdAccount.getId())
.setDirection("buy")
.setCurrencyCode("usd")
.setAmount(10000000)
.setMinAmount(10000000)
.setUseMarketBasedPrice(false)
.setMarketPriceMargin(0.00)
.setPrice("10000.1234")
.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
.setPrice("30000.1234")
.setBuyerSecurityDeposit(getDefaultBuyerSecurityDepositAsPercent())
.setMakerFeeCurrencyCode(MAKER_FEE_CURRENCY_CODE)
.build();
var newOffer = aliceStubs.offersService.createOffer(req).getOffer();
@ -103,24 +107,24 @@ public class CreateOfferUsingFixedPriceTest extends AbstractOfferTest {
assertNotEquals("", newOfferId);
assertEquals("BUY", newOffer.getDirection());
assertFalse(newOffer.getUseMarketBasedPrice());
assertEquals(100001234, newOffer.getPrice());
assertEquals(300001234, newOffer.getPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(usdAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("USD", newOffer.getCounterCurrencyCode());
assertFalse(newOffer.getIsCurrencyForMakerFeeBtc());
newOffer = getOffer(newOfferId);
newOffer = getMyOffer(newOfferId);
assertEquals(newOfferId, newOffer.getId());
assertEquals("BUY", newOffer.getDirection());
assertFalse(newOffer.getUseMarketBasedPrice());
assertEquals(100001234, newOffer.getPrice());
assertEquals(300001234, newOffer.getPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(usdAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("USD", newOffer.getCounterCurrencyCode());
assertFalse(newOffer.getIsCurrencyForMakerFeeBtc());
@ -129,16 +133,17 @@ public class CreateOfferUsingFixedPriceTest extends AbstractOfferTest {
@Test
@Order(3)
public void testCreateEURBTCSellOfferUsingFixedPrice95001234() {
PaymentAccount eurAccount = createDummyF2FAccount(alicedaemon, "FR");
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setPaymentAccountId(eurAccount.getId())
.setDirection("sell")
.setCurrencyCode("eur")
.setAmount(10000000)
.setMinAmount(10000000)
.setUseMarketBasedPrice(false)
.setMarketPriceMargin(0.00)
.setPrice("9500.1234")
.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
.setPrice("29500.1234")
.setBuyerSecurityDeposit(getDefaultBuyerSecurityDepositAsPercent())
.setMakerFeeCurrencyCode(MAKER_FEE_CURRENCY_CODE)
.build();
var newOffer = aliceStubs.offersService.createOffer(req).getOffer();
@ -146,24 +151,24 @@ public class CreateOfferUsingFixedPriceTest extends AbstractOfferTest {
assertNotEquals("", newOfferId);
assertEquals("SELL", newOffer.getDirection());
assertFalse(newOffer.getUseMarketBasedPrice());
assertEquals(95001234, newOffer.getPrice());
assertEquals(295001234, newOffer.getPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(eurAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("EUR", newOffer.getCounterCurrencyCode());
assertFalse(newOffer.getIsCurrencyForMakerFeeBtc());
newOffer = getOffer(newOfferId);
newOffer = getMyOffer(newOfferId);
assertEquals(newOfferId, newOffer.getId());
assertEquals("SELL", newOffer.getDirection());
assertFalse(newOffer.getUseMarketBasedPrice());
assertEquals(95001234, newOffer.getPrice());
assertEquals(295001234, newOffer.getPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(eurAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("EUR", newOffer.getCounterCurrencyCode());
assertFalse(newOffer.getIsCurrencyForMakerFeeBtc());

View File

@ -17,7 +17,7 @@
package bisq.apitest.method.offer;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.payment.PaymentAccount;
import bisq.proto.grpc.CreateOfferRequest;
import bisq.proto.grpc.OfferInfo;
@ -32,8 +32,10 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static bisq.common.util.MathUtils.scaleDownByPowerOf10;
import static bisq.common.util.MathUtils.scaleUpByPowerOf10;
import static bisq.core.btc.wallet.Restrictions.getDefaultBuyerSecurityDepositAsPercent;
import static java.lang.Math.abs;
import static java.lang.String.format;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -55,9 +57,10 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
@Test
@Order(1)
public void testCreateUSDBTCBuyOffer5PctPriceMargin() {
PaymentAccount usdAccount = createDummyF2FAccount(alicedaemon, "US");
double priceMarginPctInput = 5.00;
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setPaymentAccountId(usdAccount.getId())
.setDirection("buy")
.setCurrencyCode("usd")
.setAmount(10000000)
@ -65,7 +68,7 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
.setUseMarketBasedPrice(true)
.setMarketPriceMargin(priceMarginPctInput)
.setPrice("0")
.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
.setBuyerSecurityDeposit(getDefaultBuyerSecurityDepositAsPercent())
.setMakerFeeCurrencyCode(MAKER_FEE_CURRENCY_CODE)
.build();
var newOffer = aliceStubs.offersService.createOffer(req).getOffer();
@ -76,19 +79,19 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(usdAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("USD", newOffer.getCounterCurrencyCode());
assertTrue(newOffer.getIsCurrencyForMakerFeeBtc());
newOffer = getOffer(newOfferId);
newOffer = getMyOffer(newOfferId);
assertEquals(newOfferId, newOffer.getId());
assertEquals("BUY", newOffer.getDirection());
assertTrue(newOffer.getUseMarketBasedPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(usdAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("USD", newOffer.getCounterCurrencyCode());
assertTrue(newOffer.getIsCurrencyForMakerFeeBtc());
@ -99,9 +102,10 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
@Test
@Order(2)
public void testCreateNZDBTCBuyOfferMinus2PctPriceMargin() {
PaymentAccount nzdAccount = createDummyF2FAccount(alicedaemon, "NZ");
double priceMarginPctInput = -2.00;
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setPaymentAccountId(nzdAccount.getId())
.setDirection("buy")
.setCurrencyCode("nzd")
.setAmount(10000000)
@ -109,7 +113,7 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
.setUseMarketBasedPrice(true)
.setMarketPriceMargin(priceMarginPctInput)
.setPrice("0")
.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
.setBuyerSecurityDeposit(getDefaultBuyerSecurityDepositAsPercent())
.setMakerFeeCurrencyCode(MAKER_FEE_CURRENCY_CODE)
.build();
var newOffer = aliceStubs.offersService.createOffer(req).getOffer();
@ -120,19 +124,19 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(nzdAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("NZD", newOffer.getCounterCurrencyCode());
assertTrue(newOffer.getIsCurrencyForMakerFeeBtc());
newOffer = getOffer(newOfferId);
newOffer = getMyOffer(newOfferId);
assertEquals(newOfferId, newOffer.getId());
assertEquals("BUY", newOffer.getDirection());
assertTrue(newOffer.getUseMarketBasedPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(nzdAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("NZD", newOffer.getCounterCurrencyCode());
assertTrue(newOffer.getIsCurrencyForMakerFeeBtc());
@ -143,9 +147,10 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
@Test
@Order(3)
public void testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin() {
PaymentAccount gbpAccount = createDummyF2FAccount(alicedaemon, "GB");
double priceMarginPctInput = -1.5;
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setPaymentAccountId(gbpAccount.getId())
.setDirection("sell")
.setCurrencyCode("gbp")
.setAmount(10000000)
@ -153,7 +158,7 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
.setUseMarketBasedPrice(true)
.setMarketPriceMargin(priceMarginPctInput)
.setPrice("0")
.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
.setBuyerSecurityDeposit(getDefaultBuyerSecurityDepositAsPercent())
.setMakerFeeCurrencyCode(MAKER_FEE_CURRENCY_CODE)
.build();
var newOffer = aliceStubs.offersService.createOffer(req).getOffer();
@ -165,19 +170,19 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(gbpAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("GBP", newOffer.getCounterCurrencyCode());
assertTrue(newOffer.getIsCurrencyForMakerFeeBtc());
newOffer = getOffer(newOfferId);
newOffer = getMyOffer(newOfferId);
assertEquals(newOfferId, newOffer.getId());
assertEquals("SELL", newOffer.getDirection());
assertTrue(newOffer.getUseMarketBasedPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(gbpAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("GBP", newOffer.getCounterCurrencyCode());
assertTrue(newOffer.getIsCurrencyForMakerFeeBtc());
@ -188,9 +193,10 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
@Test
@Order(4)
public void testCreateBRLBTCSellOffer6Point55PctPriceMargin() {
PaymentAccount brlAccount = createDummyF2FAccount(alicedaemon, "BR");
double priceMarginPctInput = 6.55;
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setPaymentAccountId(brlAccount.getId())
.setDirection("sell")
.setCurrencyCode("brl")
.setAmount(10000000)
@ -198,7 +204,7 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
.setUseMarketBasedPrice(true)
.setMarketPriceMargin(priceMarginPctInput)
.setPrice("0")
.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
.setBuyerSecurityDeposit(getDefaultBuyerSecurityDepositAsPercent())
.setMakerFeeCurrencyCode(MAKER_FEE_CURRENCY_CODE)
.build();
var newOffer = aliceStubs.offersService.createOffer(req).getOffer();
@ -210,19 +216,19 @@ public class CreateOfferUsingMarketPriceMarginTest extends AbstractOfferTest {
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(brlAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("BRL", newOffer.getCounterCurrencyCode());
assertTrue(newOffer.getIsCurrencyForMakerFeeBtc());
newOffer = getOffer(newOfferId);
newOffer = getMyOffer(newOfferId);
assertEquals(newOfferId, newOffer.getId());
assertEquals("SELL", newOffer.getDirection());
assertTrue(newOffer.getUseMarketBasedPrice());
assertEquals(10000000, newOffer.getAmount());
assertEquals(10000000, newOffer.getMinAmount());
assertEquals(1500000, newOffer.getBuyerSecurityDeposit());
assertEquals(alicesDummyAcct.getId(), newOffer.getPaymentAccountId());
assertEquals(brlAccount.getId(), newOffer.getPaymentAccountId());
assertEquals("BTC", newOffer.getBaseCurrencyCode());
assertEquals("BRL", newOffer.getCounterCurrencyCode());
assertTrue(newOffer.getIsCurrencyForMakerFeeBtc());

View File

@ -17,7 +17,7 @@
package bisq.apitest.method.offer;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.payment.PaymentAccount;
import bisq.proto.grpc.CreateOfferRequest;
@ -31,6 +31,8 @@ import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static bisq.core.btc.wallet.Restrictions.getDefaultBuyerSecurityDepositAsPercent;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ -42,8 +44,9 @@ public class ValidateCreateOfferTest extends AbstractOfferTest {
@Test
@Order(1)
public void testAmtTooLargeShouldThrowException() {
PaymentAccount usdAccount = createDummyF2FAccount(alicedaemon, "US");
var req = CreateOfferRequest.newBuilder()
.setPaymentAccountId(alicesDummyAcct.getId())
.setPaymentAccountId(usdAccount.getId())
.setDirection("buy")
.setCurrencyCode("usd")
.setAmount(100000000000L)
@ -51,7 +54,7 @@ public class ValidateCreateOfferTest extends AbstractOfferTest {
.setUseMarketBasedPrice(false)
.setMarketPriceMargin(0.00)
.setPrice("10000.0000")
.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent())
.setBuyerSecurityDeposit(getDefaultBuyerSecurityDepositAsPercent())
.setMakerFeeCurrencyCode("bsq")
.build();
@SuppressWarnings("ResultOfMethodCallIgnored")

View File

@ -17,6 +17,8 @@
package bisq.apitest.method.trade;
import bisq.core.payment.PaymentAccount;
import bisq.proto.grpc.BtcBalanceInfo;
import io.grpc.StatusRuntimeException;
@ -59,7 +61,8 @@ public class TakeBuyBTCOfferTest extends AbstractTradeTest {
@Order(1)
public void testTakeAlicesBuyOffer(final TestInfo testInfo) {
try {
var alicesOffer = createAliceOffer(alicesDummyAcct,
PaymentAccount alicesUsdAccount = createDummyF2FAccount(alicedaemon, "US");
var alicesOffer = createAliceOffer(alicesUsdAccount,
"buy",
"usd",
12500000,
@ -70,9 +73,11 @@ public class TakeBuyBTCOfferTest extends AbstractTradeTest {
// Wait for Alice's AddToOfferBook task.
// Wait times vary; my logs show >= 2 second delay.
sleep(3000); // TODO loop instead of hard code wait time
assertEquals(1, getOpenOffersCount(aliceStubs, "buy", "usd"));
var alicesUsdOffers = getMyOffersSortedByDate(aliceStubs, "buy", "usd");
assertEquals(1, alicesUsdOffers.size());
var trade = takeAlicesOffer(offerId, bobsDummyAcct.getId(), TRADE_FEE_CURRENCY_CODE);
PaymentAccount bobsUsdAccount = createDummyF2FAccount(bobdaemon, "US");
var trade = takeAlicesOffer(offerId, bobsUsdAccount.getId(), TRADE_FEE_CURRENCY_CODE);
assertNotNull(trade);
assertEquals(offerId, trade.getTradeId());
assertFalse(trade.getIsCurrencyForTakerFeeBtc());
@ -80,7 +85,8 @@ public class TakeBuyBTCOfferTest extends AbstractTradeTest {
tradeId = trade.getTradeId();
genBtcBlocksThenWait(1, 1000);
assertEquals(0, getOpenOffersCount(aliceStubs, "buy", "usd"));
alicesUsdOffers = getMyOffersSortedByDate(aliceStubs, "buy", "usd");
assertEquals(0, alicesUsdOffers.size());
trade = getTrade(bobdaemon, trade.getTradeId());
EXPECTED_PROTOCOL_STATUS.setState(SELLER_PUBLISHED_DEPOSIT_TX)

View File

@ -17,6 +17,8 @@
package bisq.apitest.method.trade;
import bisq.core.payment.PaymentAccount;
import bisq.proto.grpc.BtcBalanceInfo;
import io.grpc.StatusRuntimeException;
@ -58,7 +60,8 @@ public class TakeSellBTCOfferTest extends AbstractTradeTest {
@Order(1)
public void testTakeAlicesSellOffer(final TestInfo testInfo) {
try {
var alicesOffer = createAliceOffer(alicesDummyAcct,
PaymentAccount alicesUsdAccount = createDummyF2FAccount(alicedaemon, "US");
var alicesOffer = createAliceOffer(alicesUsdAccount,
"sell",
"usd",
12500000,
@ -70,9 +73,11 @@ public class TakeSellBTCOfferTest extends AbstractTradeTest {
// Wait times vary; my logs show >= 2 second delay, but taking sell offers
// seems to require more time to prepare.
sleep(3000); // TODO loop instead of hard code wait time
assertEquals(1, getOpenOffersCount(bobStubs, "sell", "usd"));
var alicesUsdOffers = getMyOffersSortedByDate(aliceStubs, "sell", "usd");
assertEquals(1, alicesUsdOffers.size());
var trade = takeAlicesOffer(offerId, bobsDummyAcct.getId(), TRADE_FEE_CURRENCY_CODE);
PaymentAccount bobsUsdAccount = createDummyF2FAccount(bobdaemon, "US");
var trade = takeAlicesOffer(offerId, bobsUsdAccount.getId(), TRADE_FEE_CURRENCY_CODE);
assertNotNull(trade);
assertEquals(offerId, trade.getTradeId());
assertTrue(trade.getIsCurrencyForTakerFeeBtc());
@ -80,7 +85,8 @@ public class TakeSellBTCOfferTest extends AbstractTradeTest {
tradeId = trade.getTradeId();
genBtcBlocksThenWait(1, 4000);
assertEquals(0, getOpenOffersCount(bobStubs, "sell", "usd"));
var takeableUsdOffers = getOffersSortedByDate(bobStubs, "sell", "usd");
assertEquals(0, takeableUsdOffers.size());
trade = getTrade(bobdaemon, trade.getTradeId());
EXPECTED_PROTOCOL_STATUS.setState(BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG)

View File

@ -25,6 +25,8 @@ import bisq.proto.grpc.CreatePaymentAccountRequest;
import bisq.proto.grpc.GetAddressBalanceRequest;
import bisq.proto.grpc.GetBalancesRequest;
import bisq.proto.grpc.GetFundingAddressesRequest;
import bisq.proto.grpc.GetMyOfferRequest;
import bisq.proto.grpc.GetMyOffersRequest;
import bisq.proto.grpc.GetOfferRequest;
import bisq.proto.grpc.GetOffersRequest;
import bisq.proto.grpc.GetPaymentAccountFormRequest;
@ -96,7 +98,9 @@ public class CliMain {
createoffer,
canceloffer,
getoffer,
getmyoffer,
getoffers,
getmyoffers,
takeoffer,
gettrade,
confirmpaymentstarted,
@ -418,6 +422,19 @@ public class CliMain {
reply.getOffer().getCounterCurrencyCode()));
return;
}
case getmyoffer: {
if (nonOptionArgs.size() < 2)
throw new IllegalArgumentException("incorrect parameter count, expecting offer id");
var offerId = nonOptionArgs.get(1);
var request = GetMyOfferRequest.newBuilder()
.setId(offerId)
.build();
var reply = offersService.getMyOffer(request);
out.println(formatOfferTable(singletonList(reply.getOffer()),
reply.getOffer().getCounterCurrencyCode()));
return;
}
case getoffers: {
if (nonOptionArgs.size() < 3)
throw new IllegalArgumentException("incorrect parameter count,"
@ -440,6 +457,28 @@ public class CliMain {
return;
}
case getmyoffers: {
if (nonOptionArgs.size() < 3)
throw new IllegalArgumentException("incorrect parameter count,"
+ " expecting direction (buy|sell), currency code");
var direction = nonOptionArgs.get(1);
var currencyCode = nonOptionArgs.get(2);
var request = GetMyOffersRequest.newBuilder()
.setDirection(direction)
.setCurrencyCode(currencyCode)
.build();
var reply = offersService.getMyOffers(request);
List<OfferInfo> offers = reply.getOffersList();
if (offers.isEmpty())
out.printf("no %s %s offers found%n", direction, currencyCode);
else
out.println(formatOfferTable(reply.getOffersList(), currencyCode));
return;
}
case takeoffer: {
if (nonOptionArgs.size() < 3)
throw new IllegalArgumentException("incorrect parameter count, " +
@ -747,7 +786,9 @@ public class CliMain {
stream.format(rowFormat, "", "[,maker fee currency code = bsq|btc]", "");
stream.format(rowFormat, "canceloffer", "offer id", "Cancel offer with id");
stream.format(rowFormat, "getoffer", "offer id", "Get current offer with id");
stream.format(rowFormat, "getmyoffer", "offer id", "Get my current offer with id");
stream.format(rowFormat, "getoffers", "buy | sell, currency code", "Get current offers");
stream.format(rowFormat, "getmyoffers", "buy | sell, currency code", "Get my current offers");
stream.format(rowFormat, "takeoffer", "offer id [,taker fee currency code = bsq|btc]", "Take offer with id");
stream.format(rowFormat, "gettrade", "trade id [,showcontract = true|false]", "Get trade summary or full contract");
stream.format(rowFormat, "confirmpaymentstarted", "trade id", "Confirm payment started");

View File

@ -108,10 +108,18 @@ public class CoreApi {
return coreOffersService.getOffer(id);
}
public Offer getMyOffer(String id) {
return coreOffersService.getMyOffer(id);
}
public List<Offer> getOffers(String direction, String currencyCode) {
return coreOffersService.getOffers(direction, currencyCode);
}
public List<Offer> getMyOffers(String direction, String currencyCode) {
return coreOffersService.getMyOffers(direction, currencyCode);
}
public void createAnPlaceOffer(String currencyCode,
String directionAsString,
String priceAsString,

View File

@ -27,6 +27,8 @@ import bisq.core.offer.OpenOfferManager;
import bisq.core.payment.PaymentAccount;
import bisq.core.user.User;
import bisq.common.crypto.KeyRing;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.utils.Fiat;
@ -38,6 +40,7 @@ import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
@ -49,10 +52,15 @@ import static bisq.core.locale.CurrencyUtil.isCryptoCurrency;
import static bisq.core.offer.OfferPayload.Direction;
import static bisq.core.offer.OfferPayload.Direction.BUY;
import static java.lang.String.format;
import static java.util.Comparator.comparing;
@Slf4j
class CoreOffersService {
private final Supplier<Comparator<Offer>> priceComparator = () -> comparing(Offer::getPrice);
private final Supplier<Comparator<Offer>> reversePriceComparator = () -> comparing(Offer::getPrice).reversed();
private final KeyRing keyRing;
private final CreateOfferService createOfferService;
private final OfferBookService offerBookService;
private final OpenOfferManager openOfferManager;
@ -60,11 +68,13 @@ class CoreOffersService {
private final User user;
@Inject
public CoreOffersService(CreateOfferService createOfferService,
public CoreOffersService(KeyRing keyRing,
CreateOfferService createOfferService,
OfferBookService offerBookService,
OpenOfferManager openOfferManager,
OfferUtil offerUtil,
User user) {
this.keyRing = keyRing;
this.createOfferService = createOfferService;
this.offerBookService = offerBookService;
this.openOfferManager = openOfferManager;
@ -79,24 +89,27 @@ class CoreOffersService {
new IllegalStateException(format("offer with id '%s' not found", id)));
}
Offer getMyOffer(String id) {
return offerBookService.getOffers().stream()
.filter(o -> o.getId().equals(id))
.filter(o -> o.isMyOffer(keyRing))
.findAny().orElseThrow(() ->
new IllegalStateException(format("offer with id '%s' not found", id)));
}
List<Offer> getOffers(String direction, String currencyCode) {
List<Offer> offers = offerBookService.getOffers().stream()
.filter(o -> {
var offerOfWantedDirection = o.getDirection().name().equalsIgnoreCase(direction);
var offerInWantedCurrency = o.getOfferPayload().getCounterCurrencyCode()
.equalsIgnoreCase(currencyCode);
return offerOfWantedDirection && offerInWantedCurrency;
})
return offerBookService.getOffers().stream()
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode))
.sorted(priceComparator(direction))
.collect(Collectors.toList());
}
// A buyer probably wants to see sell orders in price ascending order.
// A seller probably wants to see buy orders in price descending order.
if (direction.equalsIgnoreCase(BUY.name()))
offers.sort(Comparator.comparing(Offer::getPrice).reversed());
else
offers.sort(Comparator.comparing(Offer::getPrice));
return offers;
List<Offer> getMyOffers(String direction, String currencyCode) {
return offerBookService.getOffers().stream()
.filter(o -> o.isMyOffer(keyRing))
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode))
.sorted(priceComparator(direction))
.collect(Collectors.toList());
}
// Create and place new offer.
@ -194,6 +207,23 @@ class CoreOffersService {
throw new IllegalStateException(offer.getErrorMessage());
}
private boolean offerMatchesDirectionAndCurrency(Offer offer,
String direction,
String currencyCode) {
var offerOfWantedDirection = offer.getDirection().name().equalsIgnoreCase(direction);
var offerInWantedCurrency = offer.getOfferPayload().getCounterCurrencyCode()
.equalsIgnoreCase(currencyCode);
return offerOfWantedDirection && offerInWantedCurrency;
}
private Comparator<Offer> priceComparator(String direction) {
// A buyer probably wants to see sell orders in price ascending order.
// A seller probably wants to see buy orders in price descending order.
return direction.equalsIgnoreCase(BUY.name())
? reversePriceComparator.get()
: priceComparator.get();
}
private long priceStringToLong(String priceAsString, String currencyCode) {
int precision = isCryptoCurrency(currencyCode) ? Altcoin.SMALLEST_UNIT_EXPONENT : Fiat.SMALLEST_UNIT_EXPONENT;
double priceAsDouble = new BigDecimal(priceAsString).doubleValue();

View File

@ -25,6 +25,10 @@ import bisq.proto.grpc.CancelOfferReply;
import bisq.proto.grpc.CancelOfferRequest;
import bisq.proto.grpc.CreateOfferReply;
import bisq.proto.grpc.CreateOfferRequest;
import bisq.proto.grpc.GetMyOfferReply;
import bisq.proto.grpc.GetMyOfferRequest;
import bisq.proto.grpc.GetMyOffersReply;
import bisq.proto.grpc.GetMyOffersRequest;
import bisq.proto.grpc.GetOfferReply;
import bisq.proto.grpc.GetOfferRequest;
import bisq.proto.grpc.GetOffersReply;
@ -69,6 +73,21 @@ class GrpcOffersService extends OffersGrpc.OffersImplBase {
}
}
@Override
public void getMyOffer(GetMyOfferRequest req,
StreamObserver<GetMyOfferReply> responseObserver) {
try {
Offer offer = coreApi.getMyOffer(req.getId());
var reply = GetMyOfferReply.newBuilder()
.setOffer(toOfferInfo(offer).toProtoMessage())
.build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
} catch (Throwable cause) {
exceptionHandler.handleException(cause, responseObserver);
}
}
@Override
public void getOffers(GetOffersRequest req,
StreamObserver<GetOffersReply> responseObserver) {
@ -88,6 +107,25 @@ class GrpcOffersService extends OffersGrpc.OffersImplBase {
}
}
@Override
public void getMyOffers(GetMyOffersRequest req,
StreamObserver<GetMyOffersReply> responseObserver) {
try {
List<OfferInfo> result = coreApi.getMyOffers(req.getDirection(), req.getCurrencyCode())
.stream().map(OfferInfo::toOfferInfo)
.collect(Collectors.toList());
var reply = GetMyOffersReply.newBuilder()
.addAllOffers(result.stream()
.map(OfferInfo::toProtoMessage)
.collect(Collectors.toList()))
.build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
} catch (Throwable cause) {
exceptionHandler.handleException(cause, responseObserver);
}
}
@Override
public void createOffer(CreateOfferRequest req,
StreamObserver<CreateOfferReply> responseObserver) {

View File

@ -47,8 +47,12 @@ message RegisterDisputeAgentReply {
service Offers {
rpc GetOffer (GetOfferRequest) returns (GetOfferReply) {
}
rpc GetMyOffer (GetMyOfferRequest) returns (GetMyOfferReply) {
}
rpc GetOffers (GetOffersRequest) returns (GetOffersReply) {
}
rpc GetMyOffers (GetMyOffersRequest) returns (GetMyOffersReply) {
}
rpc CreateOffer (CreateOfferRequest) returns (CreateOfferReply) {
}
rpc CancelOffer (CancelOfferRequest) returns (CancelOfferReply) {
@ -62,6 +66,15 @@ message GetOfferRequest {
message GetOfferReply {
OfferInfo offer = 1;
}
message GetMyOfferRequest {
string id = 1;
}
message GetMyOfferReply {
OfferInfo offer = 1;
}
message GetOffersRequest {
string direction = 1;
string currencyCode = 2;
@ -71,6 +84,15 @@ message GetOffersReply {
repeated OfferInfo offers = 1;
}
message GetMyOffersRequest {
string direction = 1;
string currencyCode = 2;
}
message GetMyOffersReply {
repeated OfferInfo offers = 1;
}
message CreateOfferRequest {
string currencyCode = 1;
string direction = 2;