NXTER.ORG

Ardor Contract add-on examples

Jelurida is Developing the Contract Concept

Jelurida continues to hone and further develop their Lightweight add-on contracts concept. In the second week of March, we introduced this in the Nxter Newsletter.  

Lior wrote:

You don’t need to pay gas for these contracts and you can program in Java. On the other hand the “contracts” are only executed by anyone running the addon and it’s not part of the consensus i.e. you can verify that anyone who created a transaction based on the contract did not cheat, but if they cheat or just choose not to run the contract then you cannot fix it. i.e. some trust in the contract executor is required.

Lior continues deploying example contracts to the decentralized data cloud, and we expect to see a number of blog posts from him soon going into detail about the add-ons concept. Until then, here’s the first view, as posted in the #developers channel in ArdorNxt.Slack.com.

 

Hello World 

Lior –

While we continue to develop our contracts concept, you can experiment with it by sending a message transaction, on the Ardor testnet, with text:

{ “chain”: 2, “fullHash”: “53758cc1f44a3eaf86cc187cbd2b73c2a60c0cf60adafb734fc42477bf6d29c2” }

to account ARDOR-NFAY-XYBA-SZ4G-H8SHA

In response, you should receive an automatic greeting message from the HelloWorld contract deployed to cloud data.

The contract code is:

 public void processTransaction(TransactionContext context) {
      if (!context.validateSameRecipient()) {
          return;
      }
      JO transactionJson = context.getTransactionJson();
      int chainId = transactionJson.getInt(“chain”);
      Chain chain = Chain.getChain(chainId);
      String recipientRS = transactionJson.getString(“senderRS”);
      JO params = new JO();
      params.put(“recipient”, recipientRS);
      JO message = new JO();
      message.put(“text”, “Hello ” + recipientRS);
      params.put(“message”, message.toJSONString());
      params.put(“messageIsPrunable”, “true”);
      context.createTransaction(“sendMessage”, chain, params);
  }

The contract transaction is 2:71660bdaa260d790772e3fc64470a8db465f6b395a0e134f921d57d6fd9589f0

The PingPong Lottery

Send any amount in any chain, on the Ardor testnet, with attached message text:

{ “chain”: 2, “fullHash”: “798131112caf0f417abd44eaac64f432d0dac147a0d7021b9232d726e215b4be” }

to account ARDOR-NFAY-XYBA-SZ4G-H8SHA

In response you will receive back amount between 0 and 2x your investment.

Contract code is:

public void processTransaction(TransactionContext context) {
if (!context.validateSameRecipient() || !context.validateTransactionType(PaymentTransactionType.ORDINARY, FxtTransactionType.findTransactionType((byte)-2, (byte)0))) {
return;
}
Random r = context.getRandom();
long amount = context.getAmountNQT();
long returnAmount = BigInteger.valueOf(Math.abs(r.nextLong())).multiply(BigInteger.valueOf(2)).multiply(BigInteger.valueOf(amount)).divide(BigInteger.valueOf(Long.MAX_VALUE)).longValue();
Logger.logInfoMessage(String.format(“amount paid %d amount returned %d”, amount, returnAmount));
Chain chain = context.getChain();
long recipient = context.getSenderId();
JO input = new JO();
input.put(“recipient”, recipient);
input.put(“amountNQT”, returnAmount);
context.createTransaction(“sendMoney”, chain, input);
}

The contract transaction id is, of course, the transaction id we mentioned in our message 2:798131112caf0f417abd44eaac64f432d0dac147a0d7021b9232d726e215b4be

Oracle

Here is an example for an “Oracle” contract.

Send 1 IGNIS or more with attached message:

{ “chain”: 2, “fullHash”: “409c120e6e7551927be4856389bb34cd257ccb84cfb202569327c4a3a89f0e7a” }

to account ARDOR-NFAY-XYBA-SZ4G-H8SHA

In response you will get back a message with the calculated rate of IGNIS per ARDOR from both Bittrex and the Coin Exchange to help you identify arbitrage opportunities.

Contract code:

package nxt.addons.contracts;

import nxt.addons.TransactionContext;
import nxt.blockchain.ChildChain;
import nxt.util.Logger;
import org.json.simple.JSONValue;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class IgnisArdorRates extends AbstractContract {

/**
* Sample contract which receives amount from the trigger transaction and returns a random amount between 0 and twice the received amount
* @param context contract context
*/
@Override
public void processTransaction(TransactionContext context) {
JO response = new JO();
if (!(context.getChain() == ChildChain.IGNIS) || context.getAmountNQT() < ChildChain.IGNIS.ONE_COIN) {
context.setErrorResponse(10001, "Oracle requires a payment of 1 IGNIS to operate");
return;
}
// {"success":true,"message":"","result":{"Bid":0.00003072,"Ask":0.00003098,"Last":0.00003090}}
JO ignisTickerResponse = getRate("IGNIS");
if (ignisTickerResponse.get("errorCode") != null) {
context.setResponse(response);
return;
}
Double ignisLastTrade = ignisTickerResponse.getJo("result").numericToDouble("Last");
JO ardorTickerResponse = getRate("ARDR");
if (ardorTickerResponse.get("errorCode") != null) {
context.setResponse(response);
return;
}
Double ardorLastTrade = ardorTickerResponse.getJo("result").numericToDouble("Last");
long ignisNQTPerARDR = BigDecimal.valueOf(ardorLastTrade).
multiply(BigDecimal.valueOf(ChildChain.IGNIS.ONE_COIN)).
divide(BigDecimal.valueOf(ignisLastTrade), RoundingMode.HALF_EVEN).
longValue();
response.put("BittrexIgnisNQTPerARDR", ignisNQTPerARDR);
JO requestParams = new JO();
requestParams.put("chain", 2);
requestParams.put("exchange", 1);
requestParams.put("firstIndex", 0);
requestParams.put("lastIndex", 1);
JO getCoinExchangeTradesResponse = context.sendRequest("getCoinExchangeTrades", requestParams);
JA trades = getCoinExchangeTradesResponse.getArray("trades");
if (trades.size() > 0) {
JO trade = trades.get(0);
response.put("BlockchainIgnisNQTPerARDR", trade.get("priceNQTPerCoin")); // TODO test with real data
}
JO input = new JO();
input.put("recipient", context.getSenderId());
input.put("message", response.toJSONString());
input.put("messageIsPrunable", true);
context.createTransaction("sendMessage", context.getChain(), input);
}

private JO getRate(String coin) {
HttpURLConnection connection;
JO response = new JO();
String protocol = "https";
String host = "bittrex.com";
int port = 443;
String urlParams = "/api/v1.1/public/getticker?market=BTC-" + coin;
URL url;
try {
url = new URL(protocol, host, port, urlParams);
} catch (MalformedURLException e) {
response.put("errorCode", 10002);
response.put("errorDescription", e.getMessage());
return response;
}
try {
Logger.logDebugMessage("Sending request to server: " + url.toString());
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
try (Reader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
return new JO(JSONValue.parse(reader));
}
} else {
response.put("errorCode", 10003);
response.put("errorDescription", "No response");
return response;
}
} catch (RuntimeException | IOException e) {
response.put("errorCode", 10004);
response.put("errorDescription", e.getMessage());
return response;
}
}
}

Class file is deployed as cloud data txid 2:409c120e6e7551927be4856389bb34cd257ccb84cfb202569327c4a3a89f0e7a

Note that when you send a message to the contract you always use this txid in the message

ProbertyBasedLottery

And contract 2:ab2ee853bf8bf57b550d16d2ffd1bed087b79eefb8b879f8d22f9ec969960a41 is a new version of the PropertyBasedLottery contract used by Bitswift to determine the winner of their twitter campaign: https://www.nxter.org/nxter-news-april-2018-i/#Bitswift_childchain_thread

UPDATE:

Lior has published a series of articles about Lightweight Contracts on his Medium blog, since this post was written. You should check them: https://medium.com/@lyaffe/lightweight-contracts-articles-49c3032a50da

Follow Lior’s blog on Medium.

apenzl
Come get me

apenzl

Arthur founded NXTER.ORG in December 2013.
apenzl
Come get me

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.