import {UPDATE_STATUS_EVENT_TAG, UPDATE_POST_ID_FETCH_TAG, UPDATE_STATUS_POST_LOAD_TAG} from "../utils/EventTags";
import Web3 from "web3";
import {CONTRACT_ABI, CONTRACT_ADDRESS} from "../contract/ContractMetadata";
import {Post} from "../models/Post";
import {ShowNotification} from "../utils/ShowNotification";
import AlertNotification from "../artifacts/AlertNotification";
/**
* This function loads the web3 provider, asks for connection, connects to the contract and prepares everything before loading the web-app
* @returns {Promise<string>}
* @async
* @method
* @example
* loadWeb3().then((r)=>{
* console.log(r)
* }).catch((e)=>{
* console.log(e)
* })
*
* @see loadReadOnlyMode
*/
export async function LoadWeb3() {
if (window.ethereum) {
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Waiting for approval"}))
window.web3 = new Web3(window.ethereum);
try{
await window.ethereum.enable();
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Loading contract"}))
window.contract = await loadContract();
console.log("Contract loaded!");
console.log(window.contract);
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Welcome"}))
return Promise.resolve("Done");
}catch(e){
console.log(e);
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Permission Denied"}))
await loadReadOnlyMode()
}
}
else if(window.web3){
window.web3 = new Web3(window.web3.currentProvider);
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Loading contract"}))
window.contract = await loadContract();
console.log("Contract loaded!");
console.log(window.contract);
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Welcome"}))
return Promise.resolve("Done");
}
else{
await loadReadOnlyMode();
return Promise.resolve("Done");
}
}
/**
* This function loads the web-app in read-only mode when the web3 provider is missing from the browser.
* @returns {Promise<string>}
* @async
* @example
* await loadReadOnlyMode();
*/
async function loadReadOnlyMode(){
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Connecting to node"}));
window.web3 = await new Web3(new Web3.providers.HttpProvider("https://data-seed-prebsc-2-s1.binance.org:8545/"));
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Loading contract"}));
window.contract = await loadContract();
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Welcome"}));
ShowNotification(<AlertNotification theme={"warning"} message={"Launching in read-only mode"}/>);
console.log("We can't detect Metamask or any wallet provider in this browser! Launching in Read-only mode!");
await alert("We can't detect Metamask or any wallet provider on this browser. Without that you will only be able to read articles but can not comment or add new posts.");
return Promise.resolve("Done");
}
/**
* This function returns the contract after loading it
* @async
* @returns {Promise<*>}
*
* @example
* window.contract = await loadContract();
*/
async function loadContract(){
return await new window.web3.eth.Contract(CONTRACT_ABI, CONTRACT_ADDRESS);
}
/**
* This function loads post data from the contract to the global variables.
* @async
* @param {number} limit - The number of posts you want to load. 0 or <0 will fetch all the posts.
* @returns {Promise<string>}
*
* @example
* let list = loadPosts(5)
* //returns top 5 latest posts
*
* let list2 = loadPosts()
* //returns all the posts
*
* let list3 = loadPosts(-1)
* //returns all the posts
*
* @see Post
*/
export async function loadPosts(limit=-1) {
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_POST_LOAD_TAG, {detail: "Loading index"}))
window.postBankIndex = await window.contract.methods.getPostBankIndex().call();
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_POST_LOAD_TAG, {detail: "Loading posts"}))
window.postBank = [];
if(limit<0) limit = window.postBankIndex.length
for(let id of window.postBankIndex.slice(window.postBankIndex.length - limit, window.postBankIndex.length)){
window.dispatchEvent(new CustomEvent(UPDATE_POST_ID_FETCH_TAG, {detail: id}))
let rawData = await window.contract.methods.getPost(id).call();
let post = new Post({id: id,
title: rawData.heading,
body: rawData.body,
location: rawData.location,
timestamp: rawData.timestamp,
author: rawData.author})
window.postBank.push(post);
}
console.log(window.postBankIndex);
console.log(window.postBank);
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Done"}))
return Promise.resolve("Done");
}
/**
* This function loads post data from the contract and passes it from the promise
* @async
* @param {number} limit - The number of posts you want to load. 0 or <0 will fetch all the posts.
* @returns {Promise<string>}
*
* @example
* getPosts(5).then({list}=>{
* console.log(e);
* })
* //returns top 5 latest posts
*
* getPosts().then({list}=>{
* console.log(e);
* })
* //returns all the posts
*
* getPosts(-1).then({list}=>{
* console.log(e);
* })
* //returns all the posts
* @returns {Promise<Post[]>}
*
* @see Post
*/
export async function getPosts(limit=-1) {
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_POST_LOAD_TAG, {detail: "Loading index"}))
let postBankIndex = await window.contract.methods.getPostBankIndex().call();
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_POST_LOAD_TAG, {detail: "Loading posts"}))
let postBank = [];
if(limit<0) limit = postBankIndex.length
for(let id of postBankIndex.slice(postBankIndex.length - limit, postBankIndex.length)){
window.dispatchEvent(new CustomEvent(UPDATE_POST_ID_FETCH_TAG, {detail: id}))
let rawData = await window.contract.methods.getPost(id).call();
let post = new Post({id:id,
title: rawData.heading,
body: rawData.body,
location: rawData.location,
timestamp: rawData.timestamp,
author: rawData.author})
postBank.push(post);
}
console.log(window.postBankIndex);
console.log(window.postBank);
window.dispatchEvent(new CustomEvent(UPDATE_STATUS_EVENT_TAG, {detail: "Done"}))
return Promise.resolve(postBank);
}