/*
* Copyright 2015 NuBits Develoeprs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.matthewmitchell.nubitsj.shapeshift;
import com.matthewmitchell.nubitsj.core.Address;
import com.matthewmitchell.nubitsj.core.AddressFormatException;
import com.matthewmitchell.nubitsj.core.Coin;
import com.matthewmitchell.nubitsj.params.MainNetParams;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Implements {@link com.matthewmitchell.nubitsj.shapeshift.ShapeShiftInterface}
*
* @author Matthew Mitchell
*/
public class ShapeShiftComm extends ShapeShiftInterface {
private static final AsyncHttpClient client = new AsyncHttpClient();
private static final String API_URL = "https://shapeshift.io/";
private static final String CONTENT_TYPE = "application/json";
private abstract class ResponseCallback implements AsyncHttpClient.HttpResponseCallbacks {
@Override
public void onFailure(int responseCode, String error) {
cbks.networkError(responseCode, String.format("%d %s", responseCode, error));
}
}
private boolean checkError(JSONObject json) throws JSONException {
if (!json.has("error"))
return false;
cbks.networkError(AsyncHttpClient.API_ERROR, json.getString("error"));
return true;
}
@Override
public void sendAmount(final ShapeShiftCoin destCoin, Address destAddr, ShapeShiftMonetary amount, Address refund) {
JSONObject jsonRequest = new JSONObject();
try {
jsonRequest.put("pair", "nbt_" + destCoin.getCoinCode());
jsonRequest.put("amount", amount.toPlainString());
jsonRequest.put("withdrawal", destAddr.toString());
jsonRequest.put("returnAddress", refund.toString());
} catch (JSONException ex) {
throw new IllegalArgumentException();
}
client.post(API_URL + "sendamount", jsonRequest.toString(), CONTENT_TYPE, new ResponseCallback() {
@Override
public void onSuccess(String response) {
try {
JSONObject jsonResult = new JSONObject(response);
if (checkError(jsonResult))
return;
jsonResult = jsonResult.getJSONObject("success");
Address deposit = new Address(MainNetParams.get(), jsonResult.getString("deposit"));
Coin amount = Coin.parseCoin(jsonResult.getString("depositAmount"));
ShapeShiftMonetary foreignRate = destCoin.getMonetaryFormat().parseShapeShiftCoin(jsonResult.getString("quotedRate"), destCoin.getExponent());
Coin rate = foreignRate.toCoinRate();
long expiry = jsonResult.getLong("expiration");
cbks.sendAmountResponse(deposit, amount, expiry, rate);
} catch (JSONException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
} catch (AddressFormatException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
}catch (ArithmeticException e) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
} catch (NumberFormatException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
}
}
});
}
@Override
public void cancelPending(Address depositAddr) {
JSONObject jsonRequest = new JSONObject();
try {
jsonRequest.put("address", depositAddr.toString());
} catch (JSONException ex) {
throw new IllegalArgumentException();
}
client.post(API_URL + "cancelpending", jsonRequest.toString(), CONTENT_TYPE, new ResponseCallback() {
@Override
public void onSuccess(String response) {
cbks.cancelPendingResponse();
}
});
}
@Override
public void shift(ShapeShiftCoin destCoin, Address destAddr, Address refund) {
JSONObject jsonRequest = new JSONObject();
try {
jsonRequest.put("pair", "nbt_" + destCoin.getCoinCode());
jsonRequest.put("withdrawal", destAddr.toString());
jsonRequest.put("returnAddress", refund.toString());
} catch (JSONException ex) {
throw new IllegalArgumentException();
}
client.post(API_URL + "shift", jsonRequest.toString(), CONTENT_TYPE, new ResponseCallback() {
@Override
public void onSuccess(String response) {
try {
JSONObject jsonResult = new JSONObject(response);
if (checkError(jsonResult))
return;
Address deposit = new Address(MainNetParams.get(), jsonResult.getString("deposit"));
cbks.shiftResponse(deposit);
} catch (JSONException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
} catch (AddressFormatException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
}
}
});
}
@Override
public void limit(ShapeShiftCoin destCoin) {
client.get(API_URL + "limit/nbt_" + destCoin.getCoinCode(), new ResponseCallback() {
@Override
public void onSuccess(String response) {
try {
JSONObject jsonResult = new JSONObject(response);
if (checkError(jsonResult))
return;
Coin max = Coin.parseCoin(jsonResult.getString("limit"));
Coin min = Coin.parseCoin(jsonResult.getString("min"));
cbks.limitResponse(max, min);
} catch (JSONException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
} catch (ArithmeticException e) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
} catch (NumberFormatException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
}
}
});
}
@Override
public void rate(ShapeShiftCoin destCoin) {
client.get(API_URL + "rate/" + destCoin.getCoinCode() + "_nbt", new ResponseCallback() {
@Override
public void onSuccess(String response) {
try {
JSONObject jsonResult = new JSONObject(response);
if (checkError(jsonResult))
return;
Coin rate = Coin.parseCoinInexact(jsonResult.getString("rate"));
cbks.rateResponse(rate);
} catch (JSONException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
} catch (NumberFormatException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
}
}
});
}
@Override
public void marketInfo(final ShapeShiftCoin destCoin) {
client.get(API_URL + "marketinfo/nbt_" + destCoin.getCoinCode(), new ResponseCallback() {
@Override
public void onSuccess(String response) {
try {
JSONObject jsonResult = new JSONObject(response);
if (checkError(jsonResult))
return;
Coin min = Coin.parseCoinInexact(jsonResult.getString("minimum"));
Coin max = Coin.parseCoinInexact(jsonResult.getString("limit"));
ShapeShiftMonetary rate = destCoin.parseCoinInexact(jsonResult.getString("rate"));
ShapeShiftMonetary fee = destCoin.parseCoinInexact(jsonResult.getString("minerFee"));
cbks.marketInfoResponse(rate, fee, max, min);
} catch (JSONException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
} catch (NumberFormatException ex) {
cbks.networkError(AsyncHttpClient.PARSE_ERROR, "");
}
}
});
}
}