1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PluginV2 --- Manual Operation ---

Last updated at Posted at 2023-12-23

STEPS TO SETUP PLUGIN 2.0 NODE ON LINUX VPS

This is a list of commands I used to set up Plugin 2.0. Right now, inv4fee has created an amazing script that the Plugin team is adopting. This is the original procedure.

I'm also trying to document the job as much as possible. Looking at it now, there may be some changes, but most of it should still be useful.

I hope this helps you all understand how to set up Plugin 2.0.

@11ppm

1. Login as root to your new VPS

2. Update the system and add in base packages before proceeding by executing below command on the root terminal.

2
sudo apt update -y && sudo apt upgrade -y && sudo apt install -y git nano curl && sudo apt autoremove -y

3. Allow permissions on below ports.

3-1
sudo apt install ufw

Port 22 is a common SSH port, but please adjust it according to your specifications.

3-2
sudo ufw allow 6688/tcp
sudo ufw allow 6689/tcp
sudo ufw allow 22/tcp
# sudo ufw allow YOUR_PORT_NUMBER/tcp
3-3
sudo ufw enable
# If prompted, please enter `y` and press Enter key.

4. Create a new admin user account

4-1
sudo groupadd my_new_user
sudo useradd -p $(openssl passwd -6 my_new_password) my_new_user -m -s /bin/bash -g my_new_user -G sudo

In this guide, you will set up as follows:

  • Username : Doraemon
  • Password : Nobita10Shizuka
4-2
sudo groupadd Doraemon
sudo useradd -p $(openssl passwd -6 Nobita10Shizuka) Doraemon -m -s /bin/bash -g Doraemon -G sudo

5. Now open a new terminal session to your VPS and logon with your new admin user account and complete the rest of the steps.

5
sudo -i -u Doraemon

6. Install GO 1.20.6 version and set GOROOT, GOPATH and PATH

6-1
cd ~ && wget https://dl.google.com/go/go1.20.6.linux-amd64.tar.gz

Screenshot by Dropbox Capture.png

6-2
sudo tar -xvf go1.20.6.linux-amd64.tar.gz
6-3
sudo mv go /usr/local
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
go version

Screenshot by Dropbox Capture.png

7. Install NVM(node version manager) and Node 16.14.0

7-1
cd ~ && curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
source ~/.bashrc

Screenshot by Dropbox Capture.png

7-2
nvm install 16.14.0
nvm use 16.14.0
node --version

Screenshot by Dropbox Capture.png

8. Install [Postgres (> 11.x and <=15.x)]

8-1
cd ~ && sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
8-2
wget -qO- https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /etc/apt/trusted.gpg.d/pgdg.asc &>/dev/null

Screenshot by Dropbox Capture.png

8-3
sudo apt install postgresql postgresql-client -y

Screenshot by Dropbox Capture.png

8-4
sudo systemctl status postgresql
psql --version

Status should be active
Screenshot by Dropbox Capture.png

9. Create Data Base for plugin_mainnet_db in Postgres and set password

Note: Restriction for Database Password
- Must be at least 16 characters long
- Must not comprise: Leading or trailing whitespace / user's API email.

The Plugin node requires three passwords, but with the script used in Plugin 1.0, you can freely generate them. Please save the generated passwords in a memo.

9-1
cd ~ && wget -O gen_passwd.sh https://raw.githubusercontent.com/11ppm/plugin-deployment/main/gen_passwd.sh
chmod +x gen_passwd.sh 

Method A

9-2
./gen_passwd.sh
./gen_passwd.sh -keys
./gen_passwd.sh -db
./gen_passwd.sh -api

Screenshot by Dropbox Capture.png

  • ./gen_passwd.sh -keys
    => 0iP5So8lGt3eJM:K=unsix2;58*.gT32
  • ./gen_passwd.sh -db
    => cmGip2lu5imYLIlcOUeEUakZe1Qysf
  • ./gen_passwd.sh -api
    => fvSNoxI2c1Z1znx3lt
9-3
echo $(tr -cd A-Za-z < /dev/urandom | fold -w10 | head -n1)@plinode.local

Screenshot by Dropbox Capture.png


Method B

Alternatively, after executing the command 9-1, please copy and paste the following command into the terminal and execute it. This will randomly create the necessary password and other requirements for setting up the node.

9-4
#!/bin/bash 

# Set Colour Vars
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# Important Infomation
IP_ADDRESS=$(ip addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -n1)
NEW_KEYSTORE="$(./gen_passwd.sh -keys)"
NEW_DB_PWD="$(./gen_passwd.sh -db)"
_AUTOGEN_API_USER=$(tr -cd A-Za-z < /dev/urandom | fold -w10 | head -n1)
NEW_API_EMAIL="$_AUTOGEN_API_USER@plinode.local"
NEW_API_PWD="$(./gen_passwd.sh -api)"

 # Print
    echo \ &&
    echo -e "${GREEN}#########################################################################${NC}" \ &&
    echo \ &&
    echo -e "${RED}##  IMPORTANT INFORMATION - PLEASE RECORD TO YOUR PASSWORD SAFE${NC}" \ &&
    echo \ &&
    echo -e "${GREEN}#########################################################################${NC}" \ &&
    echo \ &&
    echo -e "${RED}##  KEY STORE SECRET:        $NEW_KEYSTORE${NC}" \ &&
    echo \ &&
    echo -e "${RED}##  POSTGRES DB PASSWORD:    $NEW_DB_PWD${NC}" \ &&
    echo \ &&
    echo -e "${RED}##  API USERNAME:    $NEW_API_EMAIL${NC}" \ &&
    echo -e "${RED}##  API PASSWORD:    $NEW_API_PWD${NC}" \ &&
    echo \ &&
    echo -e "${GREEN}#########################################################################${NC}" \ &&
    echo \ &&
    echo -e "${GREEN}Your Plugin node GUI IP address is as follows:${NC}" \ &&
    echo \ &&
    echo -e "            ${RED}http://$IP_ADDRESS:6688${NC}" \ &&
    echo \ &&
    echo -e "${GREEN}#########################################################################${NC}"

Screenshot by Dropbox Capture.png

9-5
sudo systemctl start postgresql.service

this will login to Postgres

9-6
sudo -i -u postgres psql

Screenshot by Dropbox Capture.png

9-7
CREATE DATABASE plugin_mainnet_db;
9-8
ALTER USER postgres WITH PASSWORD 'new_password';

It is recommended to use the password outputted by the command ./gen_passwd.sh -db for 9-1.

In this demo, I have created the following password:

  • ./gen_passwd.sh -db
    cmGip2lu5imYLIlcOUeEUakZe1Qysf
9-9
ALTER USER postgres WITH PASSWORD 'cmGip2lu5imYLIlcOUeEUakZe1Qysf';

Please keep a note of this password as it will be used for the command 13-3.

Command to exit Postgres

9-10
\q

Screenshot by Dropbox Capture.png

10. Ensure you have python3

10
python3 --version

Screenshot by Dropbox Capture.png

11. Download Plugin 2.0 codebase

11-1
cd ~ && git clone https://github.com/GoPlugin/pluginV2.git && cd pluginV2

Screenshot by Dropbox Capture.png

11-2
ls -la
# ll

Screenshot by Dropbox Capture.png

12. Install pnpm

12
npm install -g pnpm

Screenshot by Dropbox Capture.png

13. Setup Environment:

apicredentials.txt

  • Modify apicredentials.txt file with a valid email id and complex password

    13-1
    nano apicredentials.txt
    

    Screenshot by Dropbox Capture.png

    Screenshot by Dropbox Capture.png

    To save the changes made to the file in nano, follow these steps:

    1. Press the "Ctrl" and "X" keys on your keyboard at the same time.
    2. Press the "Y" key on your keyboard to confirm that you want to save the changes.
    3. Press the "Enter" key on your keyboard to exit the editor.

    These steps will save the changes you made to the file and exit the nano editor.
    ::

config.toml

  • Modify config.toml with appropriate RPC, WSS, and ChainID
    13-2
    nano config.toml
    
    • Mainnet

      Mainnet
      RPC : https://erpc.xinfin.network
      WSS : wss://ws.xinfin.network
      PluginContractAddress : 0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
      Chain ID : 50
      

      https://chainlist.org/chain/50

    • Apothem

      Apothem
      RPC : https://erpc.apothem.network
      WSS : wss://ws.apothem.network/ws
      PluginContractAddress : 0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
      Chain ID : 51
      

      https://chainlist.org/chain/51

Preliminary RPC

Mainnet Websocket
wss://ws.xinfin.network

Compeleted : The following four RPCs can respond to requests with "Oracle request received" and complete within the limits of OCA's four seats.

Mainnet RPC
https://xdcpayrpc.blocksscan.io/
https://rpc-xdc.icecreamswap.com/
https://erpc.xdcrpc.com/
https://earpc.xinfin.network/

ERROR : The following five RPCs display the same error as the image.

Mainnet RPC - ERROR -
https://xdcfnode1.goplugin.co/
https://rpc.xinfin.network/
https://rpc.xdcrpc.com/
https://rpc1.xinfin.network/
http://my_fullnode_ip:8989/

Apothem(default)
Screenshot by Dropbox Capture.png

secrets.toml

  • Modify secrets.toml with appropriate Keystore and Database URL
    13-3
    nano secrets.toml
    
    secrets.toml (Sample)
    [Password]
    Keystore = 'uXgNT04ZvGLBe%CoZFn8R%NJ!'
    [Database]
    URL = 'postgresql://postgres:NIMh8ePEg58881F88DCw2wnsN0zX82@127.0.0.1:5432/plugin_mainnet_db?sslmode=disable'
    

Note: This password uses the password used in the command 9-5. Restriction for Database Password
- Must be at least 16 characters long
- Must not comprise: Leading or trailing whitespace / user's API email

Screenshot by Dropbox Capture.png

14. Install and build all plugin dependencies

14-1
cd ~/pluginV2/ && sudo apt install build-essential
# y

Screenshot by Dropbox Capture.png

14-2
make install

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.png

15. Setup the profile

Modify the .profile file in $Home directory of the admin account with below content and run the command “source ~/.profile”

15-1
nano ~/.profile
15-2
GOROOT=/usr/local/go
GOPATH=$HOME/go
PATH=$GOPATH/bin:$GOROOT/bin:$PATH
SECURE_COOKIES=false

Screenshot by Dropbox Capture.png

15-3
source ~/.profile

Screenshot by Dropbox Capture.png

16. Start the plugin node

16-1
plugin --admin-credentials-file apicredentials.txt -c config.toml -s secrets.toml node start

Please provide a valid email and password from apicredentials.txt which will be used to login to http://localhost:6688
Screenshot by Dropbox Capture.png

To run a node in the background, you can add & at the end of the command. However, I recommend installing pm2 for this purpose. Please follow the steps below.

To stop the flowing logs, press Control + C. This will pause the logs and at the same time, you won't be able to access the dashboard.

Screenshot by Dropbox Capture.png

16-2
cd ~/pluginV2/ && npm install pm2 -g

The command npm install pm2 -g installs the pm2 package globally. Global installation is done to make pm2 available throughout the system.
Therefore, you can use the pm2 command from any directory. Even if you run it in the home directory and then move to another directory, pm2 will still be available.

【日本語】

npm install pm2 -gコマンドは、グローバルにpm2パッケージをインストールします。グローバルインストールは、システム全体でpm2を使用できるようにするために行われます。

したがって、どのディレクトリにいてもpm2コマンドを使用することができます。ホームディレクトリで実行した場合でも、他のディレクトリに移動しても、pm2は利用可能です。

Screenshot by Dropbox Capture.png

16-3
cat > NodeStartPM2.sh
# Of course, you can also use `nano`.

Copy and paste the following script, and close it with Control + D.

16-4
echo "<<<<<<<<<------------------STARTING PLUGIN NODE--------------------->>>>>>>>>"
plugin --admin-credentials-file apicredentials.txt -c config.toml -s secrets.toml node start
echo "<<<<<<<<<<<-------------------Plugin node is running .. use "pm2 status" to check the status-------->>>>>>>>>>>"
# Press enter on the next line and close the terminal by pressing Control + D

Screenshot by Dropbox Capture.png
Screenshot by Dropbox Capture.png

16-5
ls -la
# ll

Screenshot by Dropbox Capture.png

Start Plugin Node

16-6
pm2 start NodeStartPM2.sh

Screenshot by Dropbox Capture.png

pm2 startup

If the server is restarted as it is, the pm2 process will not start automatically. To start it automatically even if the server is restarted, please execute the following command:

16-7
pm2 startup

Then, you will see the following message:

[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:

Copy and paste the command in the yellow box as instructed and press enter.

Screenshot by Dropbox Capture.png

Finally, make sure that the following screen is displayed.

Screenshot by Dropbox Capture.png

Then, it is recommended to execute the following command before actually restarting the server:

16-8
pm2 save
16-9
sudo reboot

Screenshot by Dropbox Capture.png

After restarting the server, please log in again and execute the following command:

16-9
pm2 ls

Make sure that NodeStartPM2 is running.

Screenshot by Dropbox Capture.png

Log in to the dashboard

provide a valid email and password from apicredentials.txt which will be used to login to http://localhost:6688.

16-7
cat apicredentials.txt 
echo http://$(hostname -i):6688

Screenshot by Dropbox Capture.png
Screenshot by Dropbox Capture.png
Screenshot by Dropbox Capture.png

Deposit XDC and PLI to Node Address.

Screenshot by Dropbox Capture.png

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

Screenshot by Dropbox Capture.png

Setup of Job and Deployment of Contract

17. Oracle Contract

Using Remix, create an Oracle contract.

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

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.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.

  • Mainnet PLI Contract :
    Mainnet PLI Contract
    0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
    
  • Apothem PLI Contract :
    Apothem PLI Contract
    0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
    

Screenshot by Dropbox Capture.png
Screenshot by Dropbox Capture.png

Mainnet PLI Contract
0xFf7412Ea7C8445C46a8254dFB557Ac1E48094391
Apothem PLI Contract
0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1

18. Job setup

type = "directrequest"
schemaVersion = 1
name = "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" allowUnrestrictedNetworkAccess="true"]

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)"]

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

  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

Sample Job Code - 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 -
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

# Bitrue

Sample Job Code - 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

Sample Job Code - Kucoin -
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

  • 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)"]

# Coinranking

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 -
coinranking Sample
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

Coinpaprika - Free
fetch [type=http method=GET url="https://api.coinpaprika.com/v1/tickers/cgo-comtech-gold?quotes=USD" allowUnrestrictedNetworkAccess="true"]
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\\"]"]
Sample Job Code - Coinpaprika -
Coinpaprika Sample
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

Tradermade
fetch [type=http method=GET url="https://marketdata.tradermade.com/api/v1/live?api_key=YOUR_API_KEY&currency=USDJPY" allowUnrestrictedNetworkAccess="true"]
Sample Job Code - Tradermade -
Tradermade Sample
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 
"""

# Bitfinex

Bitfinex
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 -
Bitfinex Sample
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

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)"]
Sample Job Code - BitMart -
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
"""

Bitrue
Screenshot by Dropbox Capture.png

Cryptocomapre
Screenshot by Dropbox Capture.png

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

19. CONSUMER CONTRACT

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

image.png

CryptocompareAPI
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "@goplugin/test/src/v0.8/PluginClient.sol";
import "@goplugin/test/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: 0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1
* B. Oracle: 0x6090149792dAAeE9D1D568c9f9a6F6B46AA29eFD (Plugin DevRel)
* C. jobId: ca98366cc7314957b8c012c72f05aeeb
*
*/

constructor() ConfirmedOwner(msg.sender) {
setPluginToken(0x33f4212b027E22aF7e6BA21Fc572843C0D701CD1);//Pli address as mentioned in ‘A’
setPluginOracle(0x06b321e3da4a5c67fBF074bb48C6408074bDD785);//Oracle address
jobId = "53034a3f099949f787937a96fa3e9a32";//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",
// "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD"
// );

req.add(
"get",
"https://min-api.cryptocompare.com/data/price?fsym=XDC&tsyms=USD"
);

// Set the path to find the desired data in the API response, where the response format is:
// {"RAW":
// {"ETH":
// {"USD":
// {
// "VOLUME24HOUR": xxx.xxx,
// }
// }
// }
// }
// request.add("path", "RAW.ETH.USD.VOLUME24HOUR"); // Plugin nodes prior to 1.0.0 support this format
//req.add("path", "RAW.ETH.USD.VOLUME24HOUR"); // Plugin nodes 1.0.0 and later support this format
//req.add("path", "USD"); // Plugin nodes 1.0.0 and later support this format
//req.add("path", "Result,data,result"); // Plugin nodes 1.0.0 and later support this format

// 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"
);
}
}

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.png

Git Command

The following command is commonly used when using Git for version control.

git fetch

git fetch
  • git fetch: Retrieves the latest changes from the remote repository, but does not apply them to the local branch. The fetched changes can be used later for merging or checking out.

git log --oneline origin/main

git log --oneline origin/main
  • git log --oneline origin/main: Displays the commit history of the origin/main branch in a one-line format. The --oneline option shows the commit messages in a concise form.
    Screenshot by Dropbox Capture.png

    In the given output of the git log --oneline origin/main command, there are two mentions of "HEAD".

    • b7a5ee2 (HEAD -> main) contracts updated: This line indicates that the current branch, main, is pointing to the commit with the hash b7a5ee2. The (HEAD -> main) part shows the current branch reference.

    • 89b2f7c (origin/main, origin/HEAD) PLI value changes: This line indicates that the remote branch origin/main and the symbolic reference origin/HEAD are both pointing to the commit with the hash 89b2f7c. The (origin/main, origin/HEAD) part shows the references associated with this commit.

    The "HEAD" reference in Git represents the currently checked out commit or branch. It can be used to navigate and make changes within the repository.

git merge

git merge
  • git merge: Merges a branch into the current branch. It incorporates the changes from the specified branch into the current branch, combining the commit histories.

git pull

git pull
  • git pull: Fetches the latest changes from the remote repository and merges them into the current branch. It is a combination of git fetch and git merge.
    Screenshot by Dropbox Capture.png

git chekout

git chekout 1a2b3c4d
  • git checkout 1a2b3c4d: Switches to the specified commit or branch. 1a2b3c4d is the commit hash or branch name. This command allows you to go back to a specific commit state or move to a different branch. However, it does not create a new branch.

Reset

This command is very dangerous. It will completely delete. Once deleted, it cannot be undone.

cd ~ && sudo rm -rf go/ go1.20.6.linux-amd64.tar.gz /usr/local/go pluginV2/

Remix.ethereum & MetaMask

Compeleted : The following four RPCs can respond to requests with "Oracle request received" and complete within the limits of OCA's five seats.

ERROR : The following four RPCs display the same error as the image.

MetaMask

Screenshot by Dropbox Capture.png

Remix.ethereum

Screenshot by Dropbox Capture.png

Oracle.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
import "@goplugin/test/src/v0.7/Operator.sol";

Screenshot by Dropbox Capture.png

Compile

Screenshot by Dropbox Capture.png

Deploy

Screenshot by Dropbox Capture.png

APIConsumerContract

Screenshot by Dropbox Capture.png

Screenshot by Dropbox Capture.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?