Search in sources :

Example 41 with Offer

use of bisq.core.offer.Offer in project bisq-core by bisq-network.

the class CreateMakerFeeTx method run.

@Override
protected void run() {
    Offer offer = model.getOffer();
    try {
        runInterceptHook();
        String id = offer.getId();
        BtcWalletService walletService = model.getWalletService();
        NodeAddress selectedArbitratorNodeAddress = ArbitratorSelectionRule.select(model.getUser().getAcceptedArbitratorAddresses(), model.getOffer());
        log.debug("selectedArbitratorAddress " + selectedArbitratorNodeAddress);
        Arbitrator selectedArbitrator = model.getUser().getAcceptedArbitratorByAddress(selectedArbitratorNodeAddress);
        checkNotNull(selectedArbitrator, "selectedArbitrator must not be null at CreateOfferFeeTx");
        Address fundingAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.OFFER_FUNDING).getAddress();
        Address reservedForTradeAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
        Address changeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
        final TradeWalletService tradeWalletService = model.getTradeWalletService();
        if (offer.isCurrencyForMakerFeeBtc()) {
            tradeFeeTx = tradeWalletService.createBtcTradingFeeTx(fundingAddress, reservedForTradeAddress, changeAddress, model.getReservedFundsForOffer(), model.isUseSavingsWallet(), offer.getMakerFee(), offer.getTxFee(), selectedArbitrator.getBtcAddress(), new FutureCallback<Transaction>() {

                @Override
                public void onSuccess(Transaction transaction) {
                    // we delay one render frame to be sure we don't get called before the method call has
                    // returned (tradeFeeTx would be null in that case)
                    UserThread.execute(() -> {
                        if (!completed) {
                            offer.setOfferFeePaymentTxId(transaction.getHashAsString());
                            model.setTransaction(transaction);
                            walletService.swapTradeEntryToAvailableEntry(id, AddressEntry.Context.OFFER_FUNDING);
                            model.getOffer().setState(Offer.State.OFFER_FEE_PAID);
                            complete();
                        } else {
                            log.warn("We got the onSuccess callback called after the timeout has been triggered a complete().");
                        }
                    });
                }

                @Override
                public void onFailure(@NotNull Throwable t) {
                    if (!completed) {
                        failed(t);
                    } else {
                        log.warn("We got the onFailure callback called after the timeout has been triggered a complete().");
                    }
                }
            });
        } else {
            final BsqWalletService bsqWalletService = model.getBsqWalletService();
            Transaction preparedBurnFeeTx = model.getBsqWalletService().getPreparedBurnFeeTx(offer.getMakerFee());
            Transaction txWithBsqFee = tradeWalletService.completeBsqTradingFeeTx(preparedBurnFeeTx, fundingAddress, reservedForTradeAddress, changeAddress, model.getReservedFundsForOffer(), model.isUseSavingsWallet(), offer.getTxFee());
            Transaction signedTx = model.getBsqWalletService().signTx(txWithBsqFee);
            WalletService.checkAllScriptSignaturesForTx(signedTx);
            bsqWalletService.commitTx(signedTx);
            // We need to create another instance, otherwise the tx would trigger an invalid state exception
            // if it gets committed 2 times
            tradeWalletService.commitTx(tradeWalletService.getClonedTransaction(signedTx));
            bsqWalletService.broadcastTx(signedTx, new FutureCallback<Transaction>() {

                @Override
                public void onSuccess(@Nullable Transaction transaction) {
                    if (transaction != null) {
                        offer.setOfferFeePaymentTxId(transaction.getHashAsString());
                        model.setTransaction(transaction);
                        log.debug("onSuccess, offerId={}, OFFER_FUNDING", id);
                        walletService.swapTradeEntryToAvailableEntry(id, AddressEntry.Context.OFFER_FUNDING);
                        log.debug("Successfully sent tx with id " + transaction.getHashAsString());
                        model.getOffer().setState(Offer.State.OFFER_FEE_PAID);
                        complete();
                    }
                }

                @Override
                public void onFailure(@NotNull Throwable t) {
                    log.error(t.toString());
                    t.printStackTrace();
                    offer.setErrorMessage("An error occurred.\n" + "Error message:\n" + t.getMessage());
                    failed(t);
                }
            });
        }
    } catch (Throwable t) {
        offer.setErrorMessage("An error occurred.\n" + "Error message:\n" + t.getMessage());
        failed(t);
    }
}
Also used : NodeAddress(bisq.network.p2p.NodeAddress) Address(org.bitcoinj.core.Address) TradeWalletService(bisq.core.btc.wallet.TradeWalletService) Arbitrator(bisq.core.arbitration.Arbitrator) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) NotNull(org.jetbrains.annotations.NotNull) Transaction(org.bitcoinj.core.Transaction) Offer(bisq.core.offer.Offer) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) BsqWalletService(bisq.core.btc.wallet.BsqWalletService) NodeAddress(bisq.network.p2p.NodeAddress) FutureCallback(com.google.common.util.concurrent.FutureCallback)

Example 42 with Offer

use of bisq.core.offer.Offer in project bisq-core by bisq-network.

the class ValidateOffer method run.

@Override
protected void run() {
    Offer offer = model.getOffer();
    try {
        runInterceptHook();
        // Coins
        checkCoinNotNullOrZero(offer.getAmount(), "Amount");
        checkCoinNotNullOrZero(offer.getMinAmount(), "MinAmount");
        checkCoinNotNullOrZero(offer.getMakerFee(), "MakerFee");
        checkCoinNotNullOrZero(offer.getBuyerSecurityDeposit(), "buyerSecurityDeposit");
        checkCoinNotNullOrZero(offer.getSellerSecurityDeposit(), "sellerSecurityDeposit");
        checkCoinNotNullOrZero(offer.getTxFee(), "txFee");
        checkCoinNotNullOrZero(offer.getMaxTradeLimit(), "MaxTradeLimit");
        // We remove those checks to be more flexible with future changes.
        /*checkArgument(offer.getMakerFee().value >= FeeService.getMinMakerFee(offer.isCurrencyForMakerFeeBtc()).value,
                "createOfferFee must not be less than FeeService.MIN_CREATE_OFFER_FEE_IN_BTC. " +
                    "MakerFee=" + offer.getMakerFee().toFriendlyString());*/
        /*checkArgument(offer.getBuyerSecurityDeposit().value >= ProposalConsensus.getMinBuyerSecurityDeposit().value,
                "buyerSecurityDeposit must not be less than ProposalConsensus.MIN_BUYER_SECURITY_DEPOSIT. " +
                    "buyerSecurityDeposit=" + offer.getBuyerSecurityDeposit().toFriendlyString());
            checkArgument(offer.getBuyerSecurityDeposit().value <= ProposalConsensus.getMaxBuyerSecurityDeposit().value,
                "buyerSecurityDeposit must not be larger than ProposalConsensus.MAX_BUYER_SECURITY_DEPOSIT. " +
                    "buyerSecurityDeposit=" + offer.getBuyerSecurityDeposit().toFriendlyString());
            checkArgument(offer.getSellerSecurityDeposit().value == ProposalConsensus.getSellerSecurityDeposit().value,
                "sellerSecurityDeposit must be equal to ProposalConsensus.SELLER_SECURITY_DEPOSIT. " +
                    "sellerSecurityDeposit=" + offer.getSellerSecurityDeposit().toFriendlyString());*/
        /*checkArgument(offer.getMinAmount().compareTo(ProposalConsensus.getMinTradeAmount()) >= 0,
                "MinAmount is less then " + ProposalConsensus.getMinTradeAmount().toFriendlyString());*/
        checkArgument(offer.getAmount().compareTo(offer.getPaymentMethod().getMaxTradeLimitAsCoin(offer.getCurrencyCode())) <= 0, "Amount is larger then " + offer.getPaymentMethod().getMaxTradeLimitAsCoin(offer.getCurrencyCode()).toFriendlyString());
        checkArgument(offer.getAmount().compareTo(offer.getMinAmount()) >= 0, "MinAmount is larger then Amount");
        checkNotNull(offer.getPrice(), "Price is null");
        checkArgument(offer.getPrice().isPositive(), "Price must be positive. price=" + offer.getPrice().toFriendlyString());
        checkArgument(offer.getDate().getTime() > 0, "Date must not be 0. date=" + offer.getDate().toString());
        checkNotNull(offer.getArbitratorNodeAddresses(), "Arbitrator is null");
        checkNotNull(offer.getMediatorNodeAddresses(), "Mediator is null");
        checkNotNull(offer.getCurrencyCode(), "Currency is null");
        checkNotNull(offer.getDirection(), "Direction is null");
        checkNotNull(offer.getId(), "Id is null");
        checkNotNull(offer.getPubKeyRing(), "pubKeyRing is null");
        checkNotNull(offer.getMinAmount(), "MinAmount is null");
        checkNotNull(offer.getPrice(), "Price is null");
        checkNotNull(offer.getTxFee(), "txFee is null");
        checkNotNull(offer.getMakerFee(), "MakerFee is null");
        checkNotNull(offer.getVersionNr(), "VersionNr is null");
        checkArgument(offer.getMaxTradePeriod() > 0, "maxTradePeriod must be positive. maxTradePeriod=" + offer.getMaxTradePeriod());
        // TODO check upper and lower bounds for fiat
        // TODO check rest of new parameters
        complete();
    } catch (Exception e) {
        offer.setErrorMessage("An error occurred.\n" + "Error message:\n" + e.getMessage());
        failed(e);
    }
}
Also used : Offer(bisq.core.offer.Offer)

Example 43 with Offer

use of bisq.core.offer.Offer in project bisq-core by bisq-network.

the class AccountAgeWitnessService method verifyPeersTradeLimit.

private boolean verifyPeersTradeLimit(Trade trade, AccountAgeWitness peersWitness, Date peersCurrentDate, ErrorMessageHandler errorMessageHandler) {
    Offer offer = trade.getOffer();
    Coin tradeAmount = checkNotNull(trade.getTradeAmount());
    final String currencyCode = offer.getCurrencyCode();
    final Coin defaultMaxTradeLimit = PaymentMethod.getPaymentMethodById(offer.getOfferPayload().getPaymentMethodId()).getMaxTradeLimitAsCoin(currencyCode);
    long peersCurrentTradeLimit = getTradeLimit(defaultMaxTradeLimit, currencyCode, Optional.of(peersWitness), peersCurrentDate);
    // Makers current trade limit cannot be smaller than that in the offer
    boolean result = tradeAmount.value <= peersCurrentTradeLimit;
    if (!result) {
        String msg = "The peers trade limit is less than the traded amount.\n" + "tradeAmount=" + tradeAmount.toFriendlyString() + "\nPeers trade limit=" + Coin.valueOf(peersCurrentTradeLimit).toFriendlyString();
        log.warn(msg);
        errorMessageHandler.handleErrorMessage(msg);
    }
    return result;
}
Also used : Coin(org.bitcoinj.core.Coin) Offer(bisq.core.offer.Offer)

Example 44 with Offer

use of bisq.core.offer.Offer in project bisq-core by bisq-network.

the class SellerAsMakerCreatesAndSignsDepositTx method run.

@Override
protected void run() {
    try {
        runInterceptHook();
        checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
        BtcWalletService walletService = processModel.getBtcWalletService();
        String id = processModel.getOffer().getId();
        TradingPeer tradingPeer = processModel.getTradingPeer();
        final Offer offer = trade.getOffer();
        // params
        final boolean makerIsBuyer = false;
        final byte[] contractHash = Hash.getSha256Hash(trade.getContractAsJson());
        trade.setContractHash(contractHash);
        log.debug("\n\n------------------------------------------------------------\n" + "Contract as json\n" + trade.getContractAsJson() + "\n------------------------------------------------------------\n");
        final Coin makerInputAmount = offer.getSellerSecurityDeposit().add(trade.getTradeAmount());
        Optional<AddressEntry> addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG);
        checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present");
        AddressEntry makerMultiSigAddressEntry = addressEntryOptional.get();
        makerMultiSigAddressEntry.setCoinLockedInMultiSig(makerInputAmount);
        walletService.saveAddressEntryList();
        final Coin msOutputAmount = makerInputAmount.add(trade.getTxFee()).add(offer.getBuyerSecurityDeposit());
        final List<RawTransactionInput> takerRawTransactionInputs = tradingPeer.getRawTransactionInputs();
        final long takerChangeOutputValue = tradingPeer.getChangeOutputValue();
        final String takerChangeAddressString = tradingPeer.getChangeOutputAddress();
        final Address makerAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
        final Address makerChangeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
        final byte[] buyerPubKey = tradingPeer.getMultiSigPubKey();
        final byte[] sellerPubKey = processModel.getMyMultiSigPubKey();
        checkArgument(Arrays.equals(sellerPubKey, makerMultiSigAddressEntry.getPubKey()), "sellerPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
        final byte[] arbitratorBtcPubKey = trade.getArbitratorBtcPubKey();
        PreparedDepositTxAndMakerInputs result = processModel.getTradeWalletService().makerCreatesAndSignsDepositTx(makerIsBuyer, contractHash, makerInputAmount, msOutputAmount, takerRawTransactionInputs, takerChangeOutputValue, takerChangeAddressString, makerAddress, makerChangeAddress, buyerPubKey, sellerPubKey, arbitratorBtcPubKey);
        processModel.setPreparedDepositTx(result.depositTransaction);
        processModel.setRawTransactionInputs(result.rawMakerInputs);
        complete();
    } catch (Throwable t) {
        failed(t);
    }
}
Also used : Address(org.bitcoinj.core.Address) AddressEntry(bisq.core.btc.AddressEntry) RawTransactionInput(bisq.core.btc.data.RawTransactionInput) Coin(org.bitcoinj.core.Coin) TradingPeer(bisq.core.trade.protocol.TradingPeer) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) Offer(bisq.core.offer.Offer) PreparedDepositTxAndMakerInputs(bisq.core.btc.data.PreparedDepositTxAndMakerInputs)

Example 45 with Offer

use of bisq.core.offer.Offer in project bisq-core by bisq-network.

the class TradeManager method handleInitialTakeOfferRequest.

private void handleInitialTakeOfferRequest(TradeMessage message, NodeAddress peerNodeAddress) {
    log.trace("handleNewMessage: message = " + message.getClass().getSimpleName() + " from " + peerNodeAddress);
    try {
        Validator.nonEmptyStringOf(message.getTradeId());
    } catch (Throwable t) {
        log.warn("Invalid requestDepositTxInputsMessage " + message.toString());
        return;
    }
    Optional<OpenOffer> openOfferOptional = openOfferManager.findOpenOffer(message.getTradeId());
    if (openOfferOptional.isPresent() && openOfferOptional.get().getState() == OpenOffer.State.AVAILABLE) {
        Offer offer = openOfferOptional.get().getOffer();
        openOfferManager.reserveOpenOffer(openOfferOptional.get());
        checkArgument(message instanceof PayDepositRequest, "message must be PayDepositRequest");
        PayDepositRequest payDepositRequest = (PayDepositRequest) message;
        Trade trade;
        if (offer.isBuyOffer())
            trade = new BuyerAsMakerTrade(offer, Coin.valueOf(payDepositRequest.getTxFee()), Coin.valueOf(payDepositRequest.getTakerFee()), payDepositRequest.isCurrencyForTakerFeeBtc(), tradableListStorage, btcWalletService);
        else
            trade = new SellerAsMakerTrade(offer, Coin.valueOf(payDepositRequest.getTxFee()), Coin.valueOf(payDepositRequest.getTakerFee()), payDepositRequest.isCurrencyForTakerFeeBtc(), tradableListStorage, btcWalletService);
        initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), trade.getProcessModel().getFundsNeededForTradeAsLong());
        tradableList.add(trade);
        ((MakerTrade) trade).handleTakeOfferRequest(message, peerNodeAddress, errorMessage -> {
            if (takeOfferRequestErrorMessageHandler != null)
                takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage);
        });
    } else {
        // TODO respond
        // (RequestDepositTxInputsMessage)message.
        // messageService.sendEncryptedMessage(peerAddress,messageWithPubKey.getMessage().);
        log.debug("We received a take offer request but don't have that offer anymore.");
    }
}
Also used : PayDepositRequest(bisq.core.trade.messages.PayDepositRequest) OpenOffer(bisq.core.offer.OpenOffer) Offer(bisq.core.offer.Offer) OpenOffer(bisq.core.offer.OpenOffer)

Aggregations

Offer (bisq.core.offer.Offer)49 Coin (org.bitcoinj.core.Coin)15 Test (org.junit.Test)13 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)12 OfferPayload (bisq.core.offer.OfferPayload)10 Price (bisq.core.monetary.Price)9 OfferMaker.btcUsdOffer (bisq.core.offer.OfferMaker.btcUsdOffer)8 PaymentMethod (bisq.core.payment.payload.PaymentMethod)7 Contract (bisq.core.trade.Contract)7 NodeAddress (bisq.network.p2p.NodeAddress)7 Volume (bisq.core.monetary.Volume)6 PeerInfoIcon (bisq.desktop.components.PeerInfoIcon)6 Popup (bisq.desktop.main.overlays.popups.Popup)6 MainView (bisq.desktop.main.MainView)5 Button (javafx.scene.control.Button)5 TableCell (javafx.scene.control.TableCell)5 TableColumn (javafx.scene.control.TableColumn)5 TradeCurrency (bisq.core.locale.TradeCurrency)4 AutoTooltipButton (bisq.desktop.components.AutoTooltipButton)4 AutoTooltipLabel (bisq.desktop.components.AutoTooltipLabel)4