Closed 7flash closed 2 years ago
You can add an onSubmit
to the form (both <form>
and <Form>
but you probably don't need to use the component for this), run event.preventDefault()
and send the transaction directly to the blockchain node as you would have done in a SPA.
Basically, if you don't want to POST against a Remix action send the request manually, nothing prevents you to do this (with proper status handling)
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
let body = new FormData(event.currentTarget)
await fetch(url, { body, method: "POST" })
}
return (
<form onSubmit={handleSubmit}>
<input type="text" name="something" />
</form>
);
Alternatively, I am looking into this approach, does that make sense?
import React from "react";
import { useActionData } from "remix";
import { useWeb3ExecuteFunction } from "moralis";
export function action({ request }) {
let body = await request.formData();
let name = body.get("visitorsName");
return { name };
}
export default function Invoices() {
let data = useActionData();
useEffect(() => {
useWeb3ExecuteFunction({
contractAddress: "",
functionName: "",
params: data
}).fetch()
}, [data]);
return (
<Form method="post">
<p>
<label>
What is your name?
<input type="text" name="visitorsName" />
</label>
</p>
<p>{data ? data.message : "Waiting..."}</p>;
</Form>
);
}
That's going to send the Form to the server, to get the same data you have in the form returned untouched, so you can run an effect.
It sounds like a waste of request, attach a onSubmit to the form and send the data to the blockchain node directly.
Also, that useEffect is not going to work, you can't call a hook inside another hook, you need to do
let { fetch } = useWeb3ExecuteFunction({
contractAddress: "",
functionName: "",
params: data
})
And then call fetch
inside inside the onSubmit handler (or your effect).
How can I make MetamaskForm component which would keep all advantages of Remix Form but instead of POST action, it would invoke transaction with exact fields provided in form? That would be so cool then, we wouldn't need to implement effects for each transaction, but simply implement form elements each time user needs to submit any transaction
You could extract the form with the onSubmit to a MetamaskForm if you want, but you are not going to get to use useTransition like with Remix Form without using an action. Is there no way you can submit the data to the blockchain node server-side? That way you keep using Form and actions and from the action you do the fetch to the node.
Because transaction should be signed client-side, but then yes it can be serialized and passed to backend to be broadcasted to network. But then it should also be observed for confirmation or failure within few minutes.
It means when form submitted, then first effect should be called to sign transaction, and after form with modified fields should be submitted, and then transaction id returned from backend, and listened to on client. I am thinking how can common component be implemented to incapsulate this logic and let us enjoy simple forms once again.
@7flash any news on this? I'm wondering if we could easily use Remix for Web3 while using its capabilities and not relying in client-side code.
@bjufre what would you expect Remix to add in order to be web3 compatible?
I know nothing about that but from the little bit I saw you either use server-side code which should work inside loaders/actions to read/write things from the blockchain or your use client-side code to connect to a user wallet and do the same which should work as normal React code.
What else is missing from Remix side?
@sergiodxa I guess nothing that I can think of right now, I was just trying to gather some information from @7flash to see how he approached this in the end, if client side or server side.
The problem is metamask does not have a public ip address /api for remix server to connect, so it not possible to remote sign transactions
Is that possible to run backend code in frontend worker and create a server listening for requests? Then we can create an abstraction over web3 interactions and common components for it.
You can add an
onSubmit
to the form (both<form>
and<Form>
but you probably don't need to use the component for this), runevent.preventDefault()
and send the transaction directly to the blockchain node as you would have done in a SPA.Basically, if you don't want to POST against a Remix action send the request manually, nothing prevents you to do this (with proper status handling)
async function handleSubmit(event: FormEvent<HTMLFormElement>) { event.preventDefault() let body = new FormData(event.currentTarget) await fetch(url, { body, method: "POST" }) } return ( <form onSubmit={handleSubmit}> <input type="text" name="something" /> </form> );
For this approach, how do you trigger a rerender of the current route?
What you're requesting imo should be implementable without the need for a Remix feature addition. You can already use forms and invoke window object. You just need to connect the dots.
The form actions part is already sufficiently documented.
Here's an example of invoking MetaMask window:
// method to invoke sign message with browser wallet
declare global {
interface Window {
ethereum: any;
}
}
export const hasMetaMask =
typeof window !== "undefined" &&
typeof window.ethereum !== "undefined" &&
typeof window.ethereum.isMetaMask !== "undefined";
export const signMetamaskMessage = async (message: string) => {
if (!hasMetaMask) return;
try {
const address = await (
await window.ethereum.request({
method: "eth_requestAccounts",
})
)[0];
const signature = await window.ethereum.request({
method: "personal_sign",
params: [address, message],
});
return signature;
} catch (error) {
if ((error as any).code === 4001) console.log("User denied request");
}
};
Then import it into one of your client files and
export default function Index() {
return (
<button onClick={() => signMetamaskMessage("WAGMI")}>
Sign Message
</button>
);
}
Btw, I found this issue trying to use Moralis SDK with Remix.run so this is helpful 🙌
If anyone else comes across this, I found this video to be super helpful too:
Hi @7flash 👋
Did you manage to get Moralis to work with Remix? I've been struggling with this for the last few days, but I'm progressing too slowly since I'm learning both Remix and Moralis 😅
o-az's solutions looks good for signing with MetaMask, but I'm hoping to get Moralis to work and struggling to adapt. Any help from anyone would be greatly appreciated 🙏
What is the new or updated feature that you are suggesting?
Allow custom handlers of form submission. Specifically, I would like to invoke metamask window when form is submitted, instead of sending POST action.
Why should this feature be included?
I am looking to build dapp, i.e. decentralized application which performs mutations by sending transactions directly from browser to blockchain node, avoiding backend POST actions.