Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bsq swap 2 #8

Closed
wants to merge 47 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
da4afc9
Refactor direct offerPayload access
sqrrm Feb 20, 2021
768ecf3
Refactor direct offerPayload access
sqrrm Feb 20, 2021
254e4f9
Add OfferPayloadI
sqrrm Feb 20, 2021
5b7d877
Add AtomicOfferPayload
sqrrm Feb 21, 2021
dc9f253
Refactor: move OfferPayload Direction protobuf methods
sqrrm Feb 22, 2021
984d385
Add atomic account type
sqrrm Aug 17, 2020
e0ddba6
Add UI for creating atomic offers
sqrrm Jan 27, 2021
5913e83
Add UI for taking atomic offers
sqrrm Mar 1, 2021
4f1a157
Refactor: TradeManager handle Tradable
sqrrm Mar 23, 2021
c962ae9
Refactor: add class tradeModel
sqrrm Mar 29, 2021
90e5357
Introduce interface ProcessModelI
sqrrm Apr 1, 2021
b0bfd18
Compiling old atomic trade protocol
sqrrm Apr 9, 2021
05c16a0
Refactor: TradeManager use TradeModel
sqrrm Apr 9, 2021
7884c58
Refactor: extract applyFilter method
sqrrm Apr 11, 2021
4bd8c0f
Add AtomicApplyFilter
sqrrm Apr 11, 2021
316bd8f
TradeTaskRunner handle AtomicTrade
sqrrm Apr 13, 2021
ad521c2
Refactor: move AtomicApplyFilter
sqrrm Apr 13, 2021
44eae7a
Take atomic offer
sqrrm Apr 13, 2021
844c059
Refactor: rename txFee -> txFeePerVbyte
sqrrm Apr 15, 2021
f30befe
Add atomic trade protocol
sqrrm Apr 28, 2021
28a332d
Set maker fee type in offer
sqrrm Apr 29, 2021
be7b1d5
Display Atomic Trade info in transaction lists
sqrrm Apr 30, 2021
0bb810f
Refactor: extract AtomicTakeOfferModel to core
sqrrm May 3, 2021
70559e5
Add ProofOfWorkPayload interface
sqrrm May 3, 2021
a6ff38c
Add ProofOfWorkPayload filter
sqrrm May 5, 2021
37aec56
Remove Arbitrator/Mediator requirement for atomic trades
sqrrm May 6, 2021
1b264f9
Add atomic offer/trade grpc proto defs
ghubstan May 7, 2021
5d22be7
Add grpc boilerplate for atomic offer/trade support
ghubstan May 7, 2021
7e88ee5
Add atomic offer/trade proto wrappers
ghubstan May 7, 2021
7dcbbe2
Add Optional<AtomicTrade> getAtomicTradeById(String tradeId)
ghubstan May 7, 2021
3038c8a
Add @Getter annotation to private AtomicTxBuilder atomicTxBuilder
ghubstan May 7, 2021
f6bb5bf
Add boolean isAtomicOffer() convenience
ghubstan May 7, 2021
2205925
Implement core api's atomic offer/trade support
ghubstan May 7, 2021
4ba04a3
Support atomic payment method
ghubstan May 7, 2021
c433745
Add atomic offer/trade tests
ghubstan May 7, 2021
e44d855
Use segwit validator for BSQ output address
sqrrm Jun 5, 2021
e58e017
Extract fee handling from AtomicTxBuilder
sqrrm Jun 5, 2021
269d4e3
Core: remove BTC trade fee option for atomic trades
sqrrm Jun 10, 2021
813e70b
Desktop: remove trade fee option from UI
sqrrm Jun 10, 2021
1aaa91a
Refactor: OpenOfferManager centralize add/remove
sqrrm Jun 13, 2021
d5e364a
Atomic funding
sqrrm Sep 22, 2021
7c04a92
AtomicOfferPayload: add hash
sqrrm Sep 27, 2021
403b1d2
bitcoinj: update to better multi wallet handling
sqrrm Sep 27, 2021
b7c0c26
Rename OfferPayloadI to OfferPayloadBase
chimp1984 Sep 29, 2021
2524b75
Fix var names ans strings using offerPayloadI
chimp1984 Sep 29, 2021
2d3cc2e
Add BSQ_SWAP_OFFER capability
chimp1984 Sep 29, 2021
bc74134
Rename noCapabilityRequiredOrCapabilityIsSupported to testCapability
chimp1984 Sep 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions apitest/src/test/java/bisq/apitest/ApiTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package bisq.apitest;

import java.time.Duration;

import java.io.IOException;

import java.util.concurrent.ExecutionException;
Expand All @@ -32,9 +34,9 @@
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static bisq.apitest.config.BisqAppConfig.arbdaemon;
import static bisq.apitest.config.BisqAppConfig.bobdaemon;
import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
import static java.net.InetAddress.getLoopbackAddress;
import static java.util.Arrays.stream;
import static java.util.concurrent.TimeUnit.MILLISECONDS;



Expand Down Expand Up @@ -131,11 +133,7 @@ protected static void genBtcBlocksThenWait(int numBlocks, long wait) {
}

protected static void sleep(long ms) {
try {
MILLISECONDS.sleep(ms);
} catch (InterruptedException ignored) {
// empty
}
sleepUninterruptibly(Duration.ofMillis(ms));
}

protected final String testName(TestInfo testInfo) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ public static void setUp() {
bobdaemon);
}

public static void createAtomicBsqPaymentAccounts() {
alicesBsqAcct = aliceClient.createCryptoCurrencyPaymentAccount("Alice's Atomic Account",
BSQ,
aliceClient.getUnusedBsqAddress(), // TODO refactor, bsq address not needed for atom acct
false);
bobsBsqAcct = bobClient.createCryptoCurrencyPaymentAccount("Bob's Atomic Account",
BSQ,
bobClient.getUnusedBsqAddress(), // TODO refactor, bsq address not needed for atom acct
false);
}

// Mkt Price Margin value of offer returned from server is scaled down by 10^-2.
protected final Function<Double, Double> scaledDownMktPriceMargin = (mktPriceMargin) ->
Expand Down
172 changes: 172 additions & 0 deletions apitest/src/test/java/bisq/apitest/method/offer/AtomicOfferTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.apitest.method.offer;

import bisq.proto.grpc.AtomicOfferInfo;

import lombok.extern.slf4j.Slf4j;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import static bisq.apitest.config.ApiTestConfig.BSQ;
import static bisq.apitest.config.ApiTestConfig.BTC;
import static bisq.cli.TableFormat.formatBalancesTbls;
import static java.lang.String.format;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static protobuf.OfferPayload.Direction.BUY;

// @Disabled
@Slf4j
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AtomicOfferTest extends AbstractOfferTest {

@BeforeAll
public static void setUp() {
AbstractOfferTest.setUp();
createAtomicBsqPaymentAccounts();
}

@BeforeEach
public void generateBtcBlock() {
genBtcBlocksThenWait(1, 2000);
}

@Test
@Order(1)
public void testGetBalancesBeforeCreateOffers() {
var alicesBalances = aliceClient.getBalances();
log.info("Alice's Before Trade Balance:\n{}", formatBalancesTbls(alicesBalances));
var bobsBalances = bobClient.getBalances();
log.info("Bob's Before Trade Balance:\n{}", formatBalancesTbls(bobsBalances));
}

@Test
@Order(2)
public void testAliceCreateAtomicBuyOffer1() {
createAtomicOffer();
}

@Test
@Order(3)
public void testAliceCreateAtomicBuyOffer2() {
createAtomicOffer();
}

@Test
@Order(4)
public void testAliceCreateAtomicBuyOffer3() {
createAtomicOffer();
}

@Test
@Order(5)
public void testAliceCreateAtomicBuyOffer4() {
createAtomicOffer();
}

private void createAtomicOffer() {
var atomicOffer = aliceClient.createAtomicOffer(BUY.name(),
100_000_000L,
100_000_000L,
"0.00005",
alicesBsqAcct.getId());
log.info("Atomic Sell BSQ (Buy BTC) OFFER:\n{}", atomicOffer);
var newOfferId = atomicOffer.getId();
assertNotEquals("", newOfferId);
assertEquals(BUY.name(), atomicOffer.getDirection());
assertEquals(5_000, atomicOffer.getPrice());
assertEquals(100_000_000L, atomicOffer.getAmount());
assertEquals(100_000_000L, atomicOffer.getMinAmount());
// assertEquals(alicesBsqAcct.getId(), atomicOffer.getMakerPaymentAccountId());
assertEquals(BSQ, atomicOffer.getBaseCurrencyCode());
assertEquals(BTC, atomicOffer.getCounterCurrencyCode());

testGetMyAtomicOffer(atomicOffer);
testGetAtomicOffer(atomicOffer);
}

private void testGetMyAtomicOffer(AtomicOfferInfo atomicOffer) {
int numFetchAttempts = 0;
while (true) {
try {
numFetchAttempts++;
var fetchedAtomicOffer = aliceClient.getMyAtomicOffer(atomicOffer.getId());
assertEquals(atomicOffer.getId(), fetchedAtomicOffer.getId());
log.info("Alice found her (my) new atomic offer on attempt # {}.", numFetchAttempts);
break;
} catch (Exception ex) {
log.warn(ex.getMessage());

if (numFetchAttempts >= 9)
fail(format("Alice giving up on fetching her (my) atomic offer after %d attempts.", numFetchAttempts), ex);

sleep(1000);
}
}
}

private void testGetAtomicOffer(AtomicOfferInfo atomicOffer) {
int numFetchAttempts = 0;
while (true) {
try {
numFetchAttempts++;
var fetchedAtomicOffer = bobClient.getAtomicOffer(atomicOffer.getId());
assertEquals(atomicOffer.getId(), fetchedAtomicOffer.getId());
log.info("Bob found new available atomic offer on attempt # {}.", numFetchAttempts);
break;
} catch (Exception ex) {
log.warn(ex.getMessage());

if (numFetchAttempts > 9)
fail(format("Bob gave up on fetching available atomic offer after %d attempts.", numFetchAttempts), ex);

sleep(1000);
}
}
}

@Test
@Order(6)
public void testGetMyAtomicOffers() {
var offers = aliceClient.getMyAtomicBsqOffersSortedByDate();
assertEquals(4, offers.size());
}

@Test
@Order(7)
public void testGetAvailableAtomicOffers() {
var offers = bobClient.getAtomicOffersSortedByDate();
assertEquals(4, offers.size());
}

@Test
@Order(8)
public void testGetBalancesAfterCreateOffers() {
var alicesBalances = aliceClient.getBalances();
log.info("Alice's After Trade Balance:\n{}", formatBalancesTbls(alicesBalances));
var bobsBalances = bobClient.getBalances();
log.info("Bob's After Trade Balance:\n{}", formatBalancesTbls(bobsBalances));
}
}
163 changes: 163 additions & 0 deletions apitest/src/test/java/bisq/apitest/method/trade/AtomicTradeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.apitest.method.trade;

import bisq.proto.grpc.AtomicOfferInfo;
import bisq.proto.grpc.AtomicTradeInfo;

import protobuf.AtomicTrade;

import java.util.ArrayList;
import java.util.List;

import lombok.extern.slf4j.Slf4j;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import static bisq.apitest.config.ApiTestConfig.BSQ;
import static bisq.apitest.config.ApiTestConfig.BTC;
import static bisq.cli.TableFormat.formatBalancesTbls;
import static java.lang.String.format;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static protobuf.OfferPayload.Direction.BUY;



import bisq.apitest.method.offer.AbstractOfferTest;

// @Disabled
@Slf4j
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AtomicTradeTest extends AbstractOfferTest {

private static final String BISQ_FEE_CURRENCY_CODE = BSQ;

@BeforeAll
public static void setUp() {
AbstractOfferTest.setUp();
createAtomicBsqPaymentAccounts();
}

@BeforeEach
public void generateBtcBlock() {
genBtcBlocksThenWait(1, 2000);
}

@Test
@Order(1)
public void testGetBalancesBeforeTrade() {
var alicesBalances = aliceClient.getBalances();
log.info("Alice's Before Trade Balance:\n{}", formatBalancesTbls(alicesBalances));
var bobsBalances = bobClient.getBalances();
log.info("Bob's Before Trade Balance:\n{}", formatBalancesTbls(bobsBalances));
}

@Test
@Order(2)
public void testAliceCreateAtomicBuyOffer() {
var atomicOffer = aliceClient.createAtomicOffer(BUY.name(),
100_000_000L,
100_000_000L,
"0.00005",
alicesBsqAcct.getId());
log.info("Atomic Sell BSQ (Buy BTC) OFFER:\n{}", atomicOffer);
var newOfferId = atomicOffer.getId();
assertNotEquals("", newOfferId);
assertEquals(BUY.name(), atomicOffer.getDirection());
assertEquals(5_000, atomicOffer.getPrice());
assertEquals(100_000_000L, atomicOffer.getAmount());
assertEquals(100_000_000L, atomicOffer.getMinAmount());
// assertEquals(alicesBsqAcct.getId(), atomicOffer.getMakerPaymentAccountId());
assertEquals(BSQ, atomicOffer.getBaseCurrencyCode());
assertEquals(BTC, atomicOffer.getCounterCurrencyCode());
}

@Test
@Order(3)
public void testBobTakesAtomicOffer() {
var atomicOffer = getAvailableAtomicOffer();

var atomicTrade = bobClient.takeAtomicOffer(atomicOffer.getId(),
bobsBsqAcct.getId(),
BISQ_FEE_CURRENCY_CODE);
log.info("Trade at t1: {}", atomicTrade);
assertEquals(AtomicTrade.State.PREPARATION.name(), atomicTrade.getState());
genBtcBlocksThenWait(1, 3000);

atomicTrade = getAtomicTrade(atomicTrade.getTradeId());
log.info("Trade at t2: {}", atomicTrade);
assertEquals(AtomicTrade.State.TX_CONFIRMED.name(), atomicTrade.getState());
}

@Test
@Order(4)
public void testGetBalancesAfterTrade() {
var alicesBalances = aliceClient.getBalances();
log.info("Alice's After Trade Balance:\n{}", formatBalancesTbls(alicesBalances));
var bobsBalances = bobClient.getBalances();
log.info("Bob's After Trade Balance:\n{}", formatBalancesTbls(bobsBalances));
}

private AtomicOfferInfo getAvailableAtomicOffer() {
List<AtomicOfferInfo> atomicOffers = new ArrayList<>();
int numFetchAttempts = 0;
while (atomicOffers.size() == 0) {
atomicOffers.addAll(bobClient.getAtomicOffers(BUY.name(), "BSQ"));
numFetchAttempts++;
if (atomicOffers.size() == 0) {
log.warn("No available atomic offer found after {} fetch attempts.", numFetchAttempts);
if (numFetchAttempts > 9) {
fail(format("Bob gave up on fetching available atomic offer after %d attempts.", numFetchAttempts));
}
sleep(1000);
} else {
assertEquals(1, atomicOffers.size());
log.info("Bob found new available atomic offer on attempt # {}.", numFetchAttempts);
break;
}
}
// Test api's getAtomicOffer(id).
var atomicOffer = bobClient.getAtomicOffer(atomicOffers.get(0).getId());
assertEquals(atomicOffers.get(0).getId(), atomicOffer.getId());
return atomicOffer;
}

private AtomicTradeInfo getAtomicTrade(String tradeId) {
int numFetchAttempts = 0;
while (true) {
try {
numFetchAttempts++;
return bobClient.getAtomicTrade(tradeId);
} catch (Exception ex) {
log.warn(ex.getMessage());
if (numFetchAttempts > 9) {
fail(format("Could not find new atomic trade after %d attempts.", numFetchAttempts));
} else {
sleep(1000);
}
}
}
}
}
Loading