Skip to content

Commit a87cb02

Browse files
committed
Use coinbase client library.
1 parent 9de3574 commit a87cb02

File tree

15 files changed

+78
-458
lines changed

15 files changed

+78
-458
lines changed

pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@
9898
<artifactId>commons-lang3</artifactId>
9999
<version>3.1</version>
100100
</dependency>
101+
102+
<dependency>
103+
<groupId>com.coinbase.api</groupId>
104+
<artifactId>coinbase-java</artifactId>
105+
<version>1.9.1</version>
106+
</dependency>
107+
<dependency>
108+
<groupId>com.fasterxml.jackson.core</groupId>
109+
<artifactId>jackson-annotations</artifactId>
110+
<version>2.4.3</version>
111+
</dependency>
112+
101113
</dependencies>
102114

103115
<build>

src/main/java/org/whispersystems/bithub/client/CoinbaseClient.java

Lines changed: 30 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,16 @@
1717

1818
package org.whispersystems.bithub.client;
1919

20-
import com.sun.jersey.api.client.Client;
21-
import com.sun.jersey.api.client.ClientHandlerException;
22-
import com.sun.jersey.api.client.UniformInterfaceException;
23-
import com.sun.jersey.api.client.WebResource;
24-
import com.sun.jersey.api.client.config.ClientConfig;
25-
import com.sun.jersey.api.client.config.DefaultClientConfig;
26-
import com.sun.jersey.api.json.JSONConfiguration;
27-
import org.apache.commons.codec.binary.Hex;
28-
import org.codehaus.jackson.map.ObjectMapper;
20+
import com.coinbase.api.Coinbase;
21+
import com.coinbase.api.CoinbaseBuilder;
22+
import com.coinbase.api.entity.Account;
23+
import com.coinbase.api.entity.Transaction;
24+
import com.coinbase.api.exception.CoinbaseException;
25+
import org.joda.money.Money;
2926
import org.whispersystems.bithub.entities.Author;
30-
import org.whispersystems.bithub.entities.BalanceResponse;
31-
import org.whispersystems.bithub.entities.BitcoinTransaction;
32-
import org.whispersystems.bithub.entities.BitcoinTransactionResponse;
33-
import org.whispersystems.bithub.entities.CoinbaseTransaction;
34-
import org.whispersystems.bithub.entities.CoinbseRecentTransactionsResponse;
35-
import org.whispersystems.bithub.entities.ExchangeRate;
3627

37-
import javax.crypto.Mac;
38-
import javax.crypto.spec.SecretKeySpec;
39-
import javax.ws.rs.core.MediaType;
4028
import java.io.IOException;
4129
import java.math.BigDecimal;
42-
import java.security.InvalidKeyException;
43-
import java.security.NoSuchAlgorithmException;
4430
import java.util.List;
4531

4632
/**
@@ -50,116 +36,55 @@
5036
*/
5137
public class CoinbaseClient {
5238

53-
private static final String COINBASE_URL = "https://coinbase.com";
54-
private static final String BALANCE_PATH = "/api/v1/account/balance";
55-
private static final String PAYMENT_PATH = "/api/v1/transactions/send_money";
56-
private static final String EXCHANGE_PATH = "/api/v1/currencies/exchange_rates";
57-
private static final String RECENT_TRANSACTIONS_PATH = "/api/v1/transactions";
58-
59-
private final String apiKey;
60-
private final String apiSecret;
61-
private final Client client;
62-
63-
private static final ObjectMapper objectMapper = new ObjectMapper();
39+
private final Coinbase coinbase;
6440

6541
public CoinbaseClient(String apiKey, String apiSecret) {
66-
this.apiKey = apiKey;
67-
this.apiSecret = apiSecret;
68-
this.client = Client.create(getClientConfig());
42+
this.coinbase = new CoinbaseBuilder().withApiKey(apiKey, apiSecret).build();
6943
}
7044

71-
public List<CoinbaseTransaction> getRecentTransactions()
72-
throws IOException, TransferFailedException
45+
public List<Transaction> getRecentTransactions()
46+
throws CoinbaseException, IOException
7347
{
74-
try {
75-
return getAuthenticatedWebResource(RECENT_TRANSACTIONS_PATH, null).get(CoinbseRecentTransactionsResponse.class)
76-
.getTransactions();
77-
} catch (UniformInterfaceException | ClientHandlerException e) {
78-
throw new IOException(e);
79-
}
48+
return coinbase.getTransactions().getTransactions();
8049
}
8150

82-
public BigDecimal getExchangeRate() throws IOException {
83-
try {
84-
WebResource resource = client.resource(COINBASE_URL)
85-
.path(EXCHANGE_PATH);
86-
87-
String btcToUsd = resource.accept(MediaType.APPLICATION_JSON)
88-
.get(ExchangeRate.class)
89-
.getBtc_to_usd();
90-
91-
return new BigDecimal(btcToUsd);
92-
} catch (UniformInterfaceException | ClientHandlerException e) {
93-
throw new IOException(e);
51+
public BigDecimal getExchangeRate() throws IOException, CoinbaseException {
52+
return coinbase.getExchangeRates().get("btc_to_usd");
9453
}
95-
}
9654

9755
public void sendPayment(Author author, BigDecimal amount, String url)
9856
throws TransferFailedException
9957
{
10058
try {
10159
String note = "Commit payment:\n__" + author.getUsername() + "__ " + url;
10260

103-
BitcoinTransaction transaction = new BitcoinTransaction(author.getEmail(),
104-
amount.toPlainString(),
105-
note);
106-
107-
WebResource.Builder resource = getAuthenticatedWebResource(PAYMENT_PATH, transaction);
61+
Transaction transaction = new Transaction();
62+
transaction.setTo(author.getEmail());
63+
transaction.setAmount(Money.parse("BTC " + amount.toPlainString()));
64+
transaction.setNotes(note);
10865

109-
BitcoinTransactionResponse response = resource.type(MediaType.APPLICATION_JSON_TYPE)
110-
.entity(transaction)
111-
.post(BitcoinTransactionResponse.class);
66+
Transaction response = coinbase.sendMoney(transaction);
11267

113-
if (!response.isSuccess()) {
68+
if (response.getStatus() != Transaction.Status.COMPLETE) {
11469
throw new TransferFailedException();
11570
}
116-
117-
} catch (UniformInterfaceException | ClientHandlerException e) {
71+
} catch (CoinbaseException | IOException e) {
11872
throw new TransferFailedException(e);
11973
}
12074
}
12175

122-
public BigDecimal getAccountBalance() throws IOException, TransferFailedException {
123-
try {
124-
WebResource.Builder resource = getAuthenticatedWebResource(BALANCE_PATH, null);
125-
String amount = resource.get(BalanceResponse.class)
126-
.getAmount();
127-
if (amount == null) {
128-
throw new IOException("Empty amount in response!");
129-
}
130-
131-
return new BigDecimal(amount);
132-
} catch (UniformInterfaceException | ClientHandlerException e) {
133-
throw new IOException(e);
134-
}
135-
}
136-
137-
private WebResource.Builder getAuthenticatedWebResource(String path, Object body) throws TransferFailedException {
138-
try {
139-
String json = body == null ? "" : objectMapper.writeValueAsString(body);
140-
String nonce = String.valueOf(System.currentTimeMillis());
141-
String message = nonce + COINBASE_URL + path + json;
142-
Mac mac = Mac.getInstance("HmacSHA256");
143-
mac.init(new SecretKeySpec(apiSecret.getBytes(), "HmacSHA256"));
76+
public BigDecimal getAccountBalance() throws IOException, CoinbaseException {
77+
List<Account> accounts = coinbase.getAccounts().getAccounts();
78+
Account primary = null;
14479

145-
String signature = new String(Hex.encodeHex(mac.doFinal(message.getBytes())));
146-
147-
return client.resource(COINBASE_URL)
148-
.path(path)
149-
.accept(MediaType.APPLICATION_JSON)
150-
.header("ACCESS_SIGNATURE", signature)
151-
.header("ACCESS_NONCE", nonce)
152-
.header("ACCESS_KEY", apiKey);
153-
} catch (NoSuchAlgorithmException | InvalidKeyException | IOException e) {
154-
throw new TransferFailedException();
80+
for (Account account : accounts) {
81+
if (account.isPrimary()) {
82+
primary = account;
83+
break;
84+
}
15585
}
156-
}
15786

158-
private ClientConfig getClientConfig() {
159-
ClientConfig config = new DefaultClientConfig();
160-
config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
161-
162-
return config;
87+
if (primary != null) return coinbase.getBalance(primary.getId()).getAmount();
88+
else return new BigDecimal(0.0);
16389
}
164-
16590
}

src/main/java/org/whispersystems/bithub/controllers/GithubController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.whispersystems.bithub.controllers;
1919

2020
import com.codahale.metrics.annotation.Timed;
21+
import com.coinbase.api.exception.CoinbaseException;
2122
import com.fasterxml.jackson.databind.ObjectMapper;
2223
import org.apache.commons.net.util.SubnetUtils;
2324
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
@@ -96,7 +97,7 @@ public GithubController(List<RepositoryConfiguration> repositories,
9697
public void handleCommits(@Auth Authentication auth,
9798
@HeaderParam("X-Forwarded-For") String clientIp,
9899
@FormParam("payload") String eventString)
99-
throws IOException, UnauthorizedHookException, TransferFailedException
100+
throws IOException, UnauthorizedHookException, TransferFailedException, CoinbaseException
100101
{
101102
authenticate(clientIp);
102103
PushEvent event = getEventFromPayload(eventString);

src/main/java/org/whispersystems/bithub/entities/Amount.java

Lines changed: 0 additions & 34 deletions
This file was deleted.

src/main/java/org/whispersystems/bithub/entities/BalanceResponse.java

Lines changed: 0 additions & 34 deletions
This file was deleted.

src/main/java/org/whispersystems/bithub/entities/BitcoinTransaction.java

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/main/java/org/whispersystems/bithub/entities/BitcoinTransactionResponse.java

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)