// constants
import Web3EthContract from "web3-eth-contract";
import Web3 from "web3";
// log
import { fetchData } from "../data/dataActions";
const connectRequest = () => {
return {
type: "CONNECTION_REQUEST",
};
};
const connectSuccess = (payload) => {
return {
type: "CONNECTION_SUCCESS",
payload: payload,
};
};
const connectFailed = (payload) => {
return {
type: "CONNECTION_FAILED",
payload: payload,
};
};
const updateAccountRequest = (payload) => {
return {
type: "UPDATE_ACCOUNT",
payload: payload,
};
};
export const connect = () => {
return async (dispatch) => {
dispatch(connectRequest());
const abiResponse = await fetch("/config/abi.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
const abi = await abiResponse.json();
const configResponse = await fetch("/config/config.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
const CONFIG = await configResponse.json();
const { ethereum } = window;
const metamaskIsInstalled = ethereum && ethereum.isMetaMask;
if (metamaskIsInstalled) {
Web3EthContract.setProvider(ethereum);
let web3 = new Web3(ethereum);
try {
const accounts = await ethereum.request({
method: "eth_requestAccounts",
});
const networkId = await ethereum.request({
method: "net_version",
});
if (networkId == CONFIG.NETWORK.ID) {
const SmartContractObj = new Web3EthContract(
abi,
CONFIG.CONTRACT_ADDRESS
);
dispatch(
connectSuccess({
account: accounts[0],
smartContract: SmartContractObj,
web3: web3,
})
);
// Add listeners start
ethereum.on("accountsChanged", (accounts) => {
dispatch(updateAccount(accounts[0]));
});
ethereum.on("chainChanged", () => {
window.location.reload();
});
// Add listeners end
} else {
dispatch(connectFailed(`Change network to ${CONFIG.NETWORK.NAME}.`));
}
} catch (err) {
dispatch(connectFailed("Something went wrong."));
}
} else {
dispatch(connectFailed("Install Metamask."));
}
};
};
export const updateAccount = (account) => {
return async (dispatch) => {
dispatch(updateAccountRequest({ account: account }));
dispatch(fetchData(account));
};
};
Metamask extension is working fine in desktop but the issue is it not working on Mobile, it is not openning the metamask app, we dont know now how to solve this issue...
If anyone here who can help will be great. We have a solution for this instead of using metamask, we want to use wallet connect integration, but we dont know how to do that too. We have read the docs but we are too confuse in it....
On mobile connecting to wallets will not work in your normal chrome/safari browsers- apple or other mobile creators do not allow this you can only connect your wallet by using the browser in your metamask app on your phone.
ie.
navigate to metamask or whichever wallet you are using on your phone
open the browser in that app
go to the website you need
I've found a way with deeplinking to work with Android and IOS from the browser, it solved my problem with opening MetaMask and redirect my app there ( or installing if its not installed )
It's the complete code, you can find this part of code here :
https://github.com/EhsanParsania/MetaMask-React-sample/blob/main/src/components/MetaMaskInstallModal.js#L74
or clone it and run to use and check all features :
https://github.com/EhsanParsania/MetaMask-React-sample
and this is the specific code :
function connectToPhoneMetamsk() {
const metamaskAppDeepLink = "https://metamask.app.link/dapp/" + YOUR_ORIGIN ; // put your origin here without http:// ro https://
return (
<a href={metamaskAppDeepLink}>
<Button>Connect to MetaMask</Button>
</a>
);
}
Related
I am using react-native-google-mobile-ads in my App to display Interstitials and Rewarded Ads. Currently, I am trying to handle the EEA consent correctly.
This is my code:
const interstitial = InterstitialAd.createForAdRequest(adUnitId, {
...ADS_REQUEST_OPTIONS,
requestNonPersonalizedAdsOnly: !userChoices.selectPersonalisedAds,
});
Here is my code:
config.js:
export const TEST_DEVICE_ID = "EMULATOR";
export const INFO_REQUEST_CONFIGURATION = {
tagForUnderAgeOfConsent: true,
testDeviceIdentifiers: [TEST_DEVICE_ID],
// Always ensure debug information is removed for production apps!
...__DEV__ && { debugGeography: AdsConsentDebugGeography.EEA },
};
export const ADS_REQUEST_CONFIGURATION = {
maxAdContentRating: MaxAdContentRating.T,
tagForChildDirectedTreatment: false,
tagForUnderAgeOfConsent: true,
testDeviceIdentifiers: [TEST_DEVICE_ID],
};
export const ADS_REQUEST_OPTIONS = {
requestNonPersonalizedAdsOnly: false,
keywords: [
...
],
};
AdMobContext.jsx:
...
export function AdMobProvider({ children }) {
const requestEEAConsent = async () => {
const consentInfo = await AdsConsent.requestInfoUpdate(INFO_REQUEST_CONFIGURATION);
if (
consentInfo.isConsentFormAvailable &&
consentInfo.status === AdsConsentStatus.REQUIRED
) {
const { status } = await AdsConsent.showForm();
consentInfo.status = status;
}
console.log({ consentInfo });
return consentInfo;
};
const initializeAdmob = async () => {
// Request the respective consent to users in the EEA
await requestEEAConsent();
// Configure the ads requests
await mobileAds().setRequestConfiguration(ADS_REQUEST_CONFIGURATION);
// Initialize the AdMob service
await mobileAds().initialize();
};
useEffect(() => {
initializeAdmob();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
...
}
Will AdMob display ads to users that have not granted the consent?
Do we have to handle this manually or does AdMob manage this for us?
i'M working on a Chat Application project
but im getting this error of fetching friends from the backend(node)
I'm getting the friends data on the console but i'm unable to display it.
this is my Context and States
export const Messenger = () => {
// Context State
const { friends, setFriends, authInfo } = useAuth();
const [loggedUser, setLoggedUser] = useState();
const { updateNotification } = useNotification();
const fetchMessengerUsers = async () => {
try {
const token = getToken();
const config = {
headers: {
authorization: "Bearer " + token,
},
};
const { data } = await client("/get-friends", config);
console.log(data);
setFriends(data);
} catch (error) {
updateNotification("error", "Failed To load the Chat");
}
};
useEffect(() => {
setLoggedUser(localStorage.getItem("auth-token"));
fetchMessengerUsers();
}, []);
then in return i'm mapping all friends to display them
<div className="friends">
{friends && friends.length > 0
? friends.map((fd) => (
<div className="hover-friend">
<Friends friend={fd} />
</div>
))
: "No Friend"}
</div>
It displays No Friend on the browser
this link shows how it appears on the browser
just change your fetchMessengerUsers function.
you need to set setFriends(data.friends)
const fetchMessengerUsers = async () => {
try {
const token = getToken();
const config = {
headers: {
authorization: "Bearer " + token,
},
};
const { data } = await client("/get-friends", config);
console.log(data);
setFriends(data.friends); // you have to set friends array here, earlier you were setting the entire object.
} catch (error) {
updateNotification("error", "Failed To load the Chat");
}
};
I am creating an application that connects volunteers to newcomers using ReactJS. In the app I have developed a chat mechanism that will help newcomers connect with volunteers and vice-versa. I have implemented a feature that displays the featured volunteers with their info and a button that says 'contact'. I have hooked up the contact button so that when pressed the user gets directed to the chat and a new conversation list document is created in MongoDB using the POST request.
The problem I am running into is that the POST request keeps on running every time I click the 'contact' button resulting in multiple duplicates of the username getting rendered. I am struggling with finding a solution to the problem. I would like only one username to get rendered to the page and not have a whole bunch of duplicates. Any help is greatly appreciated.
The GET method that grabs the email and POST method that creates a new document
**VolunterCard.jsx**
React.useEffect(() => {
const getImage = async () => {
let response = await fetch(`/image/cass#gmail.com`);
let data = await response.json();
console.log(`Data is:`, data);
setVolunteer(data);
};
getImage();
}, []);
const createConversation = async () => {
const newConversation = {
members: {
senderEmail: user.email,
recieverEmail: volunteer.email
},
};
const data = JSON.stringify(newConversation)
await fetch("/conversation", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: data,
})
};```
**Conversation.jsx (Where the user gets rendered)**
useEffect(() => {
const chatMembers = conversation.members.find(
(member) => member !== currentUser.email
);
const getUsersFirstName = async () => {
try {
const response = await axios.get("/name?email=" + chatMembers);
setUser(response.data);
} catch (err) {
console.log(err.message);
}
};
getUsersFirstName();
}, [currentUser, conversation, isLoading]);
if (isLoading) {
return <div>isLoading...</div>;
}
return (
<div style={{cursor: 'pointer'}}>
{user.firstName} {user.lastName} - {user.email}
</div>
);
};```
**converstionModel.js**
```const mongoose = require("mongoose")
const conversationSchema = new mongoose.Schema({
members: {
type: Array,
}
}, { timestamps: true});
const conversationModel = mongoose.model("Members", conversationSchema);
const createMembers = async (members) => {
const newMembers = await conversationModel.create(members);
return newMembers
};```
No matter what I try, I cannot get my data to print as it comes in. I tried this tutorial:
https://jakearchibald.com/2016/streams-ftw/
This SO post: How to handle streaming data using fetch?
(and a several other SO posts I can't recall)
And, tried reading the docs: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
test.py
import time
import sys
for i in range(1,10):
print('test', i)
time.sleep(.5)
sys.stdout.flush()
server.js
firmwareRouter.get('/run_test', (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-control': 'no-cache' });
const pathToExample = '/server/path/to/test.py';
const { spawn } = require('child_process');
const pythonProcess = spawn('python', [pathToExample]);
pythonProcess.stdout.on('data', (data) => {
// console.log(data.toString());
res.write(data);
});
pythonProcess.on('close', (code) => {
res.end('Process has ended');
});
});
Firmware.js (Version 1)
export default function Firmware(props) {
const [data, setData] = useState('');
async function runTest() {
try {
const url = 'api/firmware/run_test'
const request = {
method: 'GET',
headers: {
'Content-Type': 'text/event-stream'
},
}
const res = await fetch(url, request);
const reader = res.body.getReader();
const chunks = [];
const decoder = new TextDecoder('utf-8');
let done, value;
while (!done) {
({ value, done } = await reader.read());
value = decoder.decode(value);
if (done) {
return chunks;
}
console.log(value);
chunks.push(value);
setData(value);
}
} catch (err) {
console.log('frontend:Firmware', err);
}
}
return (
<Fragment>
{data}
<button onClick={() => runTest()}>Run Test </button>
</Fragment >
)
}
Firmware.js (Version 2)
export default function Firmware(props) {
const [data, setData] = useState('');
async function runTest() {
const url = 'api/firmware/run_test'
const request = {
method: 'GET',
headers: {
'Content-Type': 'text/event-stream'
},
}
fetch(url, request).then((res) => {
let reader = res.body.getReader();
let decoder = new TextDecoder();
reader.read().then(function processResult(result) {
if (result.done) return;
console.log(decoder.decode(result.value, { stream: true }))
return reader.read().then(processResult);
})
})
}
// return ()
No matter what, it only prints to the browser once the process has finished. I need it to print as the python script prints. What am I missing here?
Okay... So, one "solution" is to build it. After I built the app (npm run build), it worked.
Note: I am serving my app from express/node.
It seems to be a webpack or middleware issue between the backend and frontend and using a Proxy. I am going to try to use CORS, turn off React's proxy and go from there.
I am working on solutions using which i can send desktop push notification to subscribed clients.
I have created basic solution in where whenever user click on button i ask user for whether they want to allow notifications for my app or not!
I am getting an error of "Registration failed - permission denied" whenever i click on button for first time.
So that i am not able to get required endpoints to save at backend
Here is my code
index.html
<html>
<head>
<title>PUSH NOT</title>
<script src="index.js"></script>
</head>
<body>
<button onclick="main()">Ask Permission</button>
</body>
</html>
index.js
const check = () => {
if (!("serviceWorker" in navigator)) {
throw new Error("No Service Worker support!");
} else {
console.log("service worker supported")
}
if (!("PushManager" in window)) {
throw new Error("No Push API Support!");
} else {
console.log("PushManager worker supported")
}
};
const registerServiceWorker = async () => {
const swRegistration = await navigator.serviceWorker.register("/service.js?"+Math.random());
return swRegistration;
};
const requestNotificationPermission = async () => {
const permission = await window.Notification.requestPermission();
// value of permission can be 'granted', 'default', 'denied'
// granted: user has accepted the request
// default: user has dismissed the notification permission popup by clicking on x
// denied: user has denied the request.
if (permission !== "granted") {
throw new Error("Permission not granted for Notification");
}
};
const main = async () => {
check();
const swRegistration = await registerServiceWorker();
const permission = await requestNotificationPermission();
};
// main(); we will not call main in the beginning.
service.js
// urlB64ToUint8Array is a magic function that will encode the base64 public key
// to Array buffer which is needed by the subscription option
const urlB64ToUint8Array = base64String => {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, "+")
.replace(/_/g, "/");
const rawData = atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
};
const saveSubscription = async subscription => {
console.log("Save Sub")
const SERVER_URL = "http://localhost:4000/save-subscription";
const response = await fetch(SERVER_URL, {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(subscription)
});
return response.json();
};
self.addEventListener("activate", async () => {
try {
const applicationServerKey = urlB64ToUint8Array(
"BFPtpIVOcn2y25il322-bHQIqXXm-OACBtFLdo0EnzGfs-jIGXgAzjY6vNapPb4MM1Z1WuTBUo0wcIpQznLhVGM"
);
const options = { applicationServerKey, userVisibleOnly: true };
const subscription = await self.registration.pushManager.subscribe(options);
console.log(JSON.stringify(subscription))
const response = await saveSubscription(subscription);
} catch (err) {
console.log(err.code)
console.log(err.message)
console.log(err.name)
console.log('Error', err)
}
});
self.addEventListener("push", function(event) {
if (event.data) {
console.log("Push event!! ", event.data.text());
} else {
console.log("Push event but no data");
}
});
Also i have created a bit of backend as well
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const webpush = require('web-push')
const app = express();
app.use(cors());
app.use(bodyParser.json());
const port = 4000;
app.get("/", (req, res) => res.send("Hello World!"));
const dummyDb = { subscription: null }; //dummy in memory store
const saveToDatabase = async subscription => {
// Since this is a demo app, I am going to save this in a dummy in memory store. Do not do this in your apps.
// Here you should be writing your db logic to save it.
dummyDb.subscription = subscription;
};
// The new /save-subscription endpoint
app.post("/save-subscription", async (req, res) => {
const subscription = req.body;
await saveToDatabase(subscription); //Method to save the subscription to Database
res.json({ message: "success" });
});
const vapidKeys = {
publicKey:
'BFPtpIVOcn2y25il322-bHQIqXXm-OACBtFLdo0EnzGfs-jIGXgAzjY6vNapPb4MM1Z1WuTBUo0wcIpQznLhVGM',
privateKey: 'mHSKS-uwqAiaiOgt4NMbzYUb7bseXydmKObi4v4bN6U',
}
webpush.setVapidDetails(
'mailto:janakprajapati90#email.com',
vapidKeys.publicKey,
vapidKeys.privateKey
)
const sendNotification = (subscription, dataToSend='') => {
webpush.sendNotification(subscription, dataToSend)
}
app.get('/send-notification', (req, res) => {
const subscription = {endpoint:"https://fcm.googleapis.com/fcm/send/dLjyDYvI8yo:APA91bErM4sn_wRIW6xCievhRZeJcIxTiH4r_oa58JG9PHUaHwX7hQlhMqp32xEKUrMFJpBTi14DeOlECrTsYduvHTTnb8lHVUv3DkS1FOT41hMK6zwMvlRvgWU_QDDS_GBYIMRbzjhg",expirationTime:null,keys:{"p256dh":"BE6kUQ4WTx6v8H-wtChgKAxh3hTiZhpfi4DqACBgNRoJHt44XymOWFkQTvRPnS_S9kmcOoDSgOVD4Wo8qDQzsS0",auth:"CfO4rOsisyA6axdxeFgI_g"}} //get subscription from your databse here.
const message = 'Hello World'
sendNotification(subscription, message)
res.json({ message: 'message sent' })
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
Please help me
Try the following code:
index.js
const check = () => {
if (!("serviceWorker" in navigator)) {
throw new Error("No Service Worker support!");
} else {
console.log("service worker supported")
}
if (!("PushManager" in window)) {
throw new Error("No Push API Support!");
} else {
console.log("PushManager worker supported")
}
};
const saveSubscription = async subscription => {
console.log("Save Sub")
const SERVER_URL = "http://localhost:4000/save-subscription";
const response = await fetch(SERVER_URL, {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(subscription)
});
return response.json();
};
const urlB64ToUint8Array = base64String => {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, "+")
.replace(/_/g, "/");
const rawData = atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
};
const registerServiceWorker = async () => {
return navigator.serviceWorker.register("service.js?"+Math.random()).then((swRegistration) => {
console.log(swRegistration);
return swRegistration;
});
};
const requestNotificationPermission = async (swRegistration) => {
return window.Notification.requestPermission().then(() => {
const applicationServerKey = urlB64ToUint8Array(
"BFPtpIVOcn2y25il322-bHQIqXXm-OACBtFLdo0EnzGfs-jIGXgAzjY6vNapPb4MM1Z1WuTBUo0wcIpQznLhVGM"
);
const options = { applicationServerKey, userVisibleOnly: true };
return swRegistration.pushManager.subscribe(options).then((pushSubscription) => {
console.log(pushSubscription);
return pushSubscription;
});
});
};
const main = async () => {
check();
const swRegistration = await registerServiceWorker();
const subscription = await requestNotificationPermission(swRegistration);
// saveSubscription(subscription);
};
service.js
self.addEventListener("push", function(event) {
if (event.data) {
console.log("Push event!! ", event.data.text());
} else {
console.log("Push event but no data");
}
});
I can think of three reasons that the permission is denied
1) your site is not on https (including localhost that is not on https), the default behaviour from chrome as far as i know is to block notifications on http sites. If that's the case, click on the info icon near the url, then click on site settings, then change notifications to ask
2) if you are on Safari, then safari is using the deprecated interface of the Request permission, that is to say the value is not returned through the promise but through a callback so instead of
Notification.requestPermission().then(res => console.log(res))
it is
Notification.requestPermission(res => console.log(res))
3) Your browser settings are blocking the notifications request globally, to ensure that this is not your problem run the following code in the console (on a secured https site)
Notification.requestPermission().then(res => console.log(res))
if you receive the alert box then the problem is something else, if you don't then make sure that the browser is not blocking notifications requests