Metamask is working perfectly.
BinanceChainWallet is working perfectly.
WalletConnect provider (model: QR - desktop/mobile wallet support), not working when I click on Wallet-Connect model on the front-end it give me this error only.
Platform on:
Framework: Laravel 8.0
JS
The problem is in this file (LaravelWeb3Scripts.php/walletconnect.ts) - this file is the one used for getting providers models.
Vendor/Provider used
https://github.com/sawirricardo/laravel-web3
Wallet-Connect Model repo https://github.com/WalletConnect/web3modal/blob/master/docs/providers/walletconnect.md
Console Log error (Chrome Developer Tools):
Uncaught (in promise) TypeError: e is not a constructor
at walletconnect.ts:31:22
at tslib.es6.js:100:1
at Object.next (tslib.es6.js:81:45)
at tslib.es6.js:74:1
at new Promise (<anonymous>)
at Module.A (tslib.es6.js:70:1)
at walletconnect.ts:15:44
at new Promise (<anonymous>)
at t.default (walletconnect.ts:15:10)
at e.<anonymous> (providers.ts:201:30)
walletconnect.ts - providers.ts - tslib.es6.js are imported from cdns
File: walletconnect.ts
import { IAbstractConnectorOptions, getChainId } from "../../helpers";
export interface IWalletConnectConnectorOptions
extends IAbstractConnectorOptions {
infuraId?: string;
rpc?: { [chainId: number]: string };
bridge?: string;
qrcode?: boolean;
}
const ConnectToWalletConnect = (
WalletConnectProvider: any,
opts: IWalletConnectConnectorOptions ) => {
return new Promise(async (resolve, reject) => {
let bridge = "https://bridge.walletconnect.org";
let qrcode = true;
let infuraId = "";
let rpc = undefined;
let chainId = 1;
console.log('wallet connect'); // todo remove dev item
if (opts) {
bridge = opts.bridge || bridge;
qrcode = typeof opts.qrcode !== "undefined" ? opts.qrcode : qrcode;
infuraId = opts.infuraId || "";
rpc = opts.rpc || undefined;
chainId =
opts.network && getChainId(opts.network) ? getChainId(opts.network) : 1;
}
const provider = new WalletConnectProvider({
bridge,
qrcode,
infuraId,
rpc,
chainId
});
try {
await provider.enable();
resolve(provider);
} catch (e) {
reject(e);
}
});
};
export default ConnectToWalletConnect;
File: LaravelWeb3Scripts.php
<?php
namespace Sawirricardo\LaravelWeb3\Components;
use Illuminate\View\Component;
class LaravelWeb3Scripts extends Component {
/**
* Create a new component instance.
*
* #return void
*/
public function __construct() {
//
}
/**
* Get the view / contents that represent the component.
*
* #return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render() {
return <<<'blade'
<script>
class LaravelWeb3 {
constructor() {
this._provider = null;
this.reloadAfterFetching = true;
this.alertUserIfMetamaskIsNotInstalled = true;
this.contracts = #json(config('web3.contracts'));
this.web3ModalOptions = {
cacheProvider: true,
disableInjectedProvider: false,
providerOptions: {
binancechainwallet: {
package: true
},
walletconnect: {
package: WalletConnectProvider,
options: {
infuraId: "*********// hidden for post",
},
},
},
};
}
async onConnect() {
try {
const web3Modal = this.prepareWeb3Modal();
const provider = await web3Modal.connect();
provider.on("accountsChanged", async (accounts) => {
console.log("accountsChanged", accounts);
web3Modal.clearCachedProvider();
await this.fetchAccount(provider);
if (this.reloadAfterFetching) window.location.reload();
});
provider.on("chainChanged", async (chainId) => {
console.log("chainChanged", chainId);
web3Modal.clearCachedProvider();
await this.fetchAccount(provider);
if (this.reloadAfterFetching) window.location.reload();
});
provider.on("connect", ( { chainId }) => {
console.log("connect", chainId);
});
provider.on("disconnect", ( { code, message }) => {
console.log("disconnect", code, message);
});
await this.fetchAccount(provider);
if (this.reloadAfterFetching) window.location.reload();
} catch (e) {
console.log({ e });
}
}
async fetchAccount(web3Provider) {
const provider = new ethers.providers.Web3Provider(web3Provider);
const message = await(await(await fetch("/_web3/users/signature", {
method: "get",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": "{{ csrf_token() }}",
},
})).json()).message;
await fetch("/_web3/users",{
method:'post',
body: JSON.stringify({
signature: await provider.getSigner().signMessage(message),
address: await provider.getSigner().getAddress(),
}),
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": "{{ csrf_token() }}",
},
})
this._provider = provider;
}
async onDisconnect() {
this._provider = null;
const web3Modal = this.prepareWeb3Modal();
await web3Modal.clearCachedProvider();
await fetch("/_web3/users/logout",{
method: "delete",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": "{{ csrf_token() }}",
},
});
if (this.reloadAfterFetching) window.location.reload();
}
async getProvider() {
if (!this._provider) {
const web3Modal = this.prepareWeb3Modal();
const web3Provider = await web3Modal.connect();
this._provider = new ethers.providers.Web3Provider(web3Provider);
}
return this._provider;
}
prepareWeb3Modal () {
let Web3Modal, WalletConnectProvider;
// if (!(window.web3 || window.ethereum) && this.alertUserIfMetamaskIsNotInstalled) {
// alert(`Please install Metamask first`);
// return;
// }
if (window.Web3Modal.default) {
Web3Modal = window.Web3Modal.default;
}
if (window.WalletConnectProvider) {
WalletConnectProvider = window.WalletConnectProvider.default;
}
const web3Modal = new Web3Modal(this.web3ModalOptions);
return web3Modal;
}
addContract(address,contract) {
this.contracts = [...this.contracts, { address, contract }];
}
}
window.laravelWeb3 = new LaravelWeb3();
</script>
blade;
}
}
Related
executing the fetch code in onNewScanResult multiplt time and hence updating the database accordingly................
initialization of qr scanner.........
this.html5QrcodeScanner = new Html5QrcodeScanner(
qrcodeRegionId,
config,
verbose
); ```Executing scanner when qrcode is scanned```
this.html5QrcodeScanner.render(
this.props.qrCodeSuccessCallback,
this.props.qrCodeErrorCallback
);
}
}
this is main qr code class........
class QrCode extends React.Component {
constructor() {
super();
this.state = {
decodedResults: [],
};
this.onNewScanResult = this.onNewScanResult.bind(this);
}
this is where the executing multiple time is happing.......
onNewScanResult(decodedText, decodedResult) {
`geting data from loacal storage as we saved data earlier in the process about acess level`
const qrRes = decodedText;
const obj = JSON.parse(qrRes);
const token = localStorage.getItem("user");
const userData = JSON.parse(token);
const username = userData[0].userId;
const accesslevel = userData[0].accessLevel;
const result = JSON.parse(qrRes);
const ele = result.ele_name;
const newdata = { ele, username, accesslevel };
const data = {
Element_detail: obj,
accessLevel: newdata.accesslevel,
};
const verifyUser = localStorage.getItem("accessLeveldetails");
const accessdetail = JSON.parse(verifyUser);
```checking is user is verified or not```......
`checking the acess level you can ignore the checking focus on fetch part`....
This particular part is we have to stop executing multiple time so database is only entered with one value
if (accessdetail.accessLevel === data.accessLevel) {
try { ``` this fetch is updating database with multiple entries```
fetch(
data.accessLevel === 20
? `/v0/all_elements_image`
: `/v0/${accessdetail.msg}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(obj),
}
).then((res) => {
console.log(res);
if (!res) {
throw res;
}
return res.json();
});
} catch (error) {
console.log("Error:", error);
}
} else {
alert("WRONG USER");
}
}
}
I'm trying to implement meilisearch api in React native and it is working fine with my simulator and after I publish the app some of the users cannot see the data returning from meilisearch, the error is
{"name":"Invariant Violation","framesToPop":1}
This is my code
Meilisearch.js
import axios from 'axios';
import { meilisearchConfig } from '../Config';
const MeilisearchApi = async (payload, success, failed) => {
try {
const response = await axios({
method: 'post',
url: `${meilisearchConfig?.host}indexes/activities/search`,
data: payload,
headers: {
'X-Meili-API-Key': meilisearchConfig?.apiKey,
},
});
success?.(response?.data);
} catch (err) {
failed?.(err);
}
};
export default MeilisearchApi;
This is the normalizer for returning data
import moment from 'moment';
import { IActivity, IByDateGroupFilter } from 'reducers/types';
export const activityNormalizer = (state, { hits, offset }) => {
const {
melisearchActivityData: { byDate, dates, all },
} = state;
const isRefreshing = offset === 0;
const newAll = isRefreshing ? hits : [...all, ...hits];
const datesNew: string[] = isRefreshing ? [] : dates;
const byDateNew: any = isRefreshing ? {} : byDate;
const byDateGroup: IByDateGroupFilter[] = [];
hits.forEach((activity: IActivity) => {
const date = getFormattedDate(activity.created_at);
if (byDateNew[date]) byDateNew[date].push({ ...activity });
else {
byDateNew[date] = [{ ...activity }];
datesNew.push(date);
}
});
Object.keys(byDateNew).forEach((key) => {
byDateGroup.push({
title: key,
data: byDateNew[key],
});
});
return {
dates: datesNew,
byDate: byDateNew,
byDateGroup,
all: newAll,
};
};
This is how i call my Meilisearch API method
MeilisearchApi(
{
q: search,
filters: filters,
offset: newOffset,
limit: PAGE_SIZE,
},
({ hits }: { hits: any[] }) => {
setDataLoaded(true);
setMelisearchActivitiesToRedux({ hits, offset: newOffset });
if (newOffset === 0) {
sectionList?.current?.scrollToLocation({
itemIndex: 1,
});
}
},
(err: any) => {
setDataLoaded(true);
log(err)
},
);
No Idea how this error happens, when users kill the app and logging again this works fine
I created a frontend javascript for my ruby on rails backend and I am receiving the following error when I try to update a book title:
Error: app.js:65 Uncaught TypeError: Cannot read property 'renderUpdateForm' of undefined
at App.handleEditClick (app.js:65)
I am receiving books titles and their authors from a backend api.
Here is the code:
document.addEventListener('DOMContentLoaded', () => {
const app = new App();
app.attachEventListeners();
app.adapter.fetchAuthors().then(app.createAuthors);
app.adapter.fetchBooks().then(app.createBooks);
});
class Book {
constructor(data) {
this.id = data.id;
this.title = data.title;
const author = Author.findById(data.author_id);
this.author = author.name;
Book.all.push(this);
}
update({ title }) {
this.title = title;
}
renderListItem() {
return `
<li>
<h3>${this.title} - ${this.author}
<button data-id=${this.id}>update</button>
<button data-id=${this.id}>delete</button>
</h3>
</li>`;
}
renderUpdateForm() {
return `
<form data-id='${this.id}'>
<label>Title</label>
<p>
<input type="text" value="${this.title}" />
</p>
<button type='submit'>Save Book</button>
</form>
`;
}
static findById(id) {
return this.all.find(book => book.id === id);
}
}
Book.all = [];
class App {
constructor() {
this.adapter = new Adapter();
this.handleEditClick = this.handleEditClick.bind(this);
this.handleEditClick = this.handleDeleteClick.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.createBooks = this.createBooks.bind(this);
this.createAuthors = this.createAuthors.bind(this);
this.addBooks = this.addBooks.bind(this);
}
attachEventListeners() {
$('#books-list').on('click', 'button', this.handleEditClick);
$('#books-list').on('click', 'button', this.handleDeleteClick);
$('#update').on('submit', 'form', this.handleFormSubmit);
}
createBooks(books) {
books.forEach(book => {
new Book(book);
});
console.log(this);
this.addBooks();
}
createAuthors(authors) {
authors.forEach(author => {
new Author(author);
});
console.log(this);
this.addAuthors();
}
addBooks() {
$('#books-list').empty();
Book.all.forEach(book => $('#books-list').append(book.renderListItem()));
}
addAuthors() {
$('#authors-list').empty();
Author.all.forEach(author => $('#authors-list').append(author.renderListItem()));
}
handleFormSubmit(e) {
e.preventDefault();
const id = e.target.dataset.id;
const book = Book.findById(id);
const title = $(e.target)
.find('input')
.val();
const bodyJSON = { title };
this.adapter.updateBook(book.id, bodyJSON).then(updatedBook => {
const book = Book.findById(updatedBook.id);
book.update(updatedBook);
this.addBooks();
});
}
handleEditClick(e) {
const id = e.target.dataset.id;
const book = Book.findById(id);
$('#update').html(book.renderUpdateForm());
}
handleDeleteClick(e) {
const id = e.target.dataset.id;
const book = Book.findById(id);
const title = $(e.target)
.find('input')
.val();
const bodyJSON = { title };
this.adapter.deleteBook(book.id, bodyJSON);
}
}
class Adapter {
constructor() {
this.baseUrl = 'http://localhost:3000/api/v1';
this.headers = {
'Content-Type': 'application/json',
Accept: 'application/json'
};
}
fetchBooks() {
return this.get(`${this.baseUrl}/books`);
}
fetchAuthors() {
return this.get(`${this.baseUrl}/authors`);
}
updateBook(id, body) {
return this.patch(`${this.baseUrl}/books/${id}`, body);
}
deleteBook(id, body) {
return this.delete(`${this.baseUrl}/books/${id}`, body);
}
get(url) {
return fetch(url).then(res => res.json());
}
patch(url, body) {
return fetch(url, {
method: 'PATCH',
headers: this.headers,
body: JSON.stringify(body)
}).then(res => res.json());
}
delete(url, body) {
return fetch(url, {
method: 'DELETE',
headers: this.headers,
body: JSON.stringify(body)
}).then(res => res.json());
}
}
const book = Book.findById(id);
returns undefined.
Which means there is no entry with that id. e.target.dataset.id probably has a different value than expected (console.log is your friend).
To guard against this type of error (so your app doesn't break when you're using an invalid/non-existent id), you could just wrap next line in a condition:
handleEditClick(e) {
const id = e.target.dataset.id;
const book = Book.findById(id);
if (book) {
$('#update').html(book.renderUpdateForm());
}
}
Better checks are whether the result has a function named renderUpdateForm:
if (book && typeof book.renderUpdateForm === 'function') {
$('#update').html(book.renderUpdateForm())
}
or if it is a Book instance:
if (book instanceof Book) {
$('#update').html(book.renderUpdateForm())
}
I am trying to create a class that will fetch / cache users from my Firestore database. For some reason, I can't seem to save or expose the previous promise that was created. Here is my class:
export class UserCache {
private cacheTimeMilliseconds: number = 600000;
private userCache: any = {};
public getCacheUser(userid: string): Promise<User> {
return new Promise((resolve, reject) => {
let d = new Date();
d.setTime(d.getTime() - this.cacheTimeMilliseconds);
if (this.userCache[userid] && this.userCache[userid].complete && this.userCache[userid].lastAccess > d.getTime()) {
console.log("User cached");
resolve(this.userCache[userid].user);
}
console.log("Need to cache user");
this.userCache[userid] = {
complete: false
};
this.getSetUserFetchPromise(userid).then((data) => {
let user: User = <User>{ id: data.id, ...data.data() };
this.userCache[userid].user = user;
this.userCache[userid].complete = true;
this.userCache[userid].lastAccess = Date.now();
resolve(user);
});
});
}
private getSetUserFetchPromise(userid: string): Promise<any> {
console.log(this.userCache[userid]);
if (this.userCache[userid] && this.userCache[userid].promise) {
return this.userCache[userid].promise;
} else {
console.log("Creating new user fetch request.");
this.userCache[userid].promise = firestore().collection('users').doc(userid).get();
console.log(this.userCache[userid]);
return this.userCache[userid].promise;
}
}
}
Logs: (there are only 2 unique users, so should only be creating 2 new requests)
In the logs I can see that the promise is getting set in getSetUserFetchPromise, but the next time the function is called, the property is no longer set. I suspect it is either a scope or concurrency issue, but I can't seem to get around it.
I am calling getCacheUser in a consuming class with let oCache = new UserCache() and oCache.getCacheUser('USERID')
Edit following Tuan's answer below
UserCacheProvider.ts
import firestore from '#react-native-firebase/firestore';
import { User } from '../static/models';
class UserCache {
private cacheTimeMilliseconds: number = 600000;
private userCache: any = {};
public getCacheUser(userid: string): Promise<User> {
return new Promise((resolve, reject) => {
let d = new Date();
d.setTime(d.getTime() - this.cacheTimeMilliseconds);
if (this.userCache[userid] && this.userCache[userid].complete && this.userCache[userid].lastAccess > d.getTime()) {
console.log("User cached");
resolve(this.userCache[userid].user);
}
console.log("Need to cache user");
this.userCache[userid] = {
complete: false
};
this.getSetUserFetchPromise(userid).then((data) => {
let user: User = <User>{ id: data.id, ...data.data() };
this.userCache[userid].user = user;
this.userCache[userid].complete = true;
this.userCache[userid].lastAccess = Date.now();
resolve(user);
});
});
}
private getSetUserFetchPromise(userid: string): Promise<any> {
console.log(this.userCache[userid]);
if (this.userCache[userid] && this.userCache[userid].promise) {
return this.userCache[userid].promise;
} else {
console.log("Creating new user fetch request.");
this.userCache[userid].promise = firestore().collection('users').doc(userid).get();
console.log(this.userCache[userid]);
return this.userCache[userid].promise;
}
}
}
const userCache = new UserCache();
export default userCache;
ChatProvider.ts (usage)
let promises = [];
docs.forEach(doc => {
let message: Message = <Message>{ id: doc.id, ...doc.data() };
promises.push(UserCacheProvider.getCacheUser(message.senderid).then((oUser) => {
let conv: GCMessage = {
_id: message.id,
text: message.messagecontent,
createdAt: new Date(message.messagedate),
user: <GCUser>{ _id: oUser.id, avatar: oUser.thumbnail, name: oUser.displayname }
}
if (message.type && message.type == 'info') {
conv.system = true;
}
if (message.messageattachment && message.messageattachment != '') {
conv.image = message.messageattachment;
}
return conv;
}));
});
Promise.all(promises).then((values) => {
resolve(values);
});
Without seeing the calling code, it could be that getCacheUser is called twice before firestore resolves.
As an aside, I think refactoring the class may make debugging easier. I wonder why it caches the user, promise completion status, and the promise itself. Why not just cache the promise, something like:
interface UserCacheRecord {
promise: Promise<User>
lastAccess: number
}
export class UserCache {
private cacheTimeMilliseconds: number = 600000;
private userCache: { [userid: string]: UserCacheRecord } = {};
public async getCacheUser(userid: string): Promise<User> {
let d = new Date();
const cacheExpireTime = d.getTime() - this.cacheTimeMilliseconds
if (this.userCache[userid] && this.userCache[userid].lastAccess > cacheExpireTime) {
console.log("User cached");
return this.userCache[userid].promise
}
console.log("Need to cache user");
this.userCache[userid] = {
promise: this.getUser(userid),
lastAccess: Date.now()
}
return this.userCache[userid].promise
}
private async getUser(userid: string): Promise<User> {
const data = firestore().collection('users').doc(userid).get();
return <User>{ id: data.id, ...data.data() };
}
}
Currently, you create new UserCache everytime you access cache users. You have to export the instance of UserCache class, so just single instance is used for your app.
UserCache.ts
class UserCache {
}
const userCache = new UserCache();
export default userCache;
SomeFile.ts
import UserCache from './UserCache';
UserCache.getCacheUser('USERID')
Update
Added some tests
class UserCache {
userCache = {};
getUser(id) {
return new Promise((resolve, reject) => {
if (this.userCache[id]) {
resolve({
...this.userCache[id],
isCache: true,
});
}
this.requestUser(id).then(data => {
resolve(data);
this.userCache[id] = data;
});
});
}
requestUser(id) {
return Promise.resolve({
id,
});
}
}
const userCache = new UserCache();
export default userCache;
userCache.test.ts
import UserCache from '../test';
describe('Test user cache', () => {
test('User cached successfully', async () => {
const user1: any = await UserCache.getUser('test1');
expect(user1.isCache).toBeUndefined();
const user2: any = await UserCache.getUser('test1');
expect(user2.isCache).toBe(true);
});
});
I wrote a unit test for _getuser() but I don't see console.log print stub result.Also test coverage shows line 'let user = result.user;
console.log('User'+JSON.stringify(result));' is uncovered.Why stub result does not print in console log in getUser() function in LogInCommand class.
I see result shows undefined in unit test.
// userApi.js
'use strict';
const config = require('../../config/config');
const api = require('./apiService');
class UserApi {
constructor() {
}
getUser(userId) {
return api.get({
url: config.url,
qs: {
includeInactive: true,
id: userId,
startIndex: 0,
maxResults: 1
},
headers: {
Accept: 'application/json;',
'Connection': 'Keep-Alive'
}
});
}
}
module.exports = UserApi;
// LoginCommand.js
'use restrict';
const userApi = require('../../api/userApi');
class LogInCommand {
constructor() {
}
async _getUser(userId) {
let result = await new userApi().getUser(userId);
let user = result.user;
console.log('User'+JSON.stringify(result));
return user;
}
}
module.exports = LogInCommand;
//LoginCommand.test.js
describe('Test LogInCommand Class',function(){
it.only('_getUser function should return user', async ()=> {
let apiData= {
user:'abc'
};
let logincmd = proxyquire('../LogInCommand.js', {
userApi : { getUser : Promise.resolve(apiData) },'#noCallThru':true});
let obj= new logincmd();
let result= await obj._getUser(client);
});
});
The proxyquire configuration is incorrect in your current setup. Proxyquire maps the string value passed in a require call to the desired mock/stub values. Try the following instead:
let logincmd = proxyquire('../LogInCommand.js', {
'../../api/userApi' : { getUser : Promise.resolve(apiData) },
'#noCallThru':true
});
Below code worked for me
// userApi.js
'use strict';
const config = require('../../config/config');
const api = require('./apiService');
class UserApi {
constructor() {
}
getUser(userId) {
return api.get({
url: config.url,
qs: {
includeInactive: true,
id: userId,
startIndex: 0,
maxResults: 1
},
headers: {
Accept: 'application/json;',
'Connection': 'Keep-Alive'
}
});
}
}
module.exports = UserApi;
// LoginCommand.js
'use restrict';
const userApi = require('../../api/userApi');
class LogInCommand {
constructor() {
}
async _getUser(userId) {
let result = await new userApi().getUser(userId);
let user = result.user;
console.log('User'+JSON.stringify(result));
return user;
}
}
module.exports = LogInCommand;
//LoginCommand.test.js
describe('Test LogInCommand Class',function(){
it.only('_getUser function should return user', async ()=> {
class userApiStub{
constructor(){}
getUser() {
return Promise.resolve({
user:4
});
}
}
let logincmd = proxyquire('../LogInCommand.js', {
'../../api/userApi' :userApiStub },'#noCallThru':true});
let obj= new logincmd();
let result= await obj._getUser(client);
});
});