Chainlinkの外部アダプターを実装するまでのあれこれ【CFH2021その5】

さて、ぼちぼち開発をすすめていきましょう！
...って何を作るかまだ未定ですが^^;

https://chainlink-fall-hackathon-2021.devpost.com/

とりま、外部からおもしろそうなデータを引っ張ってきてごにょごにょする系が作りたいなーと思うので、
外部アダプターの作り方＆使い方をマスターしておきたいと思いますー
参考記事はこちら。

https://blog.chain.link/build-and-use-external-adapters/

# Chainlink外部アダプター（External Adapter）とは

```
あらゆるブロックチェーン上のスマートコントラクトは、
Chainlinkのオラクルと統合することで、
あらゆる開発者が現実世界のデータやイベントをブロックチェーンの世界に簡単に接続できるようにします。
ChainlinkがオラクルソリューションとしてSolidityに参入して以来、
APIやオフチェーンデータの利用はすでに大規模に拡大しています。

Chainlinkにはアダプターという機能があり、
「コアアダプター」「外部アダプター」の2種類があります。
「コアアダプター」とは、chainlinkのコアノードクライアントにネイティブにインストールされている機能です。
例: Httpget、Copy、Jsonparseなど

「外部アダプター」は、Chainlink oracle networksの機能を自由にカスタマイズすることができます。
Chainlinkの外部アダプターと外部イニシエータのカスタマイズ性は、
あらゆるブロックチェーンと連携するように設定できるChainlinkの汎用性を高めています。
```

Chainlinkに組み込まれたコアアダプターにより、
オープンAPIからのデータを簡単に構成し、検証することができます。
※Chainlinkバージョン2からコアアダプターは「Tasks」に名称が変わりました。

https://docs.chain.link/docs/tasks/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47490/9f339722-356f-2929-7882-facf51292f77.png)

```
下記のような機能を実装するために、
外部アダプターを使用します。

1. API認証(APIのパスワードキーを非公開にする)
2. ガスを節約するためのプライベート、低レイテンシー、および/または高スループットのオフチェーン計算
3. 他のブロックチェーンへのデータ書き込み（相互運用性）
4. コアアダプタではカバーできない希望の機能

外部アダプタは、高品質なデータへのアクセスを可能にし、
スマートコントラクトをプレミアムなウェブAPIに接続するための極めて高い柔軟性を実現し、
DeFi経済で3億＄以上を確保する35以上の価格参照フィードなど、
信頼性と安全性の高いオラクルネットワークですでに活用されています。

さて、スマートコントラクトをエンドツーエンドで分散させたい場合は、
他のオラクルノードもこの外部アダプターを実行できるようにしておく必要があることを覚えておきましょう。
外部アダプタはー、オープンソースのパッケージのようなもので、
Chainlinkノードのためのものだと考えてください。
つまり、ノードを実行したくない場合は実行する必要はありませんが、
スマートコントラクトにカスタマイズ可能な機能を使用させることができます。
他のノードに外部アダプターをホスティングしてもらうこともできますし、
Chainlinkを活用しているプロジェクトの多くが、
自分でノードを動かす必要がないことがわかります。
これにより、スマートコントラクトのエンジニアは分散型アプリケーションのビジネスロジックに集中し、
ノード運用者はノードの運用に集中することができます。
外部アダプタをmarket.linkのようなサードパーティのノードリストサービスに追加することもできますし、
#ask-a-node-operatorで外部アダプターをホストして、テストやビルドができるようにすることもできます。
もちろん、自分でノードを運用したい場合は、それも可能です。
```

あんまり自分で書いたプログラムを人にみせないので、
ノード運営さんに自分のコード見られるのちょっと恥ずかしい...///


# 独自の外部アダプターを作る

nodejsのテンプレートをダウンロードします。
テンプレートでは仮想通貨の価格を取得するAPIが組み込まれています。

```
git clone https://github.com/thodges-gh/CL-EA-NodeJS-Template.git ExternalAdapterTemplate
cd ExternalAdapterTemplate
yarn
yarn start
```

```
curl -X POST -H "content-type:application/json" "http://localhost:8080/" --data '{ "id": 0, "data": { "from": "ETH", "to": "USD" } }'

// 返り値
{"jobRunID":0,"data":{"USD":441.49,"result":441.49},"result":441.49,"statusCode":200}
```

Chainlinkノードは、以下を持つjsonリクエストを送信します。
 - ID
 - データオブジェクト
 - ※以下のようなシンプルなものがあります。 {"id": "0″, "data":{}}。

また、すべての外部アダプタは、少なくとも以下の項目を含むjsonオブジェクトで応答する必要があります。

 - jobRunID
 - データオブジェクト
 - status（できたら追加）
 - result（できたら追加）




# 外部アダプターをChainlinkのノードに公開する

自分でノードをたてる方法もありますが、
いろいろ大変そうなので、
外部アダプターを公開して、どこかの誰かにお願いするかたちがおすすめ...とのことです！
アダプタをMarket（ https://market.link/ ）に公開するには2つの方法があります。

https://docs.linkpool.io/docs/market_adapter_listing_overview


1. 自分でアダプターを作成し、それが GitHub の自分のリポジトリにある場合
https://docs.linkpool.io/docs/market_adapter_listing_owner

アダプターを記述した構成ファイルをリポジトリにコミット。
仕様に沿って.adapter.ymlファイルを作成する。

1. 既存のアダプタを見つけたが、自分が所有していないリポジトリにある場合
https://docs.linkpool.io/docs/market_adapter_listing_open_adapter
※リンク切れ？仕様が変わった？？


・・・

（これ、外部アダプター公開して、
自分のサーバに組み込んでくれる
心優しいノードの人っておるんか...！！？
やっぱ、自分でノード管理するしかないんじゃないのかなぁ...）


# 外部アダプターをスマートコントラクトから呼び出す

無事自作の外部アダプターがノードに登録されれば、（ハードルはかなり高いとおもいますが...）
スマートコントラクトからメソッドを呼び出すことができます。
サンプルでは、Alpha VantageのAPIを利用する例が書かれています。
Alpha Vantageは株式や暗号データのAPIで、APIキーも必要です。
LinkpoolのKovanノードがホストする外部アダプタを通じてTSLAの価格を取得するチュートリアルが公開されてます。

Remixで触りたい方はこちら。
そんなにややこしくはないですが、
やっぱり個別のjobを信頼するノードにリクエストをするってところがめんどくさいですねぇ...
独自アダプターの場合はノード立てるしかないかなぁー

https://remix.ethereum.org/#version=soljson-v0.6.12+commit.27d51765.js&optimize=false&gist=f856530b20943e92ed6cc69c1285cdfe&evmVersion=null&runs=200

```TSLAStockDataKovan.sol
/** This example code is designed to quickly deploy an example contract using Remix.
 *  If you have never used Remix, try our example walkthrough: https://docs.chain.link/docs/example-walkthrough
 *  You will need testnet ETH and LINK.
 *     - Kovan ETH faucet: https://faucet.kovan.be/
 *     - Kovan LINK faucet: https://kovan.chain.link/
 */
 
pragma solidity ^0.6.0;

import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/ChainlinkClient.sol";

contract TSLAStockDataKovan is ChainlinkClient {
    address private oracle;
    bytes32 private jobId;
    uint256 private fee;
    
    uint256 public tslaPrice;
    constructor() public {
    	setPublicChainlinkToken();
    	oracle = 0x56dd6586DB0D08c6Ce7B2f2805af28616E082455; // oracle address
    	jobId = "802ec94e00184b789a016b8e71ae9fb4"; //job id
    	fee = 0.1 * 10 ** 18; // 0.1 LINK
    }
    
    /**
     * Make initial request
     */
    function requestTSLAPrice() public {
    	Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfillEthereumPrice.selector);
    	req.add("function", "GLOBAL_QUOTE");
    	req.add("symbol", "TSLA");
    	string[] memory copyPath = new string[](2);
        copyPath[0] = "Global Quote";
        copyPath[1] = "05. price";
        req.addStringArray("copyPath", copyPath);
        req.addInt("times", 100000000);
    	sendChainlinkRequestTo(oracle, req, fee);
    }
    
    /**
     * Callback function
     */
    function fulfillEthereumPrice(bytes32 _requestId, uint256 _price) public recordChainlinkFulfillment(_requestId) {
    	tslaPrice = _price;
    }
```

ちなみにノード, アダプター情報はこちら。
https://market.link/nodes/323602b9-3831-4f8d-a66b-3fb7531649eb/
https://market.link/adapters/30861015-8da4-4f24-a76b-20efaf199e28


# 《おわりに》外部アダプター...おもしろいけど、めんどくせぇ...

先にも書きましたが、
外部アダプターをつくっても、公開して、ノード運営の方に情報提供をお願いしないといけません。
テストネットとか無償で公開してくれるノードぐらい作ってくれてもいいかもしれませんが、
特にそういうのもなく。
本気で製品化とか考えるのであれば、Chainlinkのノード運営にも手を出しといた方がよさそうかなーと思います。

ハッカソン、結局調べ物だけで終わりそうだけど、
せっかくなので、何か作りたいなぁー
どうしよう。