Upgrading from Plugin Node V1 to V2 Using Hard Reset

# Introduction

This guide provides instructions on how to upgrade from Plugin Node 1.0 to 2.0. The **[official Plugin documentation](https://docs.goplugin.co/plugin-2.0-node-operators/plugin-2.0-node-operators)** recommends performing a hard or soft reset of the V1 node before setting up V2. Here, we will guide you through performing a hard reset, setting up Plugin 2.0, and obtaining a new node address. If you happen to own a Plugin 1.0 node set up with Docker, a hard reset is likely the best option.

<details><summary>【日本語】</summary>

このガイドは、Plugin Node 1.0から2.0へ、アップグレードを行う方法を提供しています。**[Plugin公式ドキュメント](https://docs.goplugin.co/plugin-2.0-node-operators/plugin-2.0-node-operators)では、V1ノードをハードリセットまたはソフトリセットをしてからV2をセットアップするようにと書かれています。**。ここではハードリセットを実行してから、Plugin2.0をセットアップし、新しいノードアドレスを取得する方法をガイドします。また、もしもあなたがDockerでセットアップしたPlugin1.0ノードを所有している場合も、おそらくこのハードリセットが一番良い選択肢になるでしょう。
</details>

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/a755fa63-fc05-5e01-eb7b-e402c9f9cb57.png)



# 1. Processing on V1 nodes

On Plugin Node 1.0, we perform the following five steps:

Pluginノード1.0上で、以下の5つの手順を実行します：

:::note
1. Updating Linux systems
1. Output a JSON file of Node Address
1. Initializing Backup Folder and Permissions Setup
1. Store the necessary files in the backup directory
1. VPS Hard Reset

<details><summary>【日本語】</summary>

1. Linuxシステム更新
1. ノードアドレスのJSONファイルを出力
1. バックアップフォルダと権限のセットアップの初期化
1. backupディレクトリに必要なファイルを格納
1. VPSのハードリセット
</details>
:::

## 1-1. Plugin Node Preparation Commands

Commands for updating Linux systems, installing tools, configuring security, and cleaning for plugin node setup.

プラグインノード用のLinuxシステム更新、ツールインストール、セキュリティ設定、クリーニングのコマンド群

```sh:1-1
sudo apt update -y && sudo apt upgrade -y && sudo apt install -y git nano ufw curl tree htop && sudo apt autoremove -y && sudo apt autoclean -y && sudo timedatectl set-timezone UTC
```


## 1-2. Node Address Keystore File Output

The command outputs the node address keystore file to the home directory.

ノードアドレスのキーストアファイルをホームディレクトリに出力します。

```sh:1-2
cd ~/plugin-deployment/ && ./pli_node_scripts.sh keys
```
![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/2df8518d-5e75-6aa5-f6e0-931df9b63ab7.png)


## 1-3. Perform Full Backup Before Upgrading to V2

#### Initializing Backup Folder and Permissions Setup
Lets now run the setup script to ensure that the backup folder & permissions are in place.

バックアップフォルダと権限が整っていることを確認するために、セットアップスクリプトを実行しましょう。

```sh:1-3-1
./_plinode_setup_bkup.sh
```

:::note
### Perform Full Backup

Before upgrading to Plugin Node 2.0, it is recommended to perform a full backup in Plugin Node 1.0 (using commands 1-3-2). Additionally, create a directory named `originals/pluginV1` within the `/plinode_backups/` directory and copy the relevant files from Plugin Node 1.0 (using commands 1-3-3).


<details><summary>【日本語】</summary>

<!--(上に空行が必要)-->
Plugin Node 2.0にアップグレードする前に、1.0でフルバックアップを実行し（コマンド1-3-2）、さらに`/plinode_backups/`ディレクトリ内に`originals/pluginV1`ディレクトリを作成し、Plugin Node 1.0の関連するファイルをコピー（コマンド1-3-3）しておくことをお勧めします。
</details>

```sh:1-3-2
cd ~/plugin-deployment/ && ./_plinode_backup.sh -full
```
![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/da290d8d-a51f-e91e-af80-69281f746acd.png)

```sh:1-3-3
mkdir -p /plinode_backups/originals/pluginV1/ && cd ~/plugin-deployment/ && cp -u 2_nodeStartPM2.sh 3_initiatorStartPM2.sh .env.apicred .env.password /plinode_backups/originals/pluginV1/ && cd ~ && cp -u plinode_$(hostname -f).vars plinode_$(hostname -f)_keys*.json /plinode_backups/originals/pluginV1/ && tree -a /plinode_backups/ 
```
![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/1274ff49-30dc-91a6-8d80-1c2206990232.png)
:::

## 1-4. Transferring the Backup Directory to Your Local PC

Use SFTP or a similar method to transfer the `/plinode_backups/` directory to your local PC. In the screenshot, I am using Turmius. Of course, it is also possible to execute commands.

<details><summary>【日本語】</summary>

<!--(上に空行が必要)-->
SFTPなどを使用して、`/plinode_backups/`ディレクトリをローカルPCに転送してください。スクリーンショットでは、Turmiusを使っています。もちろんコマンドで実行することも可能です。
</details>

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/80d52945-a601-7b6e-c8d0-871add63dc9b.png)

## 1-5. VPS Dashboard Ubuntu 20.04 Hard Reset

Please perform a hard reset (reinstallation of Ubuntu 20.04) from your VPS service provider's dashboard. Once the hard reset is complete, please proceed to the next step.

VPSサービスプロバイダーのダッシュボードからハードリセット（Ubuntu 20.04の再インストール）を実行してください。ハードリセットが完了したら、次へ進んでください。

# 2. Build V2 Node
:::note
Upgrade to V2 Node.
1. Updating Linux systems
1. Download the script `pluginV2Install`
1. Run setup script
1. Depositing XDC and PLI into Node Address
<details><summary>【日本語】</summary>

V2 Nodeにアップグレードしていきます。
1. Linuxシステム更新
1. `pluginV2Install`スクリプトをダウンロード
1. セットアップスクリプトの実行
1. Node Addressに1XDCと1PLIを入金
</details>
:::

## 2-1. Updating Linux systems

Commands for updating Linux systems, installing tools, configuring security, and cleaning for plugin node setup.

プラグインノード用のLinuxシステム更新、ツールインストール、セキュリティ設定、クリーニングのコマンド群

```sh:2-1
sudo apt update -y && sudo apt upgrade -y && sudo apt install -y git nano ufw curl tree htop && sudo apt autoremove -y && sudo apt autoclean -y && sudo timedatectl set-timezone UTC
```


## 2-2. git clone `pluginV2Install`

```sh:2-2-1
cd && git clone https://github.com/GoPlugin/pluginV2Install.git
cd ~/pluginV2Install/
chmod +x *.sh
```

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/9a334f5c-2a44-ae1b-21fd-ccd790c964a6.png)

:::note alert
### ------ Important ------
**On December 25, 2023, at 17:10**

The mainnet RPC is set to `https://erpc.xinfin.network` by default, but I have noticed that it can be unstable at times. Therefore, personally, I believe it would be desirable to change it to `https://earpc.xinfin.network`. The following commands are used to change the `https://erpc.xinfin.network` string to `https://earpc.xinfin.network` in the `~/pluginV2Install/sample.vars` file. Finally, please verify if the change has been made correctly using the `grep` command.

<details><summary>【日本語】</summary>

<!--(上に空行が必要)-->
**2023年12月25日、17時10分**
メインネットのRPCはデフォルトで `https://erpc.xinfin.network` に設定されていますが、時に不安定であることが確認されています。そのため、個人的には `https://earpc.xinfin.network` に変更することが望ましいと考えています。次のコマンドは、`~/pluginV2Install/sample.vars` ファイル内の `https://erpc.xinfin.network` という文字列を `https://earpc.xinfin.network` に変更するためのものです。最後に、変更が正しく行われたかを確認するために `grep` コマンドを使用してください。
</details>

| Before          | After                   |
|-----------------|-------------------------|
| https://erpc.xinfin.network | https://earpc.xinfin.network |

```sh:2-2-2
sed -i -e "s|https://erpc.xinfin.network|https://earpc.xinfin.network|g" ~/pluginV2Install/sample.vars
grep "mainnet_httpUrl" ~/pluginV2Install/sample.vars
```

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/78d43e86-8302-2c61-d94c-9a7ca88c1bab.png)
:::


## 2-3. Run setup script

```sh:2-3-1
./pli_node_scripts.sh mainnet
```

:::note
**Important**
Confirm the script is complete and follow the instructions to run the command below.

**重要**
スクリプトが完了していることを確認して、指示に従って下記コマンドを実行してください。
:::

```sh:2-3-2
source ~/.profile
```
![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/616c0742-f13b-17f6-bd19-be37d99f024a.png)



## 2-4. Depositing XDC and PLI into Node Address for Testing

Use XDCPay or MetaMask to deposit `1` XDC and `1` PLI into the NodeAddress for testing. Please ensure the amount is within the maximum limit of `10` XDC and `5` PLI.

1. Click on the gear icon located in the top right corner of the dashboard.
1. Click on 'Key Management'.
1. Scroll down to the bottom of the screen and locate the 'Address' under 'EVM Chain Accounts'. This will be your 'Node Address'.
1. Send 1XDC and 1PLI to this Node Address.
1. Verify that the balances of XDC and PLI have increased.

<details><summary>【日本語】</summary>

<!--(上に空行が必要)-->
XDCPayまたはMetaMaskを使って、テストに必要な `1` XDCと `1` PLIをNodeAddressに入金します。最大でも `10` XDC、`5` PLI以内にしてください。

1. ダッシュボードの右上にある歯車のアイコンをクリックします。
1. 「Key Management」をクリックします。
1. 画面の下部までスクロールし、「EVM Chain Accounts」の下にある「Address」を探します。これがあなたの「Node Address」になります。
1. このNode Addressに1XDCと1PLIを送ります。
1. XDCとPLIの残高が増加したことを確認します。
</details>

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/5c69f90f-e819-7165-81f8-9fdc6b85b043.png)



![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/7a3894fb-172c-cf1a-28e2-af5b7d8468de.png)


![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/a7c93efe-e578-4a97-47a1-752dceef568f.png)

The upgrade of the plugin node is now complete.

以上でプラグインノードのアップグレードは完了です。



# 3. Backup After Plugin V2 Upgrade

Once you have confirmed the successful import of the V1 node address into the dashboard, it is recommended to perform a backup.

V1ノードアドレスがダッシュボードに正常にインポートされたことを確認したら、バックアップを実行することをおすすめします。

## 3-1. Initializing Backup Folder and Permissions Setup

Lets now run the setup script to ensure that the backup folder & permissions are in place.

バックアップフォルダと権限が整っていることを確認するために、セットアップスクリプトを実行しましょう。

```sh:3-1
cd ~/pluginV2Install/ && ./_plinode_setup_bkup.sh
```


### 3-2. Full Backup

Run the following commands to perform a FULL backup. As per the usage above this backups up both the conf files & the db.

以下のコマンドを実行して、完全なバックアップを実行してください。上記の使用法に従い、設定ファイルとデータベースの両方をバックアップします。

```sh:3-2
cd ~/pluginV2Install/ && ./_plinode_backup.sh -full
```


### 3-3. Create `originals/pluginV2` Directory and Copy Relevant Files

After a successful upgrade to Plugin Node 2.0, create a directory named `originals/pluginV2` within the `/plinode_backups/` directory and copy the relevant files from that moment into it.

Plugin Node 2.0のアップグレードが成功した場合、`/plinode_backups/`ディレクトリ内に`originals/pluginV2`ディレクトリを作成し、その時点で関連するファイルをコピーしてください。

```sh:3-3
mkdir -p /plinode_backups/originals/pluginV2 && cd ~/pluginV2/ && cp -u ~/pluginV2/apicredentials.txt config.toml secrets.toml /plinode_backups/originals/pluginV2/ && cd ~ &&cp -u ~/plinode_$(hostname -f).vars plinode_$(hostname -f)_keys*.json /plinode_backups/originals/pluginV2/ && tree -a /plinode_backups/
```

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/7d2d91a5-279f-b973-b03b-ed75906e96ed.png)




### 3-4. Transferring the Backup Directory to Your Local PC

Use SFTP or a similar method to transfer the `/plinode_backups/` directory to your local PC. In the screenshot, I am using Turmius. Of course, it is also possible to execute commands.

<details><summary>【日本語】</summary>

<!--(上に空行が必要)-->
SFTPなどを使用して、`/plinode_backups/`ディレクトリをローカルPCに転送してください。スクリーンショットでは、Turmiusを使っています。もちろんコマンドで実行することも可能です。
</details>

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/80d52945-a601-7b6e-c8d0-871add63dc9b.png)



# 4. Setup of Job and Deployment of Contract

## 4-1. Oracle Contract
Using Remix, create an Oracle contract.

```javascript:17-1
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
import "@goplugin/contracts2_3/src/v0.7/Operator.sol";

/**
* A. Pli Mainnet Token: 0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
* A. Pli Apothem Token: 0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
*/
```

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/823cc8c8-2e1f-6a73-47cf-e44825070446.png)

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/58ce9e5e-5682-066f-0235-f13954fe4501.png)






Please enter the contract address of PLI (either on the mainnet or Apothem) and your Wallet Address (replace "xdc" at the beginning with "0x").

Your Wallet Address will be the owner of this contract.

:::note
```s:PLI Mainnet Contract Address
0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
```
```s:PLI Apothem Contract Address
0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
```
:::

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/2e62d430-8542-719c-7b01-6da76944fca1.png)

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/490580d7-53ae-939c-7b0d-43b536871b39.png)

:::note
```s:PLI Mainnet Contract Address
0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
```
```s:PLI Apothem Contract Address
0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
```
:::

## 4-2. Job setup
```toml:Sample Job Code - Cryptocompare -
type = "directrequest"
schemaVersion = 1
name = "Sample Request Cryptocompare_XDC_USD"
# It is recommended to give a memorable name to 'name'. 
# You can use it for searching later.
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
# Please replace contractAddress with your oracle address.
minContractPaymentLinkJuels = "0"
observationSource = """
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"]
 
decode_cbor [type="cborparse" data="$(decode_log.data)"]
 
fetch [type="http" method=GET url="https://min-api.cryptocompare.com/data/price?fsym=XDC&tsyms=USD"]
parse [type="jsonparse" path="USD" data="$(fetch)"]
 
multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]
 
encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"]
 
encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ]
 
submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"] //paste the Oracle Address which you deployed in ‘to’ field
 
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
# Please paste your Oracle Address in the 'to' field on the second line from the bottom.
```

:::note
JOB SETUP
1. The value of the name key should be changed.
2. The Oracle Address will be changed in two locations.
3. The URL will be modified.
Regarding CMC, the APIKEY will be updated.
4. The path will be modified.


#### # Cryptocompare
* https://min-api.cryptocompare.com/data/price?fsym=XDC&tsyms=USD
* path="USD"

<details><summary>Sample Job Code - Cryptocompare -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Cryptocompare -
type = "directrequest"
schemaVersion = 1
name = "Sample Request Cryptocompare_XDC_USD"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"]
 
decode_cbor [type="cborparse" data="$(decode_log.data)"]
 
fetch [type="http" method=GET url="https://min-api.cryptocompare.com/data/price?fsym=XDC&tsyms=USD"]
parse [type="jsonparse" path="USD" data="$(fetch)"]
 
multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]
 
encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"]
 
encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ]
 
submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"] //paste the Oracle Address which you deployed in ‘to’ field
 
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
```
</details>

#### # Coingecko
* https://api.coingecko.com/api/v3/simple/price?ids=plugin&vs_currencies=usd
* path="plugin,usd"

<details><summary>Sample Job Code - Coingecko -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Coingecko -
type = "directrequest"
schemaVersion = 1
name = "Sample Request CoinGecko_PLI_USD"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"]
 
decode_cbor [type="cborparse" data="$(decode_log.data)"]
 
fetch [type="http" method=GET url="https://api.coingecko.com/api/v3/simple/price?include_last_updated_at=true&precision=10&ids=plugin&vs_currencies=usd"]
parse [type="jsonparse" path="plugin,usd" data="$(fetch)"]
 
multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]
 
encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"]
 
encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ]
 
submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"] //paste the Oracle Address which you deployed in ‘to’ field
 
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
```
</details>

#### # Binance
* https://api1.binance.com/api/v3/ticker/price?symbol=XRPUSDT
* path="price"

<details><summary>Sample Job Code - Binance -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Binance -
type = "directrequest"
schemaVersion = 1
name = "Sample Request Binance_XRP_USDT"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"]
 
decode_cbor [type="cborparse" data="$(decode_log.data)"]
 
fetch [type="http" method=GET url="https://api1.binance.com/api/v3/ticker/price?symbol=XRPUSDT"]
parse [type="jsonparse" path="price" data="$(fetch)"]
 
multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]
 
encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"]
 
encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ]
 
submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"] //paste the Oracle Address which you deployed in ‘to’ field
 
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
```
</details>

#### # Bitrue
* https://openapi.bitrue.com/api/v1/ticker/price?symbol=XDCUSDT
* path="price"

<details><summary>Sample Job Code - Bitrue -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Bitrue -
type = "directrequest"
schemaVersion = 1
name = "Sample Request Bitrue_XDC_USDT"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"]
 
decode_cbor [type="cborparse" data="$(decode_log.data)"]
 
fetch [type="http" method=GET url="https://openapi.bitrue.com/api/v1/ticker/price?symbol=XDCUSDT"]
parse [type="jsonparse" path="price" data="$(fetch)"]
 
multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]
 
encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"]
 
encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ]
 
submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"] //paste the Oracle Address which you deployed in ‘to’ field
 
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
```
</details>

#### # Kucoin
* https://api.kucoin.com/api/v1/market/orderbook/level1?symbol=XDC-USDT
* path="data,price"

<details><summary>Sample Job Code - Kucoin -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Kucoin -
type = "directrequest"
schemaVersion = 1
name = "Sample Request Kucoin_XDC_USDT"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"]
 
decode_cbor [type="cborparse" data="$(decode_log.data)"]
 
fetch [type="http" method=GET url="https://api.kucoin.com/api/v1/market/orderbook/level1?symbol=XDC-USDT"]
parse [type="jsonparse" path="data,price" data="$(fetch)"]
 
multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]
 
encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"]
 
encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ]
 
submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"] //paste the Oracle Address which you deployed in ‘to’ field
 
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
```
</details>

#### # CMC ／ CoinMarcketCap
* Please change YOUR_API_KEY to your own API.

```TOML
fetch [type=http method=GET url="https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest?symbol=XDC&convert=USDT" allowUnrestrictedNetworkAccess="true" headers="[\\"X-CMC_PRO_API_KEY\\", \\"YOUR_API_KEY\\"]"]
```
* parse [type="jsonparse" path="data,XDC,0,quote,USDT,price" data="$(fetch)"]

<details><summary>Sample Job Code - CMC -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - CMC -
type = "directrequest"
schemaVersion = 1
name = "CMC_XDC-USD"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
 
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"] 

decode_cbor [type="cborparse" data="$(decode_log.data)"] 

fetch [type=http method=GET url="https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest?symbol=XDC&convert=USDT" allowUnrestrictedNetworkAccess="true" headers="[\\"X-CMC_PRO_API_KEY\\", \\"YOUR_API_KEY\\"]"]

parse [type="jsonparse" path="data,XDC,0,quote,USDT,price" data="$(fetch)"]

multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"] 

encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"] 

encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)" 
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ] 

submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"]

decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx 
"""
```
</details>

#### # Coinranking
- **[Website](https://coinranking.com/)**
- **[API Document](https://developers.coinranking.com/api/documentation)**
- Please change YOUR_API_KEY to your own API.

```toml
fetch [type=http method=GET url="https://api.coinranking.com/v2/coin/77jGXSqWJ1ofG?referenceCurrencyUuid=yhjMzLPhuIDl" allowUnrestrictedNetworkAccess="true" headers="[\\"x-access-token\\", \\"YOUR_API_KEY\\"]"]
```

- path="data,coin,price"
 
<details><summary>Sample Job Code - coinranking -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Coinranking - 
type = "directrequest"
schemaVersion = 1
name = "Coinranking_XDC-USD"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
 
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"] 

decode_cbor [type="cborparse" data="$(decode_log.data)"] 

fetch [type=http method=GET url="https://api.coinranking.com/v2/coin/77jGXSqWJ1ofG?referenceCurrencyUuid=yhjMzLPhuIDl" allowUnrestrictedNetworkAccess="true" headers="[\\"x-access-token\\", \\"YOUR_API_KEY\\"]"]

parse [type="jsonparse" path="data,coin,price" data="$(fetch)"] 

multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"] 

encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"] 

encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)" 
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ] 

submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"]

decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx 
"""
```
</details>


#### # Coinpaprika
- **[Website](https://coinpaprika.com/)**
- **[API Document](https://api.coinpaprika.com/)**
- The free version does not require an API key, but please note that **the paid version requires an API key and the base URL may also change**.
- Please change YOUR_API_KEY to your own API.
    | Plan   | Base URL                           |
    |--------|------------------------------------|
    | Free   | https://api.coinpaprika.com/v1/     |
    | Starter| https://api-pro.coinpaprika.com/v1/ |
- path="quotes,USD,price"

```toml :Coinpaprika - Free
fetch [type=http method=GET url="https://api.coinpaprika.com/v1/tickers/cgo-comtech-gold?quotes=USD" allowUnrestrictedNetworkAccess="true"]
```
```toml :Coinpaprika - Paid
fetch [type=http method=GET url="https://api-pro.coinpaprika.com/v1/tickers/cgo-comtech-gold?quotes=USD" allowUnrestrictedNetworkAccess="true" headers="[\\"Authorization\\", \\"YOUR_API_KEY\\"]"]
```
 
<details><summary>Sample Job Code - Coinpaprika -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Coinpaprika -
type = "directrequest"
schemaVersion = 1
name = "Coinpaprika_CGO-USD"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
 
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"] 

decode_cbor [type="cborparse" data="$(decode_log.data)"] 

fetch [type=http method=GET url="https://api.coinpaprika.com/v1/tickers/cgo-comtech-gold?quotes=USD" allowUnrestrictedNetworkAccess="true" headers="[\\"Authorization\\", \\"YOUR_API_KEY\\"]"]
parse [type="jsonparse" path="quotes,USD,price" data="$(fetch)"] 

multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"] 

encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"] 

encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)" 
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ] 

submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"]

decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx 
"""
```
</details>

#### # Tradermade
- **[Website](https://marketdata.tradermade.com/)**
- **[API Document](https://marketdata.tradermade.com/docs/restful-api)**
- Please change YOUR_API_KEY to your own API.
- path="quotes,0,mid"

```toml :Tradermade
fetch [type=http method=GET url="https://marketdata.tradermade.com/api/v1/live?api_key=YOUR_API_KEY&currency=USDJPY" allowUnrestrictedNetworkAccess="true"]
```
 
<details><summary>Sample Job Code - Tradermade -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Tradermade -
type = "directrequest"
schemaVersion = 1
name = "Tradermade_USD-JPY"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
 
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"] 

decode_cbor [type="cborparse" data="$(decode_log.data)"] 

fetch [type=http method=GET url="https://marketdata.tradermade.com/api/v1/live?api_key=YOUR_API_KEY&currency=USDJPY" allowUnrestrictedNetworkAccess="true"]
parse [type="jsonparse" path="quotes,0,mid" data="$(fetch)"] 

multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"] 

encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"] 

encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)" 
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ] 

submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"]

decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx 
"""
```
</details>

#### # Bitfinex
- **[Website](https://www.bitfinex.com/)**
- **[API Document](https://docs.bitfinex.com/docs)**
- path="6"

```toml :Bitfinex
fetch [type=http method=GET url="https://api-pub.bitfinex.com/v2/ticker/tXDCUSD" allowUnrestrictedNetworkAccess="true"]
parse [type="jsonparse" path="6" data="$(fetch)"] 
```

<details><summary>Sample Job Code - Bitfinex -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - Bitfinex -
type = "directrequest"
schemaVersion = 1
name = "Bitfirex_XDC-USD"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
 
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"] 

decode_cbor [type="cborparse" data="$(decode_log.data)"] 

fetch [type=http method=GET url="https://api-pub.bitfinex.com/v2/ticker/tXDCUSD" allowUnrestrictedNetworkAccess="true"]
parse [type="jsonparse" path="6" data="$(fetch)"] 

multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"] 

encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"] 

encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)" 
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ] 

submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"]

decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx 
"""
```
</details>


#### # BitMart

- **[Website](https://www.bitmart.com/)**
- **[API Document](https://developer-pro.bitmart.com/en/spot/#get-ticker-of-a-trading-pair-v3)**
- path="data,last"

```toml :Bitfinex
fetch [type="http" method=GET url="https://api-cloud.bitmart.com/spot/quotation/v3/ticker?symbol=PLI_USDT"]
parse [type="jsonparse" path="data,last" data="$(fetch)"]
```

<details><summary>Sample Job Code - BitMart -</summary>

<!--(上に空行が必要)-->
```toml:Sample Job Code - BitMart -
type = "directrequest"
schemaVersion = 1
name = "Sample Request BitMart_PLI_USDT"
forwardingAllowed = false
maxTaskDuration = "0s"
contractAddress = "YOUR_ORACLE_ADDRESS"
minContractPaymentLinkJuels = "0"
observationSource = """
decode_log [type="ethabidecodelog" abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)" data="$(jobRun.logData)" topics="$(jobRun.logTopics)"]
 
decode_cbor [type="cborparse" data="$(decode_log.data)"]
 
fetch [type="http" method=GET url="https://api-cloud.bitmart.com/spot/quotation/v3/ticker?symbol=PLI_USDT"]
parse [type="jsonparse" path="data,last" data="$(fetch)"]
 
multiply [type="multiply" input="$(parse)" times="$(decode_cbor.times)"]
 
encode_data [type="ethabiencode" abi="(bytes32 requestId, uint256 value)" data="{ \\"requestId\\": $(decode_log.requestId), \\"value\\": $(multiply) }"]
 
encode_tx [type="ethabiencode" abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}" ]
 
submit_tx [type="ethtx" to="YOUR_ORACLE_ADDRESS" data="$(encode_tx)"] //paste the Oracle Address which you deployed in ‘to’ field
 
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
```
</details>

:::


Bitrue
![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/7aebb042-51fe-d4ef-5dcd-0c9c251b548c.png)

Cryptocomapre
![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/7b373ee8-cb39-8ad0-ff0c-3752071f3b31.png)

:::note
**Get the JOBID and remove the hyphen `-`.**

**JOBIDを取得し、ハイフン`-`を取り除きます。**

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/ee614ed0-ff1e-9766-98cf-b9ac2f96f4ac.png)

:::



## 4-3. CONSUMER CONTRACT

I will create a smart contract using Remix.

Remixを使って、スマートコントラクトを作成します。

https://remix.xinfin.network/


:::note
Please feel free to make any necessary modifications to the following:

* Mainnet or Apothem
    * Mainnet - 0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
    * Apothem - 0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
* Oracle Address
    * Please change the leading 'xdc' to '0x'.
* JOBID
    * Please remove the hyphen `-`.
* API(peer)
    * Please make the URL the same as when creating the JOB.

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/185abcc2-4220-9b2c-919e-3a71df5a1417.png)

```javascript:Consumer Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;


import "@goplugin/contracts2_3/src/v0.8/PluginClient.sol";
import "@goplugin/contracts2_3/src/v0.8/ConfirmedOwner.sol";

/**
* THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY.
* THIS EXAMPLE USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/


contract APIConsumer is PluginClient, ConfirmedOwner {
using Plugin for Plugin.Request;


uint256 public volume;
bytes32 private jobId;
uint256 private fee;


event RequestVolume(bytes32 indexed requestId, uint256 volume);


/**
* @notice Initialize the pli token and target oracle
*
* Details:
* A. Pli Token for Mainnt: 0xff7412ea7c8445c46a8254dfb557ac1e48094391
* B. Oracle: [Copy paste the Oracle Contract Address, which you deployed as first step in this page] (Plugin DevRel)
* C. jobId: <job ID>
*
*/
constructor() ConfirmedOwner(msg.sender) {
setPluginToken(0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391);//Pli address as mentioned in ‘A’
setPluginOracle(<Copy paste the Oracle Contract Address>);//Oracle address
jobId = "<job ID>";//Job ID as stored in ‘C’ JOB SUBMISSION
fee = (0.001 * 1000000000000000000) / 10;
}


/**
* Create a Plugin request to retrieve API response, find the target
* data, then multiply by 1000000000000000000 (to remove decimal places from data).
*/
function requestVolumeData() public returns (bytes32 requestId) {
Plugin.Request memory req = buildPluginRequest(
jobId,
address(this),
this.fulfill.selector
);


// Set the URL to perform the GET request on
// req.add(
// "get",
// "<sample_api_link>/data/pricemultifull?fsyms=ETH&tsyms=USD"
// );
req.add(
"get",
"<sample_api_link>/data/price?fsym=XDC&tsyms=USDT"
);


// Multiply the result by 1000000000000000000 to remove decimals
int256 timesAmount = 10 ** 18;
req.addInt("times", timesAmount);


// Sends the request
return sendPluginRequest(req, fee);
}


/**
* Receive the response in the form of uint256
*/
function fulfill(
bytes32 _requestId,
uint256 _volume
) public recordPluginFulfillment(_requestId) {
emit RequestVolume(_requestId, _volume);
volume = _volume;
}


/**
* Allow withdraw of Link tokens from the contract
*/
function withdrawPli() public onlyOwner {
PliTokenInterface pli = PliTokenInterface(PluginTokenAddress());
require(
pli.transfer(msg.sender, pli.balanceOf(address(this))),
"Unable to transfer"
);
}
}
```

:::

:::note warn

Please pay attention to the version of the Remix compiler. **It should be `0.8.7`**. In versions newer than `0.8.20`, errors will occur.

Remixのコンパイラのバージョンに注意してください。**`0.8.7`で良いでしょう**。`0.8.20`より新しいバージョンでは、エラーが出ます。

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/1ba69c93-ecff-84ef-34bb-673287527a9d.png)
:::

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/f250bed0-c5de-21df-fd2b-eebb0dc6f93a.png)

↓

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/39bd03ef-11f1-7bdd-151e-db9b70da1804.png)

↓

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/cd1d214f-4ff3-acfa-3dc0-643ea6f8813b.png)

↓

:::note
As of December 29, 2023, the gas fee on the XDC mainnet is **`0.25` gwei**. If the XDC network's mainnet officially transitions to XDCPoS2.0, the gas fee is expected to increase to **`12.5` gwei**.

2023年12月29日現在、XDCメインネットのガス代は **`0.25`gwei** です。 XDCネットワークのメインネットが正式にXDCPoS2.0に移行した場合、ガス代は **`12.5`gwei** になる予定です。

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/73504383-397f-97fc-39cc-6cc0c0f1ffda.png)
:::

↓

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/e11dffa7-7e4d-bd6e-58ec-2df7f54ced9b.png)

↓

Please wait for about 2 to 3 minutes. You can see that it's complete on the dashboard.

2〜3分、待ちます。するとダッシュボードで`Completed`と表示されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/80784bf3-5ebe-71a6-33cf-4b8b18c432ee.png)

You can also check it on the Remix. Please click on `Volume`.

Remixでも確認することができます。`Volume`をクリックしてください。

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/b60db510-0349-ebbb-0eb9-90c5a69e015c.png)

You can see that the value of the completed job's "multiply" task is the same.

CompleteしたJobのmultiply`タスクの値と同じであることがわかります。

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/9db6e3eb-7a81-6d4c-6c81-277d9123aef6.png)

# 5. Backup Again

I recommend that you perform another backup once the job is complete. Please refer back to "**[3. Backup After Plugin V2 Upgrade](https://qiita.com/11ppm/private/971439917fb080d887a2#3-backup-after-plugin-v2-upgrade)**" for this. **In this case, it is sufficient to back up the database only.** Use SFTP or a similar method to transfer the `/plinode_backups/` directory to your local PC.

<details><summary>【日本語】</summary>

<!--(上に空行が必要)-->
Jobがコンプリートしたら、再びバックアップをすることをおすすめします。"**[3. Backup After Plugin V2 Upgrade](https://qiita.com/11ppm/private/971439917fb080d887a2#3-backup-after-plugin-v2-upgrade)**" に戻って、そちらを参照してください。**この場合は、databaseのバックアップだけでも構いません。** SFTPなどを使用して、`/plinode_backups/`ディレクトリをローカルPCに転送してください。
</details>

```sh:5
cd ~/pluginV2Install/ && ./_plinode_backup.sh -db && tree -a /plinode_backups/ 
```
![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/a3f304cc-d060-8bde-802d-40712cef1c1b.png)


![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/80d52945-a601-7b6e-c8d0-871add63dc9b.png)


And that's the end of the guide.

以上です。


# Troubleshooting

:::note
If you encounter the following symptoms when logging into the dashboard, it is possible that the RPC your node is connected to is unstable. In such cases, consider executing the following command to change the RPC:

- `ETH` and `PLI` values are not displayed.
- When opening the `Node` tab, the `State` is displayed as `Unreachable`.

<details><summary>【日本語】</summary>

<!--(上に空行が必要)-->
ダッシュボードにログインした際に、以下の症状が現れる場合、おそらくノードが接続しているRPCが不安定である可能性があります。この場合、RPCを変更するために以下のコマンドを実行してみてください。

- `ETH`と`PLI`の値が表示されない
- `Node`タブを開くと`State`に`Unreachable`と表示されている
</details>
:::


![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/2713311b-36c5-5dc1-976a-be040295fa33.png)

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/8829edfd-ec2e-6d67-5b74-2df4604751cb.png)

![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/2957f61e-aa6a-42f0-594e-9fc557060be4.png)

### RPC Change Command

- `erpc.xinfin.network → earpc.xinfin.network` RPC Change Command

    This command replaces a specified URL (https://erpc.xinfin.network) with another URL (https://earpc.xinfin.network) in multiple files and then checks whether the replacement was successful. The target files include `~/pluginV2Install/sample.vars`, `~/plinode_$(hostname -f).vars`, and `~/pluginV2/config.toml`.
    
    <details><summary>【日本語】</summary>
    
    <!--(上に空行が必要)-->
    このコマンドは、指定したURL（https://erpc.xinfin.network）を別のURL（https://earpc.xinfin.network）に置換し、その後、置換が成功したかどうかを確認するコマンドです。対象ファイルは、`~/pluginV2Install/sample.vars`、`~/plinode_$(hostname -f).vars`、および `~/pluginV2/config.toml` です。
    </details>
    
    ```sh:T-1
    sed -i -e "s|https://erpc.xinfin.network|https://earpc.xinfin.network|g" ~/pluginV2Install/sample.vars ~/plinode_$(hostname -f).vars ~/pluginV2/config.toml && grep "mainnet_httpUrl" ~/pluginV2Install/sample.vars ~/plinode_$(hostname -f).vars && grep "httpUrl" ~/pluginV2/config.toml
    ```

    :::note warn
    If you want to revert to the default `erpc.xinfin.network`, execute the following command:
    
    デフォルトの`erpc.xinfin.network`に戻したい場合、以下のコマンドを実行してください。
    
    - `earpc.xinfin.network → erpc.xinfin.network` RPC Change Command
    
    ```sh:T-2
    sed -i -e "s|https://earpc.xinfin.network|https://erpc.xinfin.network|g" ~/pluginV2Install/sample.vars ~/plinode_$(hostname -f).vars ~/pluginV2/config.toml
    grep "mainnet_httpUrl" ~/pluginV2Install/sample.vars ~/plinode_$(hostname -f).vars && grep "httpUrl" ~/pluginV2/config.toml
    ```
:::

### RPC & Websocket Confirm Command

- Verify the RPC & Websocket in the `~/pluginV2Install/sample.vars`, `~/plinode_$(hostname -f).vars`, and `~/pluginV2/config.toml` files.
    
    ```sh:T-3
    echo -e '\n【~/plinode_YOUR_HOSTENAME.vars】' && cat ~/plinode_$(hostname -f).vars | grep -E 'mainnet_wsUrl|mainnet_httpUrl' ;echo -e '\n【~/pluginV2Install/sample.vars】' && cat ~/pluginV2Install/sample.vars | grep -E 'mainnet_wsUrl|mainnet_httpUrl' ;echo -e '\n【~/pluginV2/config.toml】' && cat ~/pluginV2/config.toml | grep -E 'httpUrl|wsUrl' ;echo
    ```
    ![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/4ab88f30-5c9a-4e8d-3dae-aaf3a87bd58c.png)

### Pm2 Restart Command

- To apply the changes, restart the process.
変更を反映させるために、プロセスを再起動させます。

    
    ```sh:T-4
    pm2 restart all
    ```
    
    Finally, log in to the dashboard.
    
    最後にダッシュボードへログインします。
    
    ```sh:T-5
    echo https://$(ip a | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1'):6689 && cat ~/pluginV2/apicredentials.txt 
    ```
    
    ![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/e03ceaa4-30a2-7923-426e-3d7999317961.png)
    
    ![Screenshot by Dropbox Capture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518907/7fd7e089-c9fe-d312-997f-8f33f4027c56.png)


*Author: [11ppm](https://twitter.com/11ppm11)*