Related
I recently took over a project from another developer who has been uncooperative in providing assistance. The project includes a contract deployed on the Rinkeby network and a decentralized exchange (DEX) developed for it. Users were able to test the DEX using our own platform, with liquidity added via the Uniswap interface. The contract includes the Uniswap V2Router contract to fetch liquidity and use it on our DEX. I have completed all necessary web3 setup, including changing the RPC port to 5 and adding the correct URL.
No error so far on my console.
SITE FOR REFERENCE: https://doxastaking.netlify.app/, It is deployed on GOERLI ETHER.
Recently, I migrated the project to the Goerli network. However, since the migration, I have not been able to purchase tokens using our DEX. Transactions go through, but the equivalent tokens are not assigned to my wallet. It is unclear to me whether the issue is with the contract or the web3 setup.
The web3 swap code:
import React, { Component } from "react";
import eth from "../../assets/eth.png";
import transfer from "../../assets/transfer.png";
import buyLoader from "../../assets/doxa-ico-loader.gif";
import { connect } from "react-redux";
import { connectWallet } from '../../redux/WalletAction';
import miniLogo from "../../assets/logo.png";
import "./scss/bs.css";
class Buydoxa extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '0',
doxaValue: 0
}
}
componentDidMount() {
const { web3Modal } = this.props.wallet
if (web3Modal.cachedProvider) {
this.props.connectWallet();
}
}
connectToWallet = async () => {
await this.props.connectWallet();
}
buyToken = async () => {
const queryParams = new URLSearchParams(window.location.search);
const id = queryParams.get('email');
let inputValue = parseFloat(this.state.inputValue);
if (inputValue >= 0.00001 && inputValue <= 10) {
const { web3, doxa, wallet, address } = this.props.wallet;
const value = this.state.inputValue.toString();
const buyValue = web3.utils.toWei(value, 'ether');
const tokenPrice = web3.utils.toWei('0.00001', 'ether');
const totalTokens = (web3.utils.toBN(buyValue).div(web3.utils.toBN(tokenPrice))).toString();
try {
this.setState({ loading: true })
const res = await wallet.methods.swapEthToDoxa(id).send({ from: address, value: buyValue });
this.setState({ loading: false })
} catch (err) {
this.setState({ loading: false })
if (err.message) {
alert(err.message)
} else {
alert("Something went wrong!")
}
}
} else {
alert("ETH should be between 0.00001 and 10");
return
}
}
updateInputValue = async (e) => {
let totalTokens;
if (e.target.value != '') {
totalTokens = parseFloat(e.target.value) / 0.00001;
}
this.setState({
inputValue: e.target.value,
doxaValue: totalTokens
});
}
render() {
return (
<div className="bs-container h-100">
<div className="bs-main">
<h2>swap your crypto</h2>
<div className="bs-input">
<div className="inpt-cont center mb-3">
<label>Enter ETH</label>
<input type="number" value={this.state.inputValue} onChange={e => this.updateInputValue(e)} />
</div>
<div className="img-cont">
<img src={eth} alt="eth" />
<p>ETH</p>
</div>
</div>
{/* image */}
<img src={transfer} className="transfer" alt="transfer" />
<div className="bs-input">
<div className="inpt-cont center">
<p>{this.state.doxaValue}</p>
</div>
<div className="img-cont">
<img src={miniLogo} alt="miniLogo" />
<p>DOXAZO</p>
</div>
</div>
{/* btn */}
<button className="bs-btn" disabled={this.state.loading} onClick={() => this.props.wallet.connected ? this.buyToken() : this.connectToWallet()}>{this.props.wallet.connected ? this.state.loading ?
<span>Processing <img src={buyLoader}></img></span>
: 'Buy' : 'PROCEED TO SWAP'}</button>
</div>
</div>
);
}
}
const mapStateToProps = state => ({
wallet: state.walletConnect
});
export default connect(mapStateToProps, { connectWallet })(Buydoxa);
My Wallet Action.js Codes:
// constants
import Web3 from "web3";
import Web3Modal from "web3modal";
import WalletConnectProvider from "#walletconnect/web3-provider";
import contract from "../contracts/staking.json";
import tokenContract from "../contracts/token.json";
import walletContract from "../contracts/wallet.json";
import store from './store';
const connectRequest = () => {
return {
type: "CONNECTION_REQUEST",
};
};
export const disconnectRequest = () => {
return {
type: "DISCONNECT"
};
}
export const connectSuccess = (payload) => {
return {
type: "CONNECTION_SUCCESS",
payload: payload,
};
};
const connectFailed = (payload) => {
return {
type: "CONNECTION_FAILED",
payload: payload,
};
};
export const updateAccountRequest = (payload) => {
return {
type: "UPDATE_ADDRESS",
payload: payload,
};
};
const getProviderOptions = () => {
const providerOptions = {
walletconnect: {
package: WalletConnectProvider,
options: {
rpc: {
5: "https://goerli.infura.io/v3/ea95b0776037479abf7a62fc14b55188",
1: "https://mainnet.infura.io/v3/ea95b0776037479abf7a62fc14b55188"
}
}
},
}
return providerOptions;
}
export const connectWallet = () => {
return async(dispatch) => {
dispatch(connectRequest());
try {
const web3Modal = new Web3Modal({
cacheProvider: true,
providerOptions: getProviderOptions() // required
});
const provider = await web3Modal.connect();
const stakingContractAddress = process.env.REACT_APP_DOXACONTRACT_ADDRESS;
const internalWalletAddress = process.env.REACT_APP_WALLET_ADDRESS;
const TokencontractAddress = process.env.REACT_APP_TOKEN_ADDRESS;
await subscribeProvider(provider, dispatch);
const web3 = new Web3(provider);
web3.eth.extend({
methods: [
{
name: "chainId",
call: "eth_chainId",
outputFormatter: web3.utils.hexToNumber
}
]
});
const accounts = await web3.eth.getAccounts();
const address = accounts[0];
const instance = new web3.eth.Contract(
contract,
stakingContractAddress
);
const tokenInstance = new web3.eth.Contract(
tokenContract,
TokencontractAddress
)
const walletInstance = new web3.eth.Contract(
walletContract,
internalWalletAddress
)
if(window.ethereum && window.ethereum.networkVersion !== '5') {
await addNetwork(5);
}
dispatch(
connectSuccess({
address,
web3,
staking: instance,
token: tokenInstance,
wallet: walletInstance,
provider,
connected: true,
web3Modal
})
);
} catch (e) {
dispatch(connectFailed(e));
}
}
}
export const disconnect = () => {
return async(dispatch)=> {
const { web3Modal } = store.getState().walletConnect;
console.log(web3Modal);
web3Modal.clearCachedProvider();
dispatch(disconnectRequest());
}
}
const subscribeProvider = async(provider) => {
if (!provider.on) {
return;
}
provider.on('connect', async(id) => {
console.log(id);
});
provider.on("networkChanged", async (networkId) => {
if(networkId !== '5') {
console.log(networkId);
await store.dispatch(connectFailed('Please switch to Ethereum mainnet'));
addNetwork(5);
} else {
store.dispatch(connectWallet());
}
});
}
export async function addNetwork(id) {
let networkData;
switch (id) {
//bsctestnet
case 5:
networkData = [
{
chainId: "0x4",
},
];
break;
//bscmainet
case 1:
networkData = [
{
chainId: "0x1",
},
];
break;
default:
break;
}
return window.ethereum.request({
method: "wallet_switchEthereumChain",
params: networkData,
});
}
(() => {
if(window.ethereum) {
window.ethereum.on('networkChanged', async function(networkId){
console.log('network change', networkId);
if(networkId !== '5') {
console.log(networkId);
await store.dispatch(connectFailed('Please switch to Binance mainnet'));
addNetwork(5);
} else {
store.dispatch(connectWallet());
}
});
}
})();
The following are the contract and wallet addresses for my Goerli deployments:
Token Address: https://goerli.etherscan.io/address/0x0f0283E1aC1f465cE2076a1F57EA0f1BAb4DDC21
Wallet Address Proxy: https://goerli.etherscan.io/address/0xdF6046711651AEC0d686F12Ed0039d5aC45517f3
The following are the contract and wallet addresses for the previous developer's Rinkeby deployments:
Token deployed by other developer on Rinkeby network: https://rinkeby.etherscan.io/address/0xD99b4BB049a6Dd490901CDfa33F15C4fAc097EF0
The wallet proxy deployed on Rinkeby: https://rinkeby.etherscan.io/address/0x5309E16fc58Dc900a08d92BE6559758D692f39Bb
I am working on an application where I have created service js which I need to consume in different components of vue3. Here is my service code
const base_url = "https://localhost:7005/";
var apiObject = {
data: function() {
return {
response : undefined
};
},
methods: {
fetchContent: function(apiEndpoint) {
axios
.get(`${base_url}${apiEndpoint}`)
.then(res => {
this.response = res
})
.catch(e => {
this.errors.push(e);
});
}
}
};
Here is my component code. It is not working it gives me the error show in image below
<script>
import {fetchContent} from "../service/apiService";
export default {
data() {
return {
// url_base: "https://localhost:7005/api/weather/",
weather: undefined,
error : false,
errormessage : "",
searchHistory : []
};
},
methods : {
async fetchWeather(e) {
if (e.key == "Enter" && this.query) {
let {response} =await fetchContent(`api/weather/forecast?city=${query}`) //get(query,`${weather_url}forecast?city=`); //await axios.get(`${this.url_base}forecast?city=${this.query}`);
this.setResults(response.data);
}else if (e.key == "Enter" && !this.query){
this.error = true;
this.errormessage = 'Please enter name to search!';
}
},
setResults(res) {
if(res.isSuccessful === true){
this.error = false;
this.weather = res.response;
this.saveData(res.response)
}else{
this.weather = undefined;
this.errormessage = res.response;
this.error = true;
}
},
saveData(res){
this.searchHistory = JSON.parse(localStorage.getItem("SearchHistory"));
if(this.searchHistory == null){this.searchHistory = [];}
res.forEach(x => {
this.searchHistory.push(x);
});
localStorage.setItem("SearchHistory",JSON.stringify(this.searchHistory));
}
},
};
</script>
Image
I am trying to connect a Kurento Media Server to React Native on iOS for a group video call.
The server is running on Nodejs and Docker, and they already have a TURN server set up.
The app is already running in the web browser via kurento-utils, but I can't stream the web video to RN, instead, the RN video looks just fine on the web.
I'm not usig kurento-utils on client side of React Native.
This is my code:
Video Screen (emmiter and receptor)
import React, { useState, useEffect } from 'react';
import {
View,
StyleSheet,
Text,
} from 'react-native';
import Display from 'react-native-display';
import InCallManager from 'react-native-incall-manager';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { socket } from '../../screens/User';
import ReceiveScreen from './ReceiveScreen';
import {
RTCView,
RTCIceCandidate,
} from 'react-native-webrtc';
import {
startCommunication,
receiveVideo,
addIceCandidate,
ProcessAnswer,
ViewPCArray
} from '../../utils/webrtc-utils';
const participants = {};
function sendMessage(message) {
if (socket) {
socket.emit('message', message);
}
}
const VideoScreen = () => {
const [videoURL, setVideoURL] = useState(null)
const [remoteURL, setRemoteURL] = useState(null)
const [userName, setUserName] = useState(socket.id)
const [roomName, setRoomName] = useState('9b33737f-737f-4a3d-a323-e1cd3f4b68b2')
useEffect(() => {
if(socket) {
var message = {
event: 'joinRoom',
userName: userName,
roomName: roomName
}
sendMessage(message);
}
socket.on('message', message => {
messageProcessHandler(message);
});
return () => {
socket.close();
}
}, [])
/**
*
* #param {*} msg
*/
const messageProcessHandler = (msg) => {
// console.log(`MessageProcessHandler: ${msg.event}`);
switch (msg.event) {
case 'existingParticipants':
console.log('LOG:176 onExistingParticipants= ' + JSON.stringify(msg));
startCommunication(sendMessage, userName, (stream) => {
setVideoURL(stream.toURL())
msg.existingUsers.forEach((object) => {
participants[object.name] = object.id;
console.log("participants:" + JSON.stringify(participants));
receiveVideo(sendMessage, object.name, (pc) => {
console.log('getRemoteStreams ', pc);
pc.getRemoteStreams().forEach(track => {
// console.log('TRACK: ', track);
console.log('STREAM', track);
// pc.addTrack(track, stream);
setRemoteURL(track.toURL())
})
});
});
});
break;
case 'newParticipantArrived':
participants[msg.name] = msg.name;
if (remoteURL == null || remoteURL === '') {
receiveVideo(sendMessage, msg.userName, (pc) => {
pc.getRemoteStreams().forEach(track => {
console.log('STREAM', track);
setRemoteURL(track.toURL())
})
});
}
break;
case 'participantLeft':
participantLeft(msg.name);
break;
case 'receiveVideoAnswer':
ProcessAnswer(msg.senderid, msg.sdpAnswer, (err) => {
if (err) {
console.log('the error: ' + err);
}
});
break;
case 'candidate':
addIceCandidate(msg.userid, new RTCIceCandidate(msg.candidate));
break;
default:
console.error('Unrecognized message', msg.message);
}
}
/**
*
* #param {*} name
*/
const participantLeft = (name) => {
if (participants[name]) {
delete participants[name];
}
if (Object.keys(participants).length == 0) {
setRemoteURL(null)
}
}
return (
<View style={styles.container}>
<View style={{position: "absolute", top: 40, right: 20, zIndex: 200}}>
<Text style={{fontSize: 20, fontWeight: "bold", color: "#fff"}}>{userName}</Text>
</View>
<RTCView zOrder={0} objectFit='cover' style={styles.videoContainer} streamURL={videoURL} />
<Display enable={remoteURL != null}>
<View style={styles.floatView}>
<ReceiveScreen videoURL={remoteURL} />
</View>
</Display>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1
},
videoContainer: {
flex: 1
},
floatView: {
position: 'absolute',
width: 250,
height: 210,
bottom: 15,
right: 20,
backgroundColor: 'rgba(255, 255, 255, 0.1)',
borderRadius: 15
}
});
export default VideoScreen
Display (where the browser video is supposed to be)
import React, { Component } from 'react';
import config from "../../config/app.js";
import {
View,
Text,
ScrollView,
StyleSheet
} from 'react-native';
import { RTCView } from 'react-native-webrtc';
const styles = StyleSheet.create({
root: {
flex: 1
},
titleContainer: {
flex: 0.1,
paddingVertical: 2,
paddingLeft: 10
},
title: {
fontSize: 15,
color: 'rgba(255, 255, 255, 0.5)'
},
contentContainer: {
flex: 1,
backgroundColor: 'transparent'
}
});
const ReceiveScreen = (props) => {
return (
<View style={styles.root}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Nuevo miembro</Text>
</View>
<RTCView objectFit='cover' zOrder={1} style={styles.contentContainer} streamURL={props.videoURL} mirror={true} />
</View>
)
}
export default ReceiveScreen;
WebRtc Utils
import {
getUserMedia,
MediaStreamTrack,
mediaDevices,
RTCPeerConnection,
RTCSessionDescription,
} from 'react-native-webrtc';
import { PERMISSIONS, request, checkMultiple } from 'react-native-permissions';
import { socket } from '../screens/User';
let pcArray = {};
let isFront = true;
let isEnableAudio = true;
let isEnableVideo = true;
let localstream = null;
const ICE_CONFIG = {
'iceServers': [
{
'urls': 'turn:xxx.xxx.xxx.xxx:3478',
'username': 'xxxxxxxx',
'credential': 'xxxxxxxxxxxxxxxxxxxxxxx',
'credentialType': 'password'
}
]
};
/**
* Obtenga elementos multimedia locales (transmisiones de video)
*
* #param {*} _sendMessage
* #param {*} _name
* #param {*} callback
*/
export function startCommunication(_sendMessage, _name, callback) {
getStream(true, stream => {
localstream = stream;
let options = {
audio: true,
video : {
mandatory : {
maxWidth : 320,
maxFrameRate : 15,
minFrameRate : 1
}
}
};
let pc = createPC(_sendMessage, _name, true, options);
pcArray[_name] = pc;
callback(stream);
});
}
/**
* Obtener transmisión de video remota
*
* #param {*} _sendMessae
* #param {*} _name
* #param {*} callback
*/
export function receiveVideo(_sendMessae, _name, callback) {
console.log("receiveVideo:", _sendMessae, _name, callback);
let options = {
audio: true,
video : {
mandatory : {
// maxWidth : 320,
// maxFrameRate : 15,
// minFrameRate : 15
maxWidth : 120,
maxHeight: 80,
minWidth : 80,
minHeight: 60,
maxFrameRate : 10,
minFrameRate : 10
}
}
};
let pc = createPC(_sendMessae, _name, true, options);
// console.log(`PC CREATED FOR ${_name}: ${JSON.stringify(pc)}`);
pcArray[_name] = pc;
// callback(pc);
callback(pcArray);
}
/**
* Encender/apagar el micrófono
*/
export function toggleAudio() {
if (localstream) {
isEnableAudio = !isEnableAudio;
localstream.getAudioTracks().forEach((track) => {
track.enabled = isEnableAudio;
});
} else {
console.log('in toggleAudio(), localstream is empty');
}
return isEnableAudio;
}
/**
* Activar/desactivar vídeo
*/
export function toggleVideo() {
if (localstream) {
isEnableVideo = !isEnableVideo;
localstream.getVideoTracks().forEach((track) => {
track.enabled = isEnableVideo;
});
} else {
console.log('in toggleVideo(), localstream is empty');
}
return isEnableVideo;
}
/**
* cambiar de cámara
*
*/
export function switchVideoType() {
if (localstream) {
localstream.getVideoTracks().forEach(track => {
track._switchCamera();
});
} else {
console.log('error');
}
}
/**
* Crear una transmisión de video local
*
* #param {*} isFront
* #param {*} callback
*/
export function getStream(isFront, callback) {
mediaDevices.enumerateDevices().then(sourceInfos => {
//console.log('Log: '+ JSON.stringify(sourceInfos)); // -> Es un objecto de 3
let videoSourceId;
for (let i = 0; i < sourceInfos.length; i++) {
const sourceInfo = sourceInfos[i];
if (sourceInfo.kind === 'videoinput' && sourceInfo.facing === (isFront ? 'front' : 'back')) {
// if (sourceInfo.kind === 'videoinput' && sourceInfo.facing === (isFront ? 'front' : 'back')) { Was video only, not videoinput
videoSourceId = sourceInfo.id;
}
}
request(PERMISSIONS.IOS.CAMERA).then((response) => {
if (response === 'granted') {
request(PERMISSIONS.IOS.CAMERA).then((response) => {
if (response === 'granted') {
mediaDevices.getUserMedia({
audio: true,
video: {
width: 640,
height: 480,
frameRate: 30,
facingMode: (isFront ? "user" : "environment"),
deviceId: videoSourceId
}
})
.then(stream => {
callback(stream)
})
.catch(error => {
// Log error
console.log(error)
});
}
})
}
})
});
}
/**
*
* Crear una conexión WebRTC
*
* #param {*} sendMessage
* #param {*} name
* #param {*} isOffer
* #param {*} options
*/
export function createPC(sendMessage, name, isOffer, options) {
let pc = new RTCPeerConnection(ICE_CONFIG);
pc.onnegotiationneeded = () => {
console.log('onnegotiationneeded');
if (isOffer) {
isOffer = false;
createOffer();
}
};
pc.onicecandidate = (event) => {
console.log('onicecandidate');
if (event.candidate) {
let msg = {
event: 'candidate',
// event: 'onIceCandidate',
userid: socket.id,
roomName: '9b33737f-737f-4a3d-a323-e1cd3f4b68b2',
candidate: event.candidate
};
sendMessage(msg);
}
};
pc.oniceconnectionstatechange = (event) => {
// console.log('oniceconnectionstatechange');
if (event.target.iceConnectionState === 'disconnected') {
//localstream.release();
// localstream = null;
if (pc !== null) {
pc.close();
pc = null;
}
}
};
pc.onsignalingstatechange = (event) => {
console.log('onsignalingstatechange: ', event.target.signalingState);
};
// send local stream
pc.addStream(localstream);
function createOffer() {
// console.log('createOffer');
pc.createOffer()
.then(function (desc) {
// console.log('...createOffer...');
pc.setLocalDescription(desc);
// something to do
let msg = {
event: 'receiveVideoFrom',
userid: socket.id,
roomName: '9b33737f-737f-4a3d-a323-e1cd3f4b68b2',
// sdpOffer: desc.sdp,
sdpOffer: desc.sdp,
};
sendMessage(msg);
})
.catch(err => console.error(err));
}
return pc;
}
/**
* Adición incremental de iceCandidate
*
* #param {*} name
* #param {*} candidate
*/
export function addIceCandidate(name, candidate) {
let pc = pcArray[name];
if (pc) {
pc.addIceCandidate(candidate);
} else {
console.log('pc.addIceCandidate failed : pc not exists');
}
}
/**
* Proceso SdpAnswer
*
* #param {*} name
* #param {*} sdp
* #param {*} callback
*/
export async function ProcessAnswer(name, sdp, callback) {
let pc = pcArray[name];
if (pc) {
let answer = {
type: 'answer',
sdp: sdp,
};
if (pc) {
// const remoteDesc = new RTCSessionDescription(answer);
// await pc.setRemoteDescription(remoteDesc);
await pc.setRemoteDescription(new RTCSessionDescription(answer)).then(function () {
console.log('LOG:252 Answer = ' + answer);
callback();
})
.catch(function (reason) {
callback(reason);
console.log('ERROR REASON:', reason);
});
}
} else {
console.log('ProcessAnswer failed : pc not exists');
}
}
/**
*
* Cierra la conexión y libera el streamer local.
*
*/
export function ViewPCArray (username) {
// console.log(pcArray[username].getRemoteStreams()[0]);
return pcArray
}
export function ReleaseMeidaSource() {
if (localstream) {
localstream.release();
localstream = null;
}
if (pcArray !== null) {
for (let mem in pcArray) {
pcArray[mem].close();
delete pcArray[mem];
}
}
}
function logError(error) {
console.log('logError', error);
}
NodeJs Kurento
module.exports = function(io, socket) {
// variables
const kurento = require('kurento-client');
const minimist = require('minimist');
var kurentoClient = null;
var iceCandidateQueues = {};
// constants
var argv = minimist(process.argv.slice(2), {
default: {
// as_uri: 'https://localhost:3000/',
// ws_uri: 'ws://localhost:8888/kurento'
as_uri: 'https://localhost:4000/',
ws_uri: 'ws://localhost:8888/kurento'
}
});
socket.on('message', function (message) {
console.log('Message received: ', message.event);
switch (message.event) {
case 'joinRoom':
joinRoom(socket, message.userName, message.roomName, err => {
if (err) {
console.log(err);
}
});
break;
case 'receiveVideoFrom':
receiveVideoFrom(socket, message.userid, message.roomName, message.sdpOffer, err => {
if (err) {
console.log(err);
}
});
break;
case 'candidate':
addIceCandidate(socket, message.userid, message.roomName, message.candidate, err => {
if (err) {
console.log(err);
}
});
break;
}
socket.on('disconnect', () => {
leaveRoom(socket, message.roomName, err => {
if (err) {
console.log(err);
};
});
})
});
// signaling functions
function joinRoom(socket, username, roomname, callback) {
console.log(('Smeone in the Room').green + socket + " " + username + " " + roomname)
getRoom(socket, roomname, (err, myRoom) => {
if (err) {
return callback(err);
}
myRoom.pipeline.create('WebRtcEndpoint', (err, outgoingMedia) => {
outgoingMedia.setMaxVideoSendBandwidth(100);
if (err) {
return callback(err);
}
var user = {
id: socket.id,
name: username,
outgoingMedia: outgoingMedia,
incomingMedia: {}
}
let iceCandidateQueue = iceCandidateQueues[user.id];
if (iceCandidateQueue) {
while (iceCandidateQueue.length) {
let ice = iceCandidateQueue.shift();
console.error(`user: ${user.name} collect candidate for outgoing media`);
user.outgoingMedia.addIceCandidate(ice.candidate);
}
}
user.outgoingMedia.on('OnIceCandidate', event => {
let candidate = kurento.register.complexTypes.IceCandidate(event.candidate);
socket.emit('message', {
event: 'candidate',
userid: user.id,
candidate: candidate
});
});
socket.to(roomname).emit('message', {
event: 'newParticipantArrived',
userid: user.id,
username: user.name
});
let existingUsers = [];
for (let i in myRoom.participants) {
if (myRoom.participants[i].id != user.id) {
existingUsers.push({
id: myRoom.participants[i].id,
name: myRoom.participants[i].name
});
}
}
socket.emit('message', {
event: 'existingParticipants',
existingUsers: existingUsers,
userid: user.id
});
myRoom.participants[user.id] = user;
});
});
}
// Disconnect from room
function leaveRoom(socket, roomname, callback) {
if (io.sockets.adapter.rooms[roomname] == null) {
// ROOMS
// console.log((io.sockets.adapter.rooms))
return;
}
var userSession = io.sockets.adapter.rooms[roomname].participants[socket.id];
var myRoom = io.sockets.adapter.rooms[roomname] || { length: 0 };
// MY ROOM
// console.log(myRoom);
if (!userSession) {
return;
}
var room = io.sockets.adapter.rooms[roomname];
if(!room){
return;
}
console.log('notify all user that ' + userSession.name + ' is leaving the room ' + roomname);
var usersInRoom = room.participants;
delete usersInRoom[userSession.id];
userSession.outgoingMedia.release();
// release incoming media for the leaving user
for (var i in userSession.incomingMedia) {
userSession.incomingMedia[i].release();
delete userSession.incomingMedia[i];
}
for (var i in usersInRoom) {
var user = usersInRoom[i];
// release viewer from this
user.incomingMedia[userSession.id].release();
delete user.incomingMedia[userSession.id];
// notify all user in the room
io.emit('message', {
event: 'participantLeft',
name: userSession.id
});
console.log('Mensaje emitido')
}
// Release pipeline and delete room when room is empty
if (Object.keys(room.participants).length == 0) {
room.pipeline.release();
delete rooms[userSession.roomName];
}
delete userSession.roomName;
// console.log(myRoom);
callback(null);
}
function receiveVideoFrom(socket, userid, roomname, sdpOffer, callback) {
getEndpointForUser(socket, roomname, userid, (err, endpoint) => {
if (err) {
return callback(err);
}
endpoint.processOffer(sdpOffer, (err, sdpAnswer) => {
if (err) {
return callback(err);
}
socket.emit('message', {
event: 'receiveVideoAnswer',
senderid: userid,
sdpAnswer: sdpAnswer
});
endpoint.gatherCandidates(err => {
if (err) {
return callback(err);
}
});
});
});
}
function addIceCandidate(socket, senderid, roomname, iceCandidate, callback) {
// console.log(io.sockets.adapter.rooms);
let user = io.sockets.adapter.rooms[roomname].participants[socket.id];
if (user != null) {
let candidate = kurento.register.complexTypes.IceCandidate(iceCandidate);
if (senderid == user.id) {
if (user.outgoingMedia) {
user.outgoingMedia.addIceCandidate(candidate);
} else {
iceCandidateQueues[user.id].push({ candidate: candidate });
}
} else {
if (user.incomingMedia[senderid]) {
user.incomingMedia[senderid].addIceCandidate(candidate);
} else {
if (!iceCandidateQueues[senderid]) {
iceCandidateQueues[senderid] = [];
}
iceCandidateQueues[senderid].push({ candidate: candidate });
}
}
callback(null);
} else {
callback(new Error("addIceCandidate failed"));
}
}
// useful functions
function getRoom(socket, roomname, callback) {
var myRoom = io.sockets.adapter.rooms[roomname] || { length: 0 };
var numClients = myRoom.length;
console.log(roomname, ' has ', numClients, ' clients');
if (numClients == 0) {
socket.join(roomname, () => {
myRoom = io.sockets.adapter.rooms[roomname];
getKurentoClient((error, kurento) => {
kurento.create('MediaPipeline', (err, pipeline) => {
if (error) {
return callback(err);
}
myRoom.pipeline = pipeline;
myRoom.participants = {};
callback(null, myRoom);
});
});
});
} else {
socket.join(roomname);
callback(null, myRoom);
}
}
function getEndpointForUser(socket, roomname, senderid, callback) {
var myRoom = io.sockets.adapter.rooms[roomname];
var asker = myRoom.participants[socket.id];
var sender = myRoom.participants[senderid];
if (asker.id === sender.id) {
return callback(null, asker.outgoingMedia);
}
if (asker.incomingMedia[sender.id]) {
sender.outgoingMedia.connect(asker.incomingMedia[sender.id], err => {
if (err) {
return callback(err);
}
callback(null, asker.incomingMedia[sender.id]);
});
} else {
myRoom.pipeline.create('WebRtcEndpoint', (err, incoming) => {
incoming.setMaxVideoSendBandwidth(100);
if (err) {
return callback(err);
}
asker.incomingMedia[sender.id] = incoming;
let iceCandidateQueue = iceCandidateQueues[sender.id];
if (iceCandidateQueue) {
while (iceCandidateQueue.length) {
let ice = iceCandidateQueue.shift();
console.error(`user: ${sender.name} collect candidate for outgoing media`);
incoming.addIceCandidate(ice.candidate);
}
}
incoming.on('OnIceCandidate', event => {
let candidate = kurento.register.complexTypes.IceCandidate(event.candidate);
console.log("CANDIDATE: ", event.candidate);
socket.emit('message', {
event: 'candidate',
userid: sender.id,
candidate: candidate
});
});
sender.outgoingMedia.connect(incoming, err => {
if (err) {
return callback(err);
}
callback(null, incoming);
});
});
}
}
function getKurentoClient(callback) {
if (kurentoClient !== null) {
return callback(null, kurentoClient);
}
kurento(argv.ws_uri, function (error, _kurentoClient) {
if (error) {
console.log("Could not find media server at address " + argv.ws_uri);
return callback("Could not find media server at address" + argv.ws_uri
+ ". Exiting with error " + error);
}
kurentoClient = _kurentoClient;
callback(null, kurentoClient);
});
}
}
I'm having trouble changing the prop: 'rate' to change the speed of the audio being played.
I'm using expo-av (https://docs.expo.dev/versions/latest/sdk/av/).
Here's my code:
import {Text, View, Alert } from 'react-native'
import * as MediaLibrary from 'expo-media-library';
import { DataProvider } from 'recyclerlistview';
import {Audio} from 'expo-av';
import { play, pause, resume, playNext } from "../misc/AudioController";
export const AudioContext = createContext()
export class AudioProvider extends Component {
constructor(props) {
super(props);
this.state = {
audioFiles: [],
permissionError: false,
dataProvider: new DataProvider((r1, r2) => r1 !== r2),
playbackObj: null,
soundObj: null,
currentAudio: {},
isPlaying: false,
currentAudioIndex: null,
playbackPosition: null,
playbackDuration: null,
rate: 2.0,
};
this.totalAudioCount = 0;
}
permissionAlert = () => {
Alert.alert("Permission Required", "This app needs to read audio files", [
{ text: "I am ready", onPress: () => this.getPermission() },
{
text: "cancel",
onPress: () => this.permissionAlert(),
},
]);
};
getAudioFiles = async () => {
const { dataProvider, audioFiles } = this.state;
let media = await MediaLibrary.getAssetsAsync({
mediaType: "audio",
});
media = await MediaLibrary.getAssetsAsync({
mediaType: "audio",
first: media.totalCount,
});
this.totalAudioCount = media.totalCount;
this.setState({
...this.state,
dataProvider: dataProvider.cloneWithRows([
...audioFiles,
...media.assets,
]),
audioFiles: [...audioFiles, ...media.assets],
});
};
loadPreviousAudio = async () => {
let previousAudio = await AsyncStorageLib.getItem("previousAudio");
let currentAudio;
let currentAudioIndex;
if (previousAudio === null) {
currentAudio = this.state.audioFiles[0];
currentAudioIndex = 0;
} else {
previousAudio = JSON.parse(previousAudio);
currentAudio = previousAudio.audio;
currentAudioIndex = previousAudio.index;
}
this.setState({ ...this.state, currentAudio, currentAudio });
};
getPermission = async () => {
// {
// "canAskAgain": true,
// "expires": "never",
// "granted": false,
// "status": "undetermined",
// }
const permission = await MediaLibrary.getPermissionsAsync();
if (permission.granted) {
this.getAudioFiles();
}
if (!permission.canAskAgain && !permission.granted) {
this.setState({ ...this.state, permissionError: true });
}
if (!permission.granted && permission.canAskAgain) {
const { status, canAskAgain } =
await MediaLibrary.requestPermissionsAsync();
if (status === "denied" && canAskAgain) {
this.permissionAlert();
}
if (status === "granted") {
this.getAudioFiles();
}
if (status === "denied" && !canAskAgain) {
this.setState({ ...this.state, permissionError: true });
}
}
};
onPlaybackStatusUpdate = async (playbackStatus) => {
console.log("hier");
if (playbackStatus.isLoaded && playbackStatus.isPlaying) {
this.updateState(this, {
playbackPosition: playbackStatus.positionMillis,
playbackDuration: playbackStatus.durationMillis,
});
}
if (playbackStatus.didJustFinish) {
const nextAudioIndex = this.state.currentAudioIndex + 1;
if (nextAudioIndex >= this.totalAudioCount) {
this.state.playbackObj.unloadAsync();
this.updateState(this, {
soundObj: null,
currentAudio: this.state.audioFiles[0],
isPlaying: false,
currentAudioIndex: 0,
playbackPosition: null,
playbackDuration: null,
});
}
const audio = this.state.audioFiles[nextAudioIndex];
const status = await playNext(this.state.playbackObj, audio.uri);
this.updateState(this, {
soundObj: status,
currentAudio: audio,
isPlaying: true,
currentAudioIndex: nextAudioIndex,
});
}
};
componentDidMount() {
this.getPermission();
if (this.state.playbackObj === null) {
this.setState({ ...this.state, playbackObj: new Audio.Sound(), });
}
}
updateState = (prevState, newState = {}) => {
this.setState({ ...prevState, ...newState });
};
render() {
const {
audioFiles,
dataProvider,
permissionError,
playbackObj,
soundObj,
currentAudio,
isPlaying,
currentAudioIndex,
playbackPosition,
playbackDuration,
rate,
} = this.state;
if (permissionError)
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<Text>It looks like you haven't accepted the permission</Text>
</View>
);
return (
<AudioContext.Provider
value={{
audioFiles,
dataProvider,
playbackObj,
soundObj,
currentAudio,
isPlaying,
currentAudioIndex,
totalAudioCount: this.totalAudioCount,
playbackPosition,
playbackDuration,
rate,
updateState: this.updateState,
loadPreviousAudio: this.loadPreviousAudio,
onPlaybackStatusUpdate: this.onPlaybackStatusUpdate
}}
>
{this.props.children}
</AudioContext.Provider>
);
}
}
import {Component} from 'react';
import AsyncStorageLib from '#react-native-async-storage/async-storage';
export default AudioProvider;
and here's some more:
// play audio
// Import the react-native-sound module
import { PitchCorrectionQuality,shouldCorrectPitch, rate } from "expo-av/build/AV.types";
export const play = async (playbackObj, uri,) => {
try {
return await playbackObj.loadAsync(
{uri},
{shouldPlay: true},
);
} catch (error) {
console.log('error inside play helper method', error.message)
}
};
//pause
export const pause = async playbackObj => {
try {
// playbackObj.setRateAsync(rate = 2.0, shouldCorrectPitch = true, PitchCorrectionQuality= High);
return await playbackObj.setStatusAsync({
shouldPlay: false},
);
} catch (error) {
console.log('error inside pause helper method', error.message)
}
};
//resume
export const resume = async playbackObj => {
try {
return await playbackObj.playAsync(
);
} catch (error) {
console.log('error inside pause resume method', error.message)
}
};
//select next
export const playNext = async (playbackObj, uri) => {
try {
await playbackObj.stopAsync()
await playbackObj.unloadAsync();
return await play(playbackObj, uri);
} catch (error) {
console.log('error inside playNext helper method')
}
}
I've tried including 'rate: 2.0' inside this.state{audioFiles: [],
permissionError: false, etc.} but it didn't work.
Also I've tried doing: await playbackObj.setRateAsync() in the 2nd code snippet.
Any suggestions?
Nvm, I found the solution. Here's my updated code:
// play audio
// Import the react-native-sound module
import { PitchCorrectionQuality,shouldCorrectPitch, rate } from "expo-av/build/AV.types";
export const play = async (playbackObj, uri,) => {
try {
await playbackObj.loadAsync(
{uri},
{shouldPlay: true},
);
return await playbackObj.setStatusAsync({ rate: 0.9749090909 });
} catch (error) {
console.log('error inside play helper method', error.message)
}
};
//pause
export const pause = async playbackObj => {
try {
return await playbackObj.setStatusAsync({
shouldPlay: false,
rate: 0.9749090909,
});
} catch (error) {
console.log('error inside pause helper method', error.message)
}
};
//resume
export const resume = async playbackObj => {
try {
return await playbackObj.playAsync(
);
} catch (error) {
console.log('error inside pause resume method', error.message)
}
};
//select next
export const playNext = async (playbackObj, uri) => {
try {
await playbackObj.stopAsync()
await playbackObj.unloadAsync();
return await play(playbackObj, uri);
} catch (error) {
console.log('error inside playNext helper method')
}
}
I want to use AsyncStorage.setItem inside AsyncStorage.getItem. How to do that in right way?
My code is as follows:
createVehicle: function (vehicle, cb) {
AsyncStorage.getItem('vehicle')
.then(json => {
let vehicles = [];
if (json) {
vehicles = JSON.parse(json);
let o_vehicle = filter(vehicles, {autralis_id: vehicle.autralis_id});
if (o_vehicle.length > 0) {
cb(o_vehicle[0].id);
return;
} else {
vehicles.push(vehicle);
}
} else {
vehicles.push(vehicle);
}
AsyncStorage.setItem('vehicle', JSON.stringify(vehicles), () => {
cb(vehicle.id + 1)
});
}).done();
},
Is that the right way to do it?
I have created a service for Storage which can be used in the entire project as and when required by passing the required params. Have a look :
export default {
async setItem(key, value) {
try {
return await AsyncStorage.setItem(key, JSON.stringify(value));
} catch (error) {
// console.error('AsyncStorage#setItem error: ' + error.message);
}
},
async getItem(key) {
return await AsyncStorage.getItem(key)
.then((result) => {
if (result) {
try {
result = JSON.parse(result);
} catch (e) {
// console.error('AsyncStorage#getItem error deserializing JSON for key: ' + key, e.message);
}
}
return result;
});
},
async removeItem(key) {
return await AsyncStorage.removeItem(key);
}
}
This is by far the best practice I have come across till the date. You should use it too.
Please refer to this official document, it uses getItem inside setItem, So I think you could also use setItem inside getItem, because the return value is just a Promise for both getItem and setItem.
AsyncStorage.setItem('UID123', JSON.stringify(UID123_object), () => {
AsyncStorage.mergeItem('UID123', JSON.stringify(UID123_delta), () => {
AsyncStorage.getItem('UID123', (err, result) => {
console.log(result);
});
});
});
import React, { Component } from 'react'
import { StatusBar } from 'react-native'
import { AsyncStorage, Text, View, TextInput, StyleSheet } from 'react-native'
class AsyncStorageExample extends Component {
state = {
'name': ''
}
componentDidMount = () => AsyncStorage.getItem('name').then((value) => this.setState({
'name': value }))
setName = (value) => {
AsyncStorage.setItem('name', value);
this.setState({ 'name': value });
}
render() {
return (
<View style = {styles.container}>
<TextInput style = {styles.textInput} autoCapitalize = 'none'
onChangeText = {this.setName}/>
<Text>
{this.state.name}
</Text>
</View>
)
}
}
export default AsyncStorageExample
const styles = StyleSheet.create ({
container: {
flex: 1,
alignItems: 'center',
marginTop: 50
},
textInput: {
margin: 5,
height: 100,
borderWidth: 1,
backgroundColor: '#7685ed'
}
})
I don't know if I come too late, but I wrote this for myself :
import { Base64 } from 'js-base64';
import { AsyncStorage } from 'react-native';
export async function storeItem(key: string, item: string, isJson: boolean) {
try {
return new Promise(async resolve => {
let stringObject = '';
if (isJson) {
stringObject = JSON.stringify(item);
} else {
stringObject = item.toString();
}
let base64Object = await Base64.encode(stringObject);
await AsyncStorage.setItem(key, base64Object);
resolve();
});
} catch (e) {
console.log(e);
}
}
export async function retrieveItem(key: string, isJson: boolean) {
try {
return new Promise(async resolve => {
let base64Item = await AsyncStorage.getItem(key);
if (base64Item === null) {
resolve(null);
}
let item = await Base64.decode(base64Item);
resolve(isJson ? JSON.parse(item) : item);
});
} catch (e) {
console.log(e);
}
}
export async function removeItem(key: string) {
try {
return new Promise(async resolve => {
await AsyncStorage.removeItem(key);
resolve();
});
} catch (e) {}
}
I use base64 because of the special characters.
Hope it could helps :)