Skip to content

Commit

Permalink
Merge pull request bisq-network#5893 from ghubstan/6-api-xmr-trading
Browse files Browse the repository at this point in the history
API XMR/BTC trading pair support (#6)
  • Loading branch information
ripcurlx committed Dec 29, 2021
2 parents 963b966 + 705e34e commit d5dc836
Show file tree
Hide file tree
Showing 35 changed files with 1,756 additions and 186 deletions.
45 changes: 45 additions & 0 deletions apitest/scripts/trade-simulation-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,51 @@ parsebsqswaporderopts() {
export CURRENCY_CODE="BSQ"
}

parsexmrscriptopts() {
usage() {
echo "Usage: $0 [-d buy|sell] [-f <fixed-price> || -m <margin-from-price>] [-a <amount in btc>]" 1>&2
exit 1;
}

local OPTIND o d f m a
while getopts "d:f:m:a:" o; do
case "${o}" in
d) d=$(echo "${OPTARG}" | tr '[:lower:]' '[:upper:]')
((d == "BUY" || d == "SELL")) || usage
export DIRECTION=${d}
;;
f) f=${OPTARG}
export FIXED_PRICE=${f}
;;
m) m=${OPTARG}
export MKT_PRICE_MARGIN=${m}
;;
a) a=${OPTARG}
export AMOUNT=${a}
;;
*) usage ;;
esac
done
shift $((OPTIND-1))

if [ -z "${d}" ] || [ -z "${a}" ]; then
usage
fi

if [ -z "${f}" ] && [ -z "${m}" ]; then
usage
fi

if [ "$DIRECTION" = "SELL" ]
then
export BOB_ROLE="(taker/buyer)"
export ALICE_ROLE="(maker/seller)"
else
export BOB_ROLE="(taker/seller)"
export ALICE_ROLE="(maker/buyer)"
fi
}

checkbitcoindrunning() {
# There may be a '+' char in the path and we have to escape it for pgrep.
if [[ $APP_HOME == *"+"* ]]; then
Expand Down
10 changes: 5 additions & 5 deletions apitest/scripts/trade-simulation-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ waitfortradepaymentsent() {

IS_TRADE_PAYMENT_SENT=$(istradepaymentsent "$TRADE_DETAIL")
exitoncommandalert $?
printdate "$SELLER: Has buyer's fiat payment been initiated? $IS_TRADE_PAYMENT_SENT"
printdate "$SELLER: Has buyer's payment been initiated? $IS_TRADE_PAYMENT_SENT"
if [ "$IS_TRADE_PAYMENT_SENT" = "YES" ]
then
DONE=1
Expand Down Expand Up @@ -407,7 +407,7 @@ waitfortradepaymentreceived() {
# but we do not need to simulate that in this regtest script.
IS_TRADE_PAYMENT_SENT=$(istradepaymentreceived "$TRADE_DETAIL")
exitoncommandalert $?
printdate "$SELLER: Has buyer's payment been transferred to seller's fiat account? $IS_TRADE_PAYMENT_SENT"
printdate "$SELLER: Has buyer's payment been transferred to seller's account? $IS_TRADE_PAYMENT_SENT"
if [ "$IS_TRADE_PAYMENT_SENT" = "YES" ]
then
DONE=1
Expand All @@ -427,7 +427,7 @@ delayconfirmpaymentstarted() {
PORT="$2"
OFFER_ID="$3"
RANDOM_WAIT=$(echo $[$RANDOM % 5 + 1])
printdate "$PAYER: Sending fiat payment sent message to seller in $RANDOM_WAIT seconds..."
printdate "$PAYER: Sending 'payment sent' message to seller in $RANDOM_WAIT seconds..."
sleeptraced "$RANDOM_WAIT"
CMD="$CLI_BASE --port=$PORT confirmpaymentstarted --trade-id=$OFFER_ID"
printdate "$PAYER_CLI: $CMD"
Expand All @@ -446,7 +446,7 @@ delayconfirmpaymentreceived() {
PORT="$2"
OFFER_ID="$3"
RANDOM_WAIT=$(echo $[$RANDOM % 5 + 1])
printdate "$PAYEE: Sending fiat payment sent message to seller in $RANDOM_WAIT seconds..."
printdate "$PAYEE: Sending 'payment sent' message to seller in $RANDOM_WAIT seconds..."
sleeptraced "$RANDOM_WAIT"
CMD="$CLI_BASE --port=$PORT confirmpaymentreceived --trade-id=$OFFER_ID"
printdate "$PAYEE_CLI: $CMD"
Expand Down Expand Up @@ -531,7 +531,7 @@ executetrade() {
fi

# Generate some btc blocks
printdate "Generating btc blocks after fiat transfer."
printdate "Generating btc blocks after payment."
genbtcblocks 2 2
printbreak

Expand Down
122 changes: 122 additions & 0 deletions apitest/scripts/trade-xmr-simulation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#! /bin/bash

# Runs xmr <-> btc trading scenarios using the API CLI with a local regtest bitcoin node.
#
# Prerequisites:
#
# - Linux or OSX with bash, Java 11-15 (JDK language compatibility 11), and bitcoin-core (v0.19 - v22).
#
# - Bisq must be fully built with apitest dao setup files installed.
# Build command: `./gradlew clean build :apitest:installDaoSetup`
#
# - All supporting nodes must be run locally, in dev/dao/regtest mode:
# bitcoind, seednode, arbdaemon, alicedaemon, bobdaemon
#
# These should be run using the apitest harness. From the root project dir, run:
# `$ ./bisq-apitest --apiPassword=xyz --supportingApps=bitcoind,seednode,arbdaemon,alicedaemon,bobdaemon --shutdownAfterTests=false`
#
# Usage:
#
# This script must be run from the root of the project, e.g.:
#
# `$ apitest/scripts/trade-xmr-simulation.sh -d buy -f 0.05 -a 0.125`
#
# Script options: -d <direction> -m <mkt-price-margin(%)> -f <fixed-price> -a <amount(btc)>
#
# Examples:
#
# Create a buy/xmr offer to buy 0.125 btc at an xmr fixed-price of 0.05 btc, using an xmr payment account:
#
# `$ apitest/scripts/trade-xmr-simulation.sh -d buy -f 0.05 -a 0.125`
#
# Create a sell/xmr offer to sell 0.125 btc at at an xmr mkt-price-margin of 0%, using using an xmr payment account:
#
# `$ apitest/scripts/trade-xmr-simulation.sh -d sell -m 0.00 -a 0.125`

export APP_BASE_NAME=$(basename "$0")
export APP_HOME=$(pwd -P)
export APITEST_SCRIPTS_HOME="$APP_HOME/apitest/scripts"
export CURRENCY_CODE="XMR"
export ALICE_XMR_ADDRESS="44i8xZbd8ecaD6nQQrHjr1BwTp6QfGL22iWqHZKmU4QYSyr1F64XAxM4HgvQHxbny7ehfxemaA9LPDLz2wY3fxhB1bbMEco"
export BOB_XMR_ADDRESS="48xdBkXaCosPxcWwXRZdSGc33M9tYu6k9ga56dqkNrgsjQuJX16xW2qTyWTZstJpXXj87dj5p4H3y1xAfoVjAysoAYrXh2N"

source "$APITEST_SCRIPTS_HOME/trade-simulation-env.sh"
source "$APITEST_SCRIPTS_HOME/trade-simulation-utils.sh"

checksetup
parsexmrscriptopts "$@"

printdate "Started $APP_BASE_NAME with parameters:"
printscriptparams
printbreak

registerdisputeagents

# Demonstrate how to create an XMR altcoin payment account.

printdate "Create Alice's XMR Trading Payment Account."
# Note: Having problems passing a double quoted --account-name param to function.
CMD="$CLI_BASE --port=$ALICE_PORT createcryptopaymentacct --account-name=Alice_XMR_Account"
CMD+=" --currency-code=XMR --address=$ALICE_XMR_ADDRESS --trade-instant=false"
printdate "ALICE CLI: $CMD"
CMD_OUTPUT=$(createpaymentacct "$CMD")
echo "$CMD_OUTPUT"
printbreak
export ALICE_ACCT_ID=$(getnewpaymentacctid "$CMD_OUTPUT")
printdate "Alice's XMR payment-account-id: $ALICE_ACCT_ID"
exitoncommandalert $?
printbreak

printdate "Create Bob's XMR Trading Payment Account."
# Note: Having problems passing a double quoted --account-name param to function.
CMD="$CLI_BASE --port=$BOB_PORT createcryptopaymentacct --account-name=Bob_XMR_Account"
CMD+=" --currency-code=XMR --address=$BOB_XMR_ADDRESS --trade-instant=false"
printdate "BOB CLI: $CMD"
CMD_OUTPUT=$(createpaymentacct "$CMD")
echo "$CMD_OUTPUT"
printbreak
export BOB_ACCT_ID=$(getnewpaymentacctid "$CMD_OUTPUT")
printdate "Bob's XMR payment-account-id: $BOB_ACCT_ID"
exitoncommandalert $?
printbreak

# Alice creates an offer.
printdate "ALICE $ALICE_ROLE: Creating $DIRECTION $CURRENCY_CODE offer with payment acct $ALICE_ACCT_ID."
CMD=$(gencreateoffercommand "$ALICE_PORT" "$ALICE_ACCT_ID")
printdate "ALICE CLI: $CMD"
OFFER_ID=$(createoffer "$CMD")
exitoncommandalert $?
printdate "ALICE $ALICE_ROLE: Created offer with id: $OFFER_ID."
printbreak
sleeptraced 3

# Show Alice's new offer.
printdate "ALICE $ALICE_ROLE: Looking at her new $DIRECTION $CURRENCY_CODE offer."
CMD="$CLI_BASE --port=$ALICE_PORT getmyoffer --offer-id=$OFFER_ID"
printdate "ALICE CLI: $CMD"
OFFER=$($CMD)
exitoncommandalert $?
echo "$OFFER"
printbreak
sleeptraced 3

# Generate some btc blocks.
printdate "Generating btc blocks after publishing Alice's offer."
genbtcblocks 3 1
printbreak

# Go through the trade protocol.
executetrade
exitoncommandalert $?
printbreak

# Get balances after trade completion.
printdate "Bob & Alice's balances after trade:"
printdate "ALICE CLI:"
printbalances "$ALICE_PORT"
printbreak
printdate "BOB CLI:"
printbalances "$BOB_PORT"
printbreak

exit 0
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind;
import static bisq.apitest.config.ApiTestConfig.BSQ;
import static bisq.apitest.config.ApiTestConfig.XMR;
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static bisq.apitest.config.BisqAppConfig.arbdaemon;
import static bisq.apitest.config.BisqAppConfig.bobdaemon;
Expand Down Expand Up @@ -65,6 +66,9 @@ public abstract class AbstractOfferTest extends MethodTest {
protected static PaymentAccount alicesLegacyBsqAcct;
protected static PaymentAccount bobsLegacyBsqAcct;

protected static PaymentAccount alicesXmrAcct;
protected static PaymentAccount bobsXmrAcct;

@BeforeAll
public static void setUp() {
startSupportingApps(true,
Expand Down Expand Up @@ -96,11 +100,16 @@ public static void setUp() {
return priceAsBigDecimal.multiply(factor).longValue();
};

protected final BiFunction<Double, Double, Long> calcPriceAsLong = (base, delta) -> {
protected final BiFunction<Double, Double, Long> calcFiatTriggerPriceAsLong = (base, delta) -> {
var priceAsDouble = new BigDecimal(base).add(new BigDecimal(delta)).doubleValue();
return Double.valueOf(exactMultiply(priceAsDouble, 10_000)).longValue();
};

protected final BiFunction<Double, Double, Long> calcAltcoinTriggerPriceAsLong = (base, delta) -> {
var priceAsDouble = new BigDecimal(base).add(new BigDecimal(delta)).doubleValue();
return Double.valueOf(exactMultiply(priceAsDouble, 100_000_000)).longValue();
};

protected final BiFunction<Double, Double, String> calcPriceAsString = (base, delta) -> {
var priceAsBigDecimal = new BigDecimal(Double.toString(base))
.add(new BigDecimal(Double.toString(delta)));
Expand All @@ -113,6 +122,7 @@ public static void setUp() {
protected final Function<List<OfferInfo>, String> toOffersTable = (offers) ->
new TableBuilder(OFFER_TBL, offers).build().toString();

@SuppressWarnings("ConstantConditions")
public static void initSwapPaymentAccounts() {
// A bot may not know what the default 'BSQ Swap' account name is,
// but API test cases do: the value of the i18n property 'BSQ_SWAP'.
Expand All @@ -132,6 +142,20 @@ public static void createLegacyBsqPaymentAccounts() {
false);
}

@SuppressWarnings("ConstantConditions")
public static void createXmrPaymentAccounts() {
alicesXmrAcct = aliceClient.createCryptoCurrencyPaymentAccount("Alice's XMR Account",
XMR,
"44G4jWmSvTEfifSUZzTDnJVLPvYATmq9XhhtDqUof1BGCLceG82EQsVYG9Q9GN4bJcjbAJEc1JD1m5G7iK4UPZqACubV4Mq",
false);
log.debug("Alices XMR Account: {}", alicesXmrAcct);
bobsXmrAcct = bobClient.createCryptoCurrencyPaymentAccount("Bob's XMR Account",
XMR,
"4BDRhdSBKZqAXs3PuNTbMtaXBNqFj5idC2yMVnQj8Rm61AyKY8AxLTt9vGRJ8pwcG4EtpyD8YpGqdZWCZ2VZj6yVBN2RVKs",
false);
log.debug("Bob's XMR Account: {}", bobsXmrAcct);
}

@AfterAll
public static void tearDown() {
tearDownScaffold();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public void testCreateSellBTCFor5To10KBSQOffer() {
@Test
@Order(5)
public void testGetAllMyBsqOffers() {
List<OfferInfo> offers = aliceClient.getMyBsqOffersSortedByDate();
List<OfferInfo> offers = aliceClient.getMyCryptoCurrencyOffersSortedByDate(BSQ);
log.debug("ALL ALICE'S BSQ OFFERS:\n{}", toOffersTable.apply(offers));
assertEquals(4, offers.size());
log.debug("ALICE'S BALANCES\n{}", formatBalancesTbls(aliceClient.getBalances()));
Expand All @@ -254,7 +254,7 @@ public void testGetAllMyBsqOffers() {
@Test
@Order(6)
public void testGetAvailableBsqOffers() {
List<OfferInfo> offers = bobClient.getBsqOffersSortedByDate();
List<OfferInfo> offers = bobClient.getCryptoCurrencyOffersSortedByDate(BSQ);
log.debug("ALL BOB'S AVAILABLE BSQ OFFERS:\n{}", toOffersTable.apply(offers));
assertEquals(4, offers.size());
log.debug("BOB'S BALANCES\n{}", formatBalancesTbls(bobClient.getBalances()));
Expand Down
Loading

0 comments on commit d5dc836

Please sign in to comment.