Why dissect code?
Nowadays a RESTful API represents the best way for developers to show off the potential of a service. In this post, I analyse the processes we used in order to produce our API in just four weeks.
This article sets out to contribute to the Bitcoin/blockchain ecosystem, describing how it is possible in a short time to realise a blockchain-agnostic micropayment API. Read on and learn how to combine blockchain technology with a lightweight Spring-Boot, Neo4j artifact.
The Yope Payment API
The Yope Payment API is a lightweight micropayment RESTful API, able to hide internal complexity and showing a lean set of interfaces.
The API is under MIT license and can be forked here. An up-to-date instance is fully testable here.
The modular project is blockchain-agnostic, and its responsibilities are divided into self-consistent sub-modules.
payment-api
|-- yope-payment-rest
|-- yope-payment-spring-security
|-- yope-payment-blockchain
|-- yope-payment-db-api
|-- yope-payment-db-neo4j
|-- yope-payment-service
|-- yope-payment-transaction-service
REST, or How It Communicates Outside
Spring Boot offers the easiest way to build a RESTful API in five minutes around a Spring application. It has been adopted, in our case, to build APIs able to easily manage /accounts, /wallets and /transactions.
@Controller
@EnableAutoConfiguration
@RequestMapping("/wallets")
public class WalletResource extends BaseResource {
...
@RequestMapping(method = RequestMethod.GET, produces = "application/json")
public @ResponseBody PaymentResponse<List<Wallet>> getWallets() {
...
}
...
Security, first of all
A dedicated submodule is responsible to handle authentication, extending Spring Security features.
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
The payment-spring-security module is involved during the authentication phase and the org.springframework.security.authentication.AuthenticationManager is responsible to validate any authentication request.
private Authentication tryToAuthenticate(Authentication requestAuthentication) {
Authentication responseAuthentication = authenticationManager.authenticate(requestAuthentication);
if (responseAuthentication == null || !responseAuthentication.isAuthenticated()) {
throw new InternalAuthenticationServiceException("Unable to authenticate Domain User for provided credentials");
}
logger.debug("User successfully authenticated");
return responseAuthentication;
}
Once authenticated, an account can interact with the APIs, after having verified its role: @PreAuthorize(“hasAuthority(‘ROLE_DOMAIN_USER’)”)
@PreAuthorize("hasAuthority('ROLE_DOMAIN_USER')")
@RequestMapping(value="/me", method = RequestMethod.PUT, consumes = "application/json", produces = "application/json")
public @ResponseBody PaymentResponse<Account> updateAccount(final HttpServletResponse response,
@RequestBody(required=false) final Account account) {
return doUpdateAccount(response, getLoggedAccount().getId(), account);
}
Blockchain-agnostic
The project is blockchain-agnostic, that means the payment-blockchain module implementation can be substituted, changing the integration from the Bitcoin blockchain to any other decentralised ledger and maintaining pre-existing interfaces. Currently the payment-blockchain module communicates directly with the Bitcoin blockchain, thanks to bitcoinj library integration.
bitcoinj is a library for working with the Bitcoin protocol. It can maintain a wallet, send/receive transactions without needing a local copy of Bitcoin Core and has many other advanced features.
Bitcoinj library is internally referenced as a Maven dependency, using its latest release.
<dependencies>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.13.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
That library is used to build a service connected to the bitcoin blockchain, able to create wallets, send/receive transactions and notifications.
The excerpt below shows the sending of a transaction through the blockchain, mediated through the bitcoinj library.
final long satoshi = transaction.getAmount()
.multiply(Constants.MILLI_TO_SATOSHI).longValue();
final Coin value = Coin.valueOf(satoshi);
final org.bitcoinj.core.Wallet sender = this.centralWallet();
sender.allowSpendingUnconfirmedTransactions();
final Address receiver = new Address(this.params,
transaction.getDestination().getWalletHash());
final SendResult result = sender.sendCoins(this.peerGroup, receiver,
value);
result.broadcastComplete.get();
return result.tx.getHashAsString();
How it works
The payment-blockchain module handles only one central wallet connected to the blockchain, allowed to send/receive transactions to a given public address and generating a fresh publish hash on every payment request. A payment request is stored in a pending status, until the blockchain sends enough confirmations. A cookbook describes in detail every use case.
Off-chain transactions
Transactions happen off-chain so there is no need to wait for confirmations and there is no limit to the number of transactions or internal wallets that a user can have. Writing to the blockchain occurs only when the user deposits or withdraws their Yope balance, while internal transactions between Yope wallets happen at the speed of the internet, rather than the speed of the blockchain.
Continuous delivery
Any committed change, after being pushed to the master branch, is automatically built in Codeship and can be automatically deployed to a Digitalocean instance, directly connected to apiary.
About this article and the author
Everyone is victim of his/her own destiny. Mine, giving life to lifeless code, is like that of Dr. Frederick Frankenstein. I use dissecting only software artefacts. Follow us on @yopeio.