Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Multi-chain implementation #180

Merged
merged 38 commits into from
Mar 17, 2024
Merged

Initial Multi-chain implementation #180

merged 38 commits into from
Mar 17, 2024

Conversation

hcho112
Copy link
Collaborator

@hcho112 hcho112 commented Mar 4, 2024

DO NOT MERGE, this PR is currently created for review/discussion with the maintainers.
This has been implemented along with:
https://gist.github.com/esaminu/8ecfd8524a3404d34135acde9c7cbb8b
https://gist.github.com/esaminu/f8cc37849de754f228c5a67bebce9b0f

Current out put
image

Todo:

  1. Integrate with near-fastauth-wallet and use it against real world example
  2. Update Infura account API
  3. Any UI/UX improvements feedback
  4. Check if gas fee calculation is correct. (It seems too low, but couldn't figure out what went wrong..)

Feel free to leave comments on things that are missing.

@hcho112 hcho112 requested review from esaminu and Pessina March 4, 2024 04:26
Copy link

vercel bot commented Mar 4, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
fast-auth-signer ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 17, 2024 11:32pm

@@ -40,11 +41,14 @@ const onCreateAccount = async ({
email,
gateway,
}) => {
// Stop from LAK with multi-chain contract
const containBlacklistedContractId = getMultiChainContract() === contract_id;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we should throw earlier i.e. in the create account and add device pages to save the user the trouble. It should throw only if multichain contract is explicitly passed. If no value is passed we can continue the flow and only authenticate the signer

});

const onError = (text: string) => {
window.parent.postMessage({ signedDelegates: '', text }, '*');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a different payload than the error on line 47. Can we standardize and also would be useful if you documented the possible requests and responses in the PR or on a README on the folder

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will try to make it similar withn SignMultichain component, but convention is already diverged on everywhere else in this repo. (eg. Existing Sign component)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created issue for handling above issue across whole repo #183
Should be handled separately later

};

window.addEventListener(
'multichain-message',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should just be a message event

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why I gave different name is because on RpcRoute component handles add/remove event listener. Initially I thought I want to handle it separately, but actually its better to keep the same name, so will change this to 'message'

useEffect(() => {
const handleMessage = (event) => {
console.log('event', event);
// Maybe add origin check here? if url of origin is available, maybe update below
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes we should add a check for event.origin and compare with domain in the derivation path as part of the validation. If it's the same we can just proceed without prompting the user

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const newPublicKeyPoint = oldPublicKeyPoint.add(scalarTimesG);

return `04${
newPublicKeyPoint.getX().toString('hex')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const methodNames = searchParams.get('methodNames');
const contract_id = searchParams.get('contract_id');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicated, no? You are also defining it at line 123

@@ -119,6 +120,16 @@ function CreateAccount() {
const [searchParams] = useSearchParams();
const [inFlight, setInFlight] = useState(false);

const contractId = searchParams.get('contract_id');
useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicated, isn't better create a custom hook for it?

Or call it only from the App.ts? (you set it to run only for routes that aren't /multi-chain)

const methodNames = searchParams.get('methodNames');
const contract_id = searchParams.get('contract_id');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated, declared above too, no?

@@ -0,0 +1,33 @@
import { EVMInterface, BTCInterface, MultichainExecutionResponse, InitializationConfig } from './types';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are already planning it, but just to not. This can be removed

});
setInFlight(false);
if (response.success) {
window.parent.postMessage({ type: 'response', message: `Successfully sign and send transaction, ${response.transactionHash}` }, '*');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should post the transaction hash, so the parent can check it's status, results or whatever it needs to do

if (response.success) {
window.parent.postMessage({ type: 'response', message: `Successfully sign and send transaction, ${response.transactionHash}` }, '*');
} else {
// @ts-ignore
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need @ts-ignore here?

onError(response?.errorMessage);
}
} catch (e) {
setInFlight(false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go on the finnaly block, no?

}, [deserializedDerivationPath?.asset, deserializedDerivationPath?.domain, isValid, message]);

// If domain info passed from derivation path is same as window.parent.orgin, post message to parent directly
useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you can use a single useEffect on this page where it performs

setEventListener => receiveMessage => validateMessage => signMultiChain

With that you optimize the code and make it more easy to read.


try {
if (amountInfo.tokenAmount === 0 && message) {
setInFlight(true);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setInFlight should only be managed on the top level functions.

Doing something like

const topLevel = async () => {
setInFlight(true)
  try {
    await processMessage();
  } catch (e) {
    onError(e);
  } finally {
    setInFlight(false);
  }
};

Inside the processMessage you don't need to setInFlight, you only throw the error if necessary

The process mesage will be the onConfirm and the eventListener

import { BorshSchema } from 'borsher';

export const derivationPathSchema = BorshSchema.Struct({
asset: BorshSchema.String,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it should be a string.

I think it's better create a enum of supported chains and re-use it on all the places where you do chain checks.

const res = await getMultichainCoinGeckoPrice(asset);
if (!res) {
return {
price: 0,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can't get the data, I think it's better to use null/undefined so it's clear for the caller that the data couldn't be fetched. 0 still a number


export const getMultichainCoinGeckoPrice = async (asset: DerivationPathDeserialized['asset']) => fetchGeckoPrices(multichainAssetToCoinGeckoId(asset));

const convertTokenToReadable = (value : MultichainInterface['value'], asset: DerivationPathDeserialized['asset']) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't better getTokenAmount() I think it's more readable and down there you do

const tokenAmount = convertTokenToReadable()

I think it sounds more readable

};
}
return {
price: 0,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

};
};

export const shortenAddress = (address: string): string => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2024-03-16 at 1 23 50 AM

There are some duplicated numbers, is this a bug? I think the user would expect the two parts of the string to be not overlapping.

That's what I would expect

Pessina
Pessina previously approved these changes Mar 17, 2024
@hcho112 hcho112 merged commit b74a06c into main Mar 17, 2024
5 of 6 checks passed
@Pessina Pessina deleted the multi-chain-singer branch May 31, 2024 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants