4

I'm looking to make a simple ethereum smart contract to just monitor a twitter weather feed for the word "sunny". And if its sunny, it would send coins to some account I specify.

Are there any live demo's out there that do something similar to this? And is there a step by step tutorial on how to do this?

1 Answer 1

5

This is not 100% what you asked for, but it's (what I believe) is the closest thing so far. Using Oraclize, you can grab twitter data for a contract. (And this is actually a BIG step forward because previous to this it was near impossible without trusting that some third party isn't feeding in false data.)

Also, I've not seen a tutorial that shows step by step how this works. I'd ask Oraclize themselves as they are the one taking your fee you pay to execute this, so technically they should have tutorials in my opinion.

Oraclize does have documentation: https://docs.oraclize.it/

Example twitter monitoring contract with Oraclize: https://github.com/iudex/iudex/blob/master/contracts/twitter.sol

//
// This contract will validate that a twitter message url:
// 1) corresponds to a given username
// 2) containts an expected message (the user identifier)
//

import "accountProviderBase.sol";

contract Twitter is accountProviderBase {
  Lookup lookup;

  address owner;

  modifier owneronly { if (msg.sender == owner) _ }

  function setOwner(address addr) owneronly {
    owner = addr;
  }

  function Twitter() {
    owner = msg.sender;
  }

  function setLookup(address addr) owneronly {
    lookup = Lookup(addr);
  }

  // map the expected identifier to an oraclize identifier
  mapping (bytes32 => bytes32) expectedId;

  // true if verification, otherwise scoring
  mapping (bytes32 => bool) isVerification;

  // callback from oraclize with the result, let the storage contract know
  function __callback(bytes32 myid, string result, bytes proof) {
    if (msg.sender != oraclize_cbAddress()) throw;

    if (isVerification[myid])
      processVerification(myid, result);
    else
      processScore(myid, result);

    // clean up
    delete expectedId[myid];
    delete isVerification[myid];
  }

  function processScore(bytes32 myid, string result) internal {
    uint followers = parseInt(result);
    uint24 newScore = 1000000;
    if (followers / 10000 == 0)
      newScore = 100 * uint24(followers % 10000);

    Storage(lookup.addrStorage()).updateScore(lookup.accountProvider_TWITTER(), expectedId[myid], newScore);
  }

  // start the scoring process and call oraclize with the URL
  function score(bytes32 id, string userId) coupon("HackEtherCamp") {
    bytes memory _userId = bytes(userId);
    string memory head = "html(https://twitter.com/";
    bytes memory _head = bytes(head);
    string memory tail = ").xpath(//*[contains(@data-nav, 'followers')]/*[contains(@class, 'ProfileNav-value')]/text())";
    bytes memory _tail = bytes(tail);
    string memory query = new string(_head.length + _userId.length + _tail.length);
    bytes memory _query = bytes(query);
    uint i = 0;
    for (uint j = 0; j < _head.length; j++)
      _query[i++] = _head[j];
    for (j = 0; j < _userId.length; j++)
      _query[i++] = _userId[j];
    for (j = 0; j < _tail.length; j++)
      _query[i++] = _tail[j];
    oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
    bytes32 oraclizeId = oraclize_query("URL", query);
    expectedId[oraclizeId] = id;
    isVerification[oraclizeId] = false;
  }

  function processVerification(bytes32 myid, string result) internal {
    // this is basically a bytes32 to hexstring piece
    string memory expected = iudexIdToString(expectedId[myid]);
    bool asExpected = indexOf(result, expected) > -1;
    Storage(lookup.addrStorage()).updateAccount(lookup.accountProvider_TWITTER(), expectedId[myid], asExpected, myid);
  }

  // ensure that the proofLocation corresponds to a twitter.com URL for the user `userId`
  function verifyUrl(string userId, string proofLocation) internal returns (bool){
    bytes memory _userId = bytes(userId);
    string memory twitterPrefix = "://twitter.com/";
    bytes memory _twitterPrefix = bytes(twitterPrefix);
    string memory urlHead = new string(_twitterPrefix.length + _userId.length + 1);
    bytes memory _urlHead = bytes(urlHead);
    uint i = 0;
    for (uint j = 0; j < _twitterPrefix.length; j++)
      _urlHead[i++] = _twitterPrefix[j];
    for (j = 0; j < _userId.length; j++)
      _urlHead[i++] = _userId[j];
    _urlHead[i++] = byte("/");

    if (indexOf(proofLocation, string(_urlHead)) == -1)
      return false;

    return true;
  }

  // start the verification process and call oraclize with the URL
  function verify(bytes32 id, string userId, string proofLocation) coupon("HackEtherCamp") {
  //    bytes32 oraclizeId = oraclize_query("html(https://twitter.com/oraclizeit/status/671316655893561344).xpath(//*[contains(@class, 'tweet-text')]/text())");

    // check that userId matches the username in proofLocation
    if (!verifyUrl(userId, proofLocation))
      throw;

    // build up the request string
    string memory head = "html(";
    bytes memory _head = bytes(head);
    string memory tail = ").xpath(//*[contains(@class, 'tweet-text')]/text())";
    bytes memory _tail = bytes(tail);

    bytes memory _tweetUrl = bytes(proofLocation);

    string memory query = new string(_head.length + _tail.length + _tweetUrl.length + 2);
    bytes memory _query = bytes(query);
    uint i = 0;
    for (uint j = 0; j < _head.length; j++)
      _query[i++] = _head[j];
    for (j = 0; j < _tweetUrl.length; j++)
      _query[i++] = _tweetUrl[j];
    for (j = 0; j < _tail.length; j++)
      _query[i++] = _tail[j];
    _query[i++] = 0;

    oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
    bytes32 oraclizeId = oraclize_query("URL", query);
    expectedId[oraclizeId] = id;
    isVerification[oraclizeId] = true;
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.