From 286c752608bd7608d86ea7feca14abfa0c5f1bc5 Mon Sep 17 00:00:00 2001
From: XFT-dev <XFT-DEV@Offshit>
Date: Thu, 15 Apr 2021 18:25:01 +0300
Subject: [PATCH] adding scripts

---
 frontend/Shifting/README.md                   |   2 +
 frontend/Shifting/scripts/js/index.js         | 115 ++++
 frontend/Shifting/scripts/js/package.json     |  14 +
 frontend/Shifting/scripts/js/shift-abi.json   |  66 ++
 frontend/Shifting/scripts/js/token-abi.json   | 640 ++++++++++++++++++
 frontend/Shifting/scripts/py/requirements.txt |   1 +
 frontend/Shifting/scripts/py/script.py        |  81 +++
 frontend/Shifting/scripts/py/shift-abi.json   |  66 ++
 frontend/Shifting/scripts/py/token-abi.json   | 640 ++++++++++++++++++
 frontend/Shifting/{ => website}/Shift.html    |   0
 frontend/Shifting/{ => website}/faucet.html   |   0
 frontend/Shifting/{ => website}/mini.css      |   0
 12 files changed, 1625 insertions(+)
 create mode 100644 frontend/Shifting/scripts/js/index.js
 create mode 100644 frontend/Shifting/scripts/js/package.json
 create mode 100644 frontend/Shifting/scripts/js/shift-abi.json
 create mode 100644 frontend/Shifting/scripts/js/token-abi.json
 create mode 100644 frontend/Shifting/scripts/py/requirements.txt
 create mode 100644 frontend/Shifting/scripts/py/script.py
 create mode 100644 frontend/Shifting/scripts/py/shift-abi.json
 create mode 100644 frontend/Shifting/scripts/py/token-abi.json
 rename frontend/Shifting/{ => website}/Shift.html (100%)
 rename frontend/Shifting/{ => website}/faucet.html (100%)
 rename frontend/Shifting/{ => website}/mini.css (100%)

diff --git a/frontend/Shifting/README.md b/frontend/Shifting/README.md
index 1f3b70a..db53d8d 100644
--- a/frontend/Shifting/README.md
+++ b/frontend/Shifting/README.md
@@ -1,2 +1,4 @@
 # Shifting frontend
 
+website directory: browser based frontend (requires metamask for interaction).
+scripts directory: scripts for interacting with the contracts. 
\ No newline at end of file
diff --git a/frontend/Shifting/scripts/js/index.js b/frontend/Shifting/scripts/js/index.js
new file mode 100644
index 0000000..848340b
--- /dev/null
+++ b/frontend/Shifting/scripts/js/index.js
@@ -0,0 +1,115 @@
+const Web3 = require("web3");
+const fs = require('fs');
+const readline = require("readline");
+
+let web3 = new Web3(Web3.givenProvider || "ws://localhost:8545")
+let shift_abi = fs.readFileSync('shift-abi.json');
+let shift = new web3.eth.Contract(JSON.parse(shift_abi), "0x6bE4C94052BF34e09d67C255D9Fe564c5abd4f95");
+
+let token_abi = fs.readFileSync('token-abi.json');
+let tokenA = new web3.eth.Contract(JSON.parse(token_abi), "0x1190fb1B00D20656549cdFF689E55D072BA764f3");
+let tokenB = new web3.eth.Contract(JSON.parse(token_abi), "0x0e1BFf82509994170026f47f1d0857fB275c3003");
+
+
+web3.eth.accounts.wallet.add(web3.eth.accounts.privateKeyToAccount("0x0"));
+
+async function approve(num) {
+    let amount = web3.utils.toWei(parseFloat(num).toString(), 'ether');
+    const gasPrice = await web3.eth.getGasPrice();
+    const gasEstimate = await tokenA.methods.approve(shift._address, amount).estimateGas({ from: web3.eth.accounts.wallet[0].address });
+
+    if (amount => 0) {
+        let approvalAmount;
+        tokenA.methods.allowance(web3.eth.accounts.wallet[0].address, shift._address).call({ from: web3.eth.accounts.wallet[0].address }).then(data => approvalAmount = data);
+        if (approvalAmount >= amount) {
+            console.log("already approved");
+        } else {
+            tokenA.methods.approve(shift._address, amount).send({ from: web3.eth.accounts.wallet[0].address, gasPrice: gasPrice, gas: gasEstimate }).then(console.log);
+        }
+    } else {
+        console.log("input a number");
+    }
+
+    await sleep(20000);
+}
+
+async function shifter(num) {
+    let A_aggregator = "0xECe365B379E1dD183B20fc5f022230C044d51404";
+    let B_aggregator = "0xab4a352ac35dFE83221220D967Db41ee61A0DeFa";
+    let amount = web3.utils.toWei(parseFloat(num).toString(), 'ether');
+
+    const gasPrice = await web3.eth.getGasPrice();
+    const gasEstimate = await shift.methods.shift(amount, A_aggregator, B_aggregator).estimateGas({ from: web3.eth.accounts.wallet[0].address });
+
+    if (amount > 0) {
+        shift.methods.shift(amount, A_aggregator, B_aggregator).send({ from: web3.eth.accounts.wallet[0].address, gasPrice: gasPrice, gas: gasEstimate }).then(console.log);
+    }
+}
+
+async function faucet() {
+    const gasPrice = await web3.eth.getGasPrice();
+    const gasEstimate = await shift.methods.faucet().estimateGas({ from: web3.eth.accounts.wallet[0].address });
+    shift.methods.faucet().send({ from: web3.eth.accounts.wallet[0].address, gasPrice: gasPrice, gas: gasEstimate }).then(console.log);
+    await sleep(6000);
+}
+
+function sleep(ms) {
+    return new Promise((resolve) => {
+        setTimeout(resolve, ms);
+    });
+}
+
+async function handle_shift(n) {
+    await approve(n);
+    await shifter(n);
+}
+
+
+
+async function handle_args(arg) {
+    switch (arg) {
+        case "0":
+            await faucet();
+            break;
+        case "1":
+            rl.question("Amount of tokens to shift: ", function (given_amount) {
+                handle_shift(given_amount);
+            });
+            break;
+        case "2":
+            await tokenA.methods.balanceOf(web3.eth.accounts.wallet[0].address).call().then(t => console.log(`current xftTM ${t/1e18}`));
+            break;
+        case "3":
+            await tokenB.methods.balanceOf(web3.eth.accounts.wallet[0].address).call().then(t => console.log(`current xftTB ${t/1e18}`));
+            break;
+    }
+    rl.close();
+}
+
+const rl = readline.createInterface({
+    input: process.stdin,
+    output: process.stdout
+});
+
+console.log(`
+    Request funds from the faucet -> 0
+    shift tokens -> 1
+    get xftTM balance -> 2
+    get xftTB balance -> 3
+    EXIT -> 4
+
+`);
+rl.question("Please select an option: ", function (option) {
+    switch (option) {
+        case "4":
+            rl.close();
+        default:
+            handle_args(option);
+    }
+});
+
+rl.on("close", function () {
+    console.log("\nBYE -_-");
+    process.exit(0);
+});
+
diff --git a/frontend/Shifting/scripts/js/package.json b/frontend/Shifting/scripts/js/package.json
new file mode 100644
index 0000000..cb59165
--- /dev/null
+++ b/frontend/Shifting/scripts/js/package.json
@@ -0,0 +1,14 @@
+{
+  "name": "script",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC",
+  "devDependencies": {
+    "web3": "^1.3.5"
+  }
+}
diff --git a/frontend/Shifting/scripts/js/shift-abi.json b/frontend/Shifting/scripts/js/shift-abi.json
new file mode 100644
index 0000000..d506d5d
--- /dev/null
+++ b/frontend/Shifting/scripts/js/shift-abi.json
@@ -0,0 +1,66 @@
+[
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "_tokenA",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "_tokenB",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "_chainlink",
+                "type": "address"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "constructor"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "value",
+                "type": "uint256"
+            }
+        ],
+        "name": "Shifted",
+        "type": "event"
+    },
+    {
+        "inputs": [],
+        "name": "faucet",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            },
+            {
+                "internalType": "address",
+                "name": "_A",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "_B",
+                "type": "address"
+            }
+        ],
+        "name": "shift",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    }
+]
\ No newline at end of file
diff --git a/frontend/Shifting/scripts/js/token-abi.json b/frontend/Shifting/scripts/js/token-abi.json
new file mode 100644
index 0000000..3f53a46
--- /dev/null
+++ b/frontend/Shifting/scripts/js/token-abi.json
@@ -0,0 +1,640 @@
+[
+    {
+        "inputs": [],
+        "stateMutability": "nonpayable",
+        "type": "constructor"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "owner",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            },
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "value",
+                "type": "uint256"
+            }
+        ],
+        "name": "Approval",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": false,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "Paused",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "previousAdminRole",
+                "type": "bytes32"
+            },
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "newAdminRole",
+                "type": "bytes32"
+            }
+        ],
+        "name": "RoleAdminChanged",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "sender",
+                "type": "address"
+            }
+        ],
+        "name": "RoleGranted",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "sender",
+                "type": "address"
+            }
+        ],
+        "name": "RoleRevoked",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "from",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "to",
+                "type": "address"
+            },
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "value",
+                "type": "uint256"
+            }
+        ],
+        "name": "Transfer",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": false,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "Unpaused",
+        "type": "event"
+    },
+    {
+        "inputs": [],
+        "name": "BURNER_ROLE",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "DEFAULT_ADMIN_ROLE",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "MINTER_ROLE",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "PAUSER_ROLE",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "owner",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            }
+        ],
+        "name": "allowance",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "approve",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "balanceOf",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "burn",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "from",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "burn",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "burnFrom",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "decimals",
+        "outputs": [
+            {
+                "internalType": "uint8",
+                "name": "",
+                "type": "uint8"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "subtractedValue",
+                "type": "uint256"
+            }
+        ],
+        "name": "decreaseAllowance",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            }
+        ],
+        "name": "getRoleAdmin",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "grantRole",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "hasRole",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "addedValue",
+                "type": "uint256"
+            }
+        ],
+        "name": "increaseAllowance",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "to",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "mint",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "name",
+        "outputs": [
+            {
+                "internalType": "string",
+                "name": "",
+                "type": "string"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "pause",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "paused",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "renounceRole",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "revokeRole",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes4",
+                "name": "interfaceId",
+                "type": "bytes4"
+            }
+        ],
+        "name": "supportsInterface",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "symbol",
+        "outputs": [
+            {
+                "internalType": "string",
+                "name": "",
+                "type": "string"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "totalSupply",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "recipient",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "transfer",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "sender",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "recipient",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "transferFrom",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "unpause",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    }
+]
\ No newline at end of file
diff --git a/frontend/Shifting/scripts/py/requirements.txt b/frontend/Shifting/scripts/py/requirements.txt
new file mode 100644
index 0000000..b51922a
--- /dev/null
+++ b/frontend/Shifting/scripts/py/requirements.txt
@@ -0,0 +1 @@
+web3==5.12.1
diff --git a/frontend/Shifting/scripts/py/script.py b/frontend/Shifting/scripts/py/script.py
new file mode 100644
index 0000000..792780c
--- /dev/null
+++ b/frontend/Shifting/scripts/py/script.py
@@ -0,0 +1,81 @@
+from web3.auto.infura.rinkeby import w3
+import json
+
+with open("shift-abi.json", "r") as f:
+    shift_abi = json.load(f)
+
+with open("token-abi.json", "r") as f:
+    token_abi = json.load(f)
+    
+priv_key = "0x0"
+
+w3.eth.defaultAccount = w3.eth.account.privateKeyToAccount(priv_key)
+
+shift_contract = w3.eth.contract(abi=shift_abi, address=w3.toChecksumAddress("0x6bE4C94052BF34e09d67C255D9Fe564c5abd4f95"))
+tokenA = w3.eth.contract(abi=token_abi, address=w3.toChecksumAddress("0x1190fb1B00D20656549cdFF689E55D072BA764f3"))
+tokenB = w3.eth.contract(abi=token_abi, address=w3.toChecksumAddress("0x0e1BFf82509994170026f47f1d0857fB275c3003"))
+
+def approve(amount):
+    txn = tokenA.functions.approve(shift_contract.address, int(amount*1e18)).buildTransaction({
+        'chainId': 4, 
+        'gas': 500000,
+        'gasPrice': w3.eth.gasPrice,
+        'nonce': w3.eth.getTransactionCount(w3.eth.defaultAccount.address)
+        })
+    signed_txn = w3.eth.account.signTransaction(txn, '0x047eb26808901c4fdf33262a3d9ea7e6a15f5683f9f60eef1b5a615fc2b3756a')
+    txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction)
+    tx_receipt = w3.eth.waitForTransactionReceipt(txn_hash)
+
+def shift(amount):
+    A_aggregator = "0xECe365B379E1dD183B20fc5f022230C044d51404";
+    B_aggregator = "0xab4a352ac35dFE83221220D967Db41ee61A0DeFa";
+    txn = shift_contract.functions.shift(int(amount*1e18), A_aggregator, B_aggregator).buildTransaction({
+        'chainId': 4, 
+        'gas': 500000,
+        'gasPrice': w3.eth.gasPrice,#w3.eth.gasPrice,
+        'nonce': w3.eth.getTransactionCount(w3.eth.defaultAccount.address)
+        })
+    signed_txn = w3.eth.account.signTransaction(txn, '0x047eb26808901c4fdf33262a3d9ea7e6a15f5683f9f60eef1b5a615fc2b3756a')
+    txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction)
+    tx_receipt = w3.eth.waitForTransactionReceipt(txn_hash)
+
+def faucet():
+    txn = shift_contract.functions.faucet().buildTransaction({
+        'chainId': 4, 
+        'gas': 500000,
+        'gasPrice': w3.eth.gasPrice,#w3.eth.gasPrice,
+        'nonce': w3.eth.getTransactionCount(w3.eth.defaultAccount.address)
+        })
+    signed_txn = w3.eth.account.signTransaction(txn, '0x047eb26808901c4fdf33262a3d9ea7e6a15f5683f9f60eef1b5a615fc2b3756a')
+    txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction)
+    tx_receipt = w3.eth.waitForTransactionReceipt(txn_hash)
+
+def take_input():
+    t = input("please select an option: ")
+    if t == "1":
+        n = input("amount of tokens to shift: ")
+        approve(int(n))
+        shift(int(n))
+    elif t == "2":
+        print("requesting funds")
+        faucet()
+        print("funds transfered :D")
+    elif t == "3":
+        print(tokenA.functions.balanceOf(w3.eth.defaultAccount.address).call({'from': w3.eth.defaultAccount.address}) / 1e18)
+    elif t == "4":
+        print(tokenB.functions.balanceOf(w3.eth.defaultAccount.address).call({'from': w3.eth.defaultAccount.address}) / 1e18)
+    elif t == "0":
+        exit(0);
+    else:
+        print("invalid option provided")
+if __name__ == "__main__":
+    help_menu = """
+shift tokens: 1
+request funds from the faucet: 2
+check xftTM balance: 3
+check xftTB balance: 4
+exit : 0 
+    """
+    print(help_menu) 
+    while True:
+        take_input()
\ No newline at end of file
diff --git a/frontend/Shifting/scripts/py/shift-abi.json b/frontend/Shifting/scripts/py/shift-abi.json
new file mode 100644
index 0000000..d506d5d
--- /dev/null
+++ b/frontend/Shifting/scripts/py/shift-abi.json
@@ -0,0 +1,66 @@
+[
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "_tokenA",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "_tokenB",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "_chainlink",
+                "type": "address"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "constructor"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "value",
+                "type": "uint256"
+            }
+        ],
+        "name": "Shifted",
+        "type": "event"
+    },
+    {
+        "inputs": [],
+        "name": "faucet",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            },
+            {
+                "internalType": "address",
+                "name": "_A",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "_B",
+                "type": "address"
+            }
+        ],
+        "name": "shift",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    }
+]
\ No newline at end of file
diff --git a/frontend/Shifting/scripts/py/token-abi.json b/frontend/Shifting/scripts/py/token-abi.json
new file mode 100644
index 0000000..3f53a46
--- /dev/null
+++ b/frontend/Shifting/scripts/py/token-abi.json
@@ -0,0 +1,640 @@
+[
+    {
+        "inputs": [],
+        "stateMutability": "nonpayable",
+        "type": "constructor"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "owner",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            },
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "value",
+                "type": "uint256"
+            }
+        ],
+        "name": "Approval",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": false,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "Paused",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "previousAdminRole",
+                "type": "bytes32"
+            },
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "newAdminRole",
+                "type": "bytes32"
+            }
+        ],
+        "name": "RoleAdminChanged",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "sender",
+                "type": "address"
+            }
+        ],
+        "name": "RoleGranted",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "sender",
+                "type": "address"
+            }
+        ],
+        "name": "RoleRevoked",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "from",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "to",
+                "type": "address"
+            },
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "value",
+                "type": "uint256"
+            }
+        ],
+        "name": "Transfer",
+        "type": "event"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": false,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "Unpaused",
+        "type": "event"
+    },
+    {
+        "inputs": [],
+        "name": "BURNER_ROLE",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "DEFAULT_ADMIN_ROLE",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "MINTER_ROLE",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "PAUSER_ROLE",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "owner",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            }
+        ],
+        "name": "allowance",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "approve",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "balanceOf",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "burn",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "from",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "burn",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "burnFrom",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "decimals",
+        "outputs": [
+            {
+                "internalType": "uint8",
+                "name": "",
+                "type": "uint8"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "subtractedValue",
+                "type": "uint256"
+            }
+        ],
+        "name": "decreaseAllowance",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            }
+        ],
+        "name": "getRoleAdmin",
+        "outputs": [
+            {
+                "internalType": "bytes32",
+                "name": "",
+                "type": "bytes32"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "grantRole",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "hasRole",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "spender",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "addedValue",
+                "type": "uint256"
+            }
+        ],
+        "name": "increaseAllowance",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "to",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "mint",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "name",
+        "outputs": [
+            {
+                "internalType": "string",
+                "name": "",
+                "type": "string"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "pause",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "paused",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "renounceRole",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes32",
+                "name": "role",
+                "type": "bytes32"
+            },
+            {
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "revokeRole",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "bytes4",
+                "name": "interfaceId",
+                "type": "bytes4"
+            }
+        ],
+        "name": "supportsInterface",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "symbol",
+        "outputs": [
+            {
+                "internalType": "string",
+                "name": "",
+                "type": "string"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "totalSupply",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "recipient",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "transfer",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "sender",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "recipient",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            }
+        ],
+        "name": "transferFrom",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "unpause",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    }
+]
\ No newline at end of file
diff --git a/frontend/Shifting/Shift.html b/frontend/Shifting/website/Shift.html
similarity index 100%
rename from frontend/Shifting/Shift.html
rename to frontend/Shifting/website/Shift.html
diff --git a/frontend/Shifting/faucet.html b/frontend/Shifting/website/faucet.html
similarity index 100%
rename from frontend/Shifting/faucet.html
rename to frontend/Shifting/website/faucet.html
diff --git a/frontend/Shifting/mini.css b/frontend/Shifting/website/mini.css
similarity index 100%
rename from frontend/Shifting/mini.css
rename to frontend/Shifting/website/mini.css
-- 
GitLab