Introduction
This guide provides a method for upgrading from Plugin Node 1.0 to 2.0 using a soft reset. The official Plugin documentation offers a soft reset option for V1 nodes. After the soft reset, installing Plugin 2.0 will assign a new node address.
【日本語】
このガイドは、Plugin Node 1.0から2.0へ、ソフトリセットを使ってアップグレードを行う方法を提供しています。Plugin公式ドキュメントでは、V1ノードのソフトリセットオプションが提供されています。ソフトリセット後、Plugin 2.0をインストールすると新しいノードアドレスが割り当てられます。
1. Processing on V1 nodes
On Plugin Node 1.0, we perform the following five steps:
Pluginノード1.0上で、以下の5つの手順を実行します:
- Updating Linux systems
- Output a JSON file of Node Address
- Initializing Backup Folder and Permissions Setup
- Store the necessary files in the backup directory
- Soft Reset of V1 Node
【日本語】
- Linuxシステム更新
- ノードアドレスのJSONファイルを出力
- バックアップフォルダと権限のセットアップの初期化
- backupディレクトリに必要なファイルを格納
- V1ノードのソフトリセット
1-1. Plugin Node Preparation Commands
Commands for updating Linux systems, installing tools, configuring security, and cleaning for plugin node setup.
プラグインノード用のLinuxシステム更新、ツールインストール、セキュリティ設定、クリーニングのコマンド群
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.
ノードアドレスのキーストアファイルをホームディレクトリに出力します。
cd ~/plugin-deployment/ && ./pli_node_scripts.sh keys
1-3. Initializing Backup Folder and Permissions Setup
Lets now run the setup script to ensure that the backup folder & permissions are in place.
バックアップフォルダと権限が整っていることを確認するために、セットアップスクリプトを実行しましょう。
./_plinode_setup_bkup.sh
Perform Full Backup Before Upgrading to Plugin Node 2.0
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).
【日本語】
Plugin Node 2.0にアップグレードする前に、1.0でフルバックアップを実行し(コマンド1-3-2)、さらに/plinode_backups/
ディレクトリ内にoriginals/pluginV1
ディレクトリを作成し、Plugin Node 1.0の関連するファイルをコピー(コマンド1-3-3)しておくことをお勧めします。
cd ~/plugin-deployment/ && ./_plinode_backup.sh -full
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/
1-4. Important Files Copying
cp ~/plinode_$(hostname -f).vars /plinode_backups/plinode_V1.vars
cp $(ls -t ~/plinode_$(hostname -f)_keys_* | head -n 1) /plinode_backups/plinode_V1_keys.json
cp ~/plugin-deployment/.env.password /plinode_backups/.env.password
ll /plinode_backups/
The files to be copied are as follows.
- Node configuration file
- json file where Node Address information is defined
- Keystore file required when importing Node Address
【日本語】
コピーするファイルは下記のとおりです。
- Nodeの設定ファイル
- Node Address情報が定義されているjsonファイル
- Node Addressインポート時に必要となるkeystoreファイル
1-5. Soft Reset of V1 Node
Performing Soft Reset on Plugin Node 1.0.
Plugin Node 1.0のソフトリセットを実行します。
cd ~/plugin-deployment/ && ./reset_pli.sh
Please enter y
in response to the prompt.
2. Build V2 Node
Upgrade to V2 Node.
- Download the script
pluginV2Install
- Soft Reset
- clear environment variables
- Preparing files for V2 nodes
- Run setup script
【日本語】
V2 Nodeにアップグレードしていきます。
-
pluginV2Install
スクリプトをダウンロード - ソフトリセット
- 環境変数のクリア
- V2 ノードのためのファイルの準備
- セットアップスクリプトの実行
2-1. git clone pluginV2Install
cd && git clone https://github.com/GoPlugin/pluginV2Install.git
cd ~/pluginV2Install/
chmod +x *.sh
------ 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.
【日本語】
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
コマンドを使用してください。
Before | After |
---|---|
https://erpc.xinfin.network | https://earpc.xinfin.network |
sed -i -e "s|https://erpc.xinfin.network|https://earpc.xinfin.network|g" ~/pluginV2Install/sample.vars
grep "mainnet_httpUrl" ~/pluginV2Install/sample.vars
2-2. Soft Reset Again
Performing Soft Reset Again.
再びソフトリセットを実行します。
cd ~/pluginV2Install && ./reset_pli.sh
Please enter y
in response to the prompt.
source ~/.profile
2-3. Delete environment variables
These commands remove the environment variable FEATURE_EXTERNAL_INITIATORS
from the profile and unset it.
これらのコマンドは、環境変数 FEATURE_EXTERNAL_INITIATORS をプロファイルから削除し、その設定を無効化します。
sed -i '/FEATURE_EXTERNAL_INITIATORS/d' ~/.profile
cat ~/.profile
echo $FEATURE_EXTERNAL_INITIATORS
unset FEATURE_EXTERNAL_INITIATORS
echo $FEATURE_EXTERNAL_INITIATORS
Reference:
Building a V2 Node with the environment variable still set results in the following message being displayed and the process not starting:
"Config validation failed: invalid environment: environment variable FEATURE_EXTERNAL_INITIATORS
must not be set: unsupported with config v2."
【日本語】
参考:
環境変数が残った状態で V2 Node をビルドすると、以下のメッセージが表示され処理が開始されません。
"Config validation failed: invalid environment: environment variable FEATURE_EXTERNAL_INITIATORS
must not be set: unsupported with config v2."
設定の検証に失敗しました:無効な環境:環境変数 FEATURE_EXTERNAL_INITIATORS は設定されてはなりません:設定 v2 ではサポートされていません。
2-4. Preparing V2 Node
Update sample.vars
In order to inherit the settings of V1 Node, read the vars file of V1 Node and edit sample.vars.
V1 Nodeの設定を引き継ぐために、V1 Nodeのvarsファイルを読み込んでsample.varsを編集します。
The items to be carried over are as follows.
-
API_EMAIL
: Dashboard login user ID -
API_PASS
: Dashboard login password -
PASS_KEYSTORE
: keystore -
DB_PWD_NEW
: PostgreSQL DB password
【日本語】
引き継ぐ項目は下記のとおりです。
-
API_EMAIL
: ダッシュボードのログインユーザID -
API_PASS
: ダッシュボードのログインパスワード -
PASS_KEYSTORE
: キーストア -
DB_PWD_NEW
: PostgreSQL DBのパスワード
source /plinode_backups/plinode_V1.vars && \
sed -i "/API_EMAIL=/c\API_EMAIL=\"$API_EMAIL\"" ~/pluginV2Install/sample.vars && \
sed -i "/API_PASS=/c\API_PASS='$API_PASS'" ~/pluginV2Install/sample.vars && \
sed -i "/PASS_KEYSTORE=/c\PASS_KEYSTORE='$PASS_KEYSTORE'" ~/pluginV2Install/sample.vars && \
sed -i "/DB_PWD_NEW=/c\DB_PWD_NEW=\"$DB_PWD_NEW\"" ~/pluginV2Install/sample.vars
Delete V1 Node files from Home Directory
Delete unnecessary files related to the V1 Node from the home directory.
ホームディレクトリからV1ノードの不要なファイルを削除します。
rm -rf ~/plinode_$(hostname -f)*
2-5. Run setup script
./pli_node_scripts.sh mainnet
Important
Confirm the script is complete and follow the instructions to run the command below.
重要
スクリプトが完了していることを確認して、指示に従って下記コマンドを実行してください。
source ~/.profile
The Node configuration file from V1 is being loaded.
V1のNode設定ファイルが読み込まれています。
2-6. 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.
- Click on the gear icon located in the top right corner of the dashboard.
- Click on 'Key Management'.
- Scroll down to the bottom of the screen and locate the 'Address' under 'EVM Chain Accounts'. This will be your 'Node Address'.
- Send 1XDC and 1PLI to this Node Address.
- Verify that the balances of XDC and PLI have increased.
【日本語】
XDCPayまたはMetaMaskを使って、テストに必要な 1
XDCと 1
PLIをNodeAddressに入金します。最大でも 10
XDC、5
PLI以内にしてください。
- ダッシュボードの右上にある歯車のアイコンをクリックします。
- 「Key Management」をクリックします。
- 画面の下部までスクロールし、「EVM Chain Accounts」の下にある「Address」を探します。これがあなたの「Node Address」になります。
- このNode Addressに1XDCと1PLIを送ります。
- XDCとPLIの残高が増加したことを確認します。
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. 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.
以下のコマンドを実行して、完全なバックアップを実行してください。上記の使用法に従い、設定ファイルとデータベースの両方をバックアップします。
cd ~/pluginV2Install/ && ./_plinode_backup.sh -full
3-2. 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
ディレクトリを作成し、その時点で関連するファイルをコピーしてください。
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/
3-3. 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.
【日本語】
SFTPなどを使用して、/plinode_backups/
ディレクトリをローカルPCに転送してください。スクリーンショットでは、Turmiusを使っています。もちろんコマンドで実行することも可能です。
4. Setup of Job and Deployment of Contract
4-1. Oracle Contract
Using Remix, create an Oracle contract.
// 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
*/
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.
0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
4-2. Job setup
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.
JOB SETUP
- The value of the name key should be changed.
- The Oracle Address will be changed in two locations.
- The URL will be modified.
Regarding CMC, the APIKEY will be updated. - The path will be modified.
# Cryptocompare
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
"""
# Coingecko
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
"""
# Binance
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
"""
# Bitrue
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
"""
# Kucoin
- https://api.kucoin.com/api/v1/market/orderbook/level1?symbol=XDC-USDT
- path="data,price"
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
"""
# CMC / CoinMarcketCap
- Please change YOUR_API_KEY to your own API.
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)"]
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
"""
# Coinranking
- Website
- API Document
- Please change YOUR_API_KEY to your own API.
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"
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
"""
# Coinpaprika
- Website
- API Document
- 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"
fetch [type=http method=GET url="https://api.coinpaprika.com/v1/tickers/cgo-comtech-gold?quotes=USD" allowUnrestrictedNetworkAccess="true"]
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\\"]"]
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
"""
# Tradermade
- Website
- API Document
- Please change YOUR_API_KEY to your own API.
- path="quotes,0,mid"
fetch [type=http method=GET url="https://marketdata.tradermade.com/api/v1/live?api_key=YOUR_API_KEY¤cy=USDJPY" allowUnrestrictedNetworkAccess="true"]
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¤cy=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
"""
# Bitfinex
- Website
- API Document
- path="6"
fetch [type=http method=GET url="https://api-pub.bitfinex.com/v2/ticker/tXDCUSD" allowUnrestrictedNetworkAccess="true"]
parse [type="jsonparse" path="6" data="$(fetch)"]
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
# BitMart
- Website
- API Document
- path="data,last"
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)"]
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
"""
4-3. CONSUMER CONTRACT
I will create a smart contract using Remix.
Remixを使って、スマートコントラクトを作成します。
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
-
.
- Please remove the hyphen
- API(peer)
- Please make the URL the same as when creating the JOB.
// 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"
);
}
}
↓
↓
↓
↓
↓
Please wait for about 2 to 3 minutes. You can see that it's complete on the dashboard.
2〜3分、待ちます。するとダッシュボードでCompleted
と表示されていることがわかります。
You can also check it on the Remix. Please click on Volume
.
Remixでも確認することができます。Volume
をクリックしてください。
You can see that the value of the completed job's "multiply" task is the same.
CompleteしたJobのmultiply`タスクの値と同じであることがわかります。
I recommend that you perform another backup once the job is complete. Please refer back to "3. Backup After Plugin V2 Upgrade" for this. In this case, it is sufficient to back up the database only.
Jobがコンプリートしたら、再びバックアップをすることをおすすめします。"3. Backup After Plugin V2 Upgrade" に戻って、そちらを参照してください。この場合は、databaseのバックアップだけでも構いません。
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" 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.
【日本語】
Jobがコンプリートしたら、再びバックアップをすることをおすすめします。"3. Backup After Plugin V2 Upgrade" に戻って、そちらを参照してください。この場合は、databaseのバックアップだけでも構いません。 SFTPなどを使用して、/plinode_backups/
ディレクトリをローカルPCに転送してください。
cd ~/pluginV2Install/ && ./_plinode_backup.sh -db && tree -a /plinode_backups/
And that's the end of the guide.
以上です。
Troubleshooting
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
andPLI
values are not displayed. - When opening the
Node
tab, theState
is displayed asUnreachable
.
【日本語】
ダッシュボードにログインした際に、以下の症状が現れる場合、おそらくノードが接続しているRPCが不安定である可能性があります。この場合、RPCを変更するために以下のコマンドを実行してみてください。
-
ETH
とPLI
の値が表示されない -
Node
タブを開くとState
にUnreachable
と表示されている
RPC Change Command
-
erpc.xinfin.network → earpc.xinfin.network
RPC Change CommandThis 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
.【日本語】
このコマンドは、指定したURL(
https://erpc.xinfin.network
)を別のURL(https://earpc.xinfin.network
)に置換し、その後、置換が成功したかどうかを確認するコマンドです。対象ファイルは、~/pluginV2Install/sample.vars
、~/plinode_$(hostname -f).vars
、および~/pluginV2/config.toml
です。T-1sed -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
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
T-2sed -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.T-3echo -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
Pm2 Restart Command
-
To apply the changes, restart the process.
変更を反映させるために、プロセスを再起動させます。T-4pm2 restart all
Finally, log in to the dashboard.
最後にダッシュボードへログインします。
T-5echo https://$(ip a | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1'):6689 && cat ~/pluginV2/apicredentials.txt
Author: 11ppm