web3React and solana/web3.js in one lib working together with MetaMask and Phantom wallets - web3js

is there any library out there that integrates web3React and solana/web3.js so that they can co-exist and do all the operations when the user switches chains from EVM chains to Solana and the other way back, as well as support for chainId and account?
If not, how would you approach the following:
User connects to Phantom wallet via solanaProvider.connect() on a button click. Now the user has access to a list of chains [1, 56, 137, 'Solana'] that they can choose from to switch to another network. The user connected to chain 'Solana' and we now have access to PublicKey. But now the user wants to switch to EVM chains ([1, 56, 137]). How do you handle this action in the app. There is no RPCs method to switch from Solana to EVM since Solana has not been build in cross-chain way so we do not have methods that would allow to switch like we do with
evmProvider.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: '0x${chainId.toString(16)}' }], })
So you can easily switch from EVM to EVM chain using the RPC methods and web3React lib will emit the events properly and update chainId and account. But how do you handle the EVM to non-EVM chain switch so that the front-end knows that user now wants to be on chain 1 and evmAccount or other way round.
So far I have been using web3React lib and augmented it to my own hook, let's call it useMyWeb3ReactHook with some extra changes. There I also packed in a custom-built useMySolanaWeb3Hook that returns provider, pubKey and chainID.
The app so far is using useMyWeb3ReactHook in different places and I would like to keep just one hook from which the app reads provider, (pubKey || account) and chainID.
I also have at least 3 places where I request the chain switch just by passing chainID to wallet_switchEthereumChain method. I was thinking of creating a redux state, let's call it nonEvmState that would also get updated if requested chainID === 'Solana' and then pass that nonEvmState to useMyWeb3ReactHook where I would say if nonEvmState then chainID is 'Solana'. If user wants to switch back to EVM -> Reset the nonEvmState and hopefully switch back to evm chain.
How others are doing it that support EVM and Solana? Would be curious to learn.
Thanks for your suggestions

Related

Is it a good practice to allocate a Redux state dedicated to entity creation with a 'fire-and-forget' API?

In several blogs video and so on, there's a CRUD tutorial with Redux.
None of them (AFAIK after surfing) deal with fully async API on servers, like a fire-and-forget behavior.
Main commands in a CQRS environment deal frequently with those kind of fire-and-forget.
Let's take a fictive example of Twitter to easily get the idea:
Basically, in a context of a synchronous CRUD API, you likely have:
Redux Action: POST_TWEET
Server API: returning the entire created tweet in the response data.
State: TweetReducer exploring and storing the created tweet's data from the response.
UI: listening to the new tweet from the Tweet state directly.
The TweetReducer, besides the classical fetching APIs, can fully handle the POST_TWEET action since it can encompass the new tweet directly.
However, in a context of fire-and-forget API on the server:
Redux Action: POST_TWEET
Server API: returning only the tweet's id (e.g Location) in the response.
State: TweetReducer does not handle the creation since the tweet is not available at the time of the success action triggering.
Thus a new Redux state dedicated to handle tweet creation labeled TweetCreation typically owning those properties: (data: {id: string}, inProgress: boolean, errors: []).
It would then grab the newly created tweet's id in the data and allow UI to listen to this state (TweetCreation).
UI: listening to TweetCreation state and hence displays that the tweet is sent or even tries to fetch the server at some time interval to get the full tweet.
Is it a good practice some people experiment to add another state on the Redux store to deal with fire-and-forget APIs?
Is it "conventional" in the community or is there another clever way?
1. Creating a separate state for pending tweets
For a start, you'd need to change your TweetCreation to an array in case the user makes a second tweet before the first is confirmed.
So your shape would look like this: { pendingTweets: [], confirmedTweets: [] }.
In POST_TWEET, you append the new tweet to pendingTweets.
In SET_TWEET_ID, you remove the matching tweet from pendingTweets and push it to confirmedTweets.
In your component, you probably do something like confirmedTweets.concat(pendingTweets).map(...).
2. Use the same state for pending tweets
The shape will just be { tweets: [] }.
In POST_TWEET, you append the new tweet to tweets.
In SET_TWEET_ID, you update the matching tweet in tweets.
In your component, you do tweets.map(...).
Conclusion
Using the same state for pending tweets seems like a simpler (and therefore better) approach.
Additional considerations (for both approaches)
I left out details about avoiding direct state mutations when updating since that's very basic.
You probably need to do something like generating a temporary id for the pending tweet and sending it back from the server so that you can find the matching tweet in SET_TWEET_ID.
The temporary id can use a different object key (or use an additional flag) so that you can distinguish between a pending and a confirmed tweet in the component (eg. to render a loading icon beside pending tweets).
Replacing [] with {} using id as object key might be better (depending on the exact requirements) but that's not the focus of this question.

Should I use firebase cloud functions for every http request?

Writing a React Native App that allows users to Register, Login, Update Account Info, Post (Each post contains a short message with 1500 chars or less and/or up to 9 images) and Download Posts. I can do all these tasks without using cloud functions, but I wonder which approach is better and why?
For example, to Set user's account info, I could do something like this in my app:
firebase.database().ref(`users/${uid}`)
.set({
firstName: 'Stack',
lastName: 'Overflow'
});
Or I could simply write a firebase cloud function and every time I want to set a user's account info, I could do something like this:
const SET_ACCOUNT_URL = 'https://firebase.set_account_url.com';
axios.post(SET_ACCOUNT_URL, {
firstName: 'Stack',
lastName: 'Overflow'
})
.then(() => ...Do Something Here...)
.catch((error) => console.log(error));
Which approach is better and why?
A lot depends on scale here. If you're remaining within the free plan limits, the sky is the limit. If you're working at scale, then you'll be paying for the bandwidth to RTDB as well as the invocations of Functions, which could be superfluous.
It's hard to predict what will be useful without knowing your use case see XY problem.
As a general rule, you can always add functions later, since they can be triggered from a DB write. So if a write suffices, just do that. Later, you can trigger an event off of that write to take any further actions you need.
If you need to hide proprietary functionality (i.e. trademark algorithms or secured game logic) use a Function. If you know you'll be doing calculations on that data or if it can't be triggered by a DB event, then use a Function.
If it's just going to end up in the Database and the goal is validation or restricting access, write to the DB and use security rules.

Coalescing Flux Actions

This is a detailed Flux Architecture question.
Say I have a resource that gets asynchronously prepared. Let's take User Data as an example.
There are multiple different ways to get this user data - in our example it may be that it requires a few different subsequent queries to generate from the server or is stored locally as a whole.
Case 1:
User data needs sequential steps. Fire USER_DATA_1_SUCESS, USER_DATA_2_SUCCESS. Other stores listen for USER_DATA_2_SUCCESS.
Case 2:
User Data is locally available as a whole. Fire a USER_DATA_READY action.
I'm trying to figure out how to go from a linear state completion (USER_DATA_2_SUCESS) to a resource ready event (USER_DATA_READY) in the stores. I can't call USER_DATA_READY directly from the stores - I get a can't call action in the middle of dispatch error. At the same time I want granularity - I want to control the different stages of putting the data together.
I'd like to have one way to condense these calls with good design. The option I can think of is:
Add a convenience 'Ready' function in a client class that is visible to the store. Call it with a tiny timeout in the stores callback for USER_DATA_2_SUCCESS.
Can anyone suggest a better flow?

Firebase having thousands of on() event listeners good design

We need to run some operation on our Firebase DB and manipulate data after certain input is given by user from the Mobile Device modifying a flag.
Currently we are using on() to listen to particular flag in each users node. We are running this listener from a Nodejs server hosted on Heruku.
If we plan to have 100 thousand users we will have 100 thousand listener. One listener for each users flag which is waiting to be manipulated by user on the Mobile device.
Is this a good design in terms of Firebase?
Ideally we can create a REST API which is called by users and then on the Node JS server we can manipulate the data.
What is the best way to run background operation on Data on Firebase based on user input?
We were using Parse earlier and it was easy to achieve this using Parse Cloud code. With Firebase we are having issues because of this.
If we plan to have 100 thousand users we will have 100 thousand listener. One listener for each users flag which is waiting to be manipulated by user on the Mobile device.
This sounds like a bad data design. While it is definitely possible to listen for changes to hundreds of thousands of items, it shouldn't require hundreds of thousands listeners.
My guess (because you didn't include a snippet of your JSON) is that you have a structure similar to this:
users
$uid
name: "user6155746"
flag: "no"
And you're attaching a listener in just the flag of each user with something like:
ref.child('users').on('child_added', function(userSnapshot) {
userSnapshot.ref().child('flag').on('value', function(flagSnapshot) {
console.log('the flag changed to '+flagSnapshot.val());
});
})
In code this is simple, in practice you'll have a hard time managing the "flag listeners". When will you remove them? Do you keep a list of them?
All of these things become a list simpler if you isolate the information that you're interested in in the JSON tree:
users
$uid
name: "user6155746"
userFlags
$uid: "no"
Now you can just listen on userFlags to see if the flag of any user has changed:
ref.child('userFlags').on('child_changed', function(userSnapshot) {
console.log('Flag of user '+userSnapshot.key()+' changed to '+userSnapshot.val());
});
With this you have a single listener, monitoring the flag of potentially hundreds of thousands of users.

What are appropriate action types in react.js?

In the Flux examples, the two action types I noticed are view actions & server actions. Are there any other action types to be concerned about from a large app perspective? I'm just thinking of appropriate patterns to use for the long term.
https://github.com/facebook/flux/tree/master/examples
Actions are just actions. If there's an action you use when getting the current user from the server, you could also create that action some other time (such as getting the user from local storage, etc.).
The two most common sources of events are from the UI and the server, however you could also have actions triggered on a timer (setInterval) or from a global event handler (e.g. window's resize), or third party libraries which get it from any source.
Perhaps a better word for and 'action' in flux would be an 'intent'. It doesn't actually do anything on its own, it just suggests something be done; the dispatcher dispatches the intent, and stores can do something (i.e. take action) based on the intent.
"view actions & server actions" is either too specific or too vague. You should either consider all actions equal (my personal take), or consider there to be hundreds of action types.
I'm just thinking of appropriate patterns to use for the long term.
I don't quite see how classifying actions affects patterns you use. Grouping of actions is more about which ones you want to generally expose to which other modules. For example ChatServerActionCreators is only used by utils/ChatWebAPIUtils. It's a matter of encapsulation rather than grouping by related functionality.
Thanks, I suppose I was also indirectly asking why these event sources
exist.
Also there is this discussion on google forums answered by Bill Fisher from FB:
Q: The todo-list example mentions a possible handleServerAction in
addition to handleViewAction - can someone give some color as to why
you might want to handle server actions differently from view actions?
I'm guessing a server action is triggered through polling, sockets, or
some external event, but is there a common case/example where it's
useful to check between the two types of actions? Just curious here,
as nothing obvious jumped out (i.e. marking an item as a favorite
should trigger the same codepath, regardless of where it came from).
A: As far as the server actions vs. the view actions goes, I think it's
more common to detect a view action and act differently upon it. For
example, you might want to only run a validation when the data comes
from user input, rather than on server initialization. I left that in
there just to show that you can do whatever you want with the payload,
that there can be this kind of structure providing metadata around the
Action, allowing you to group different actions together for whatever
purpose you need. You don't have to use these handleViewAction or
handleServerAction or handleServerInitializationAction (etc) methods,
but I've found it to be occasionally useful.

Resources