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

Adding tenderly simulation #49

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

ragingrahul
Copy link

@ragingrahul ragingrahul commented Jul 24, 2023

Description

Implemented tenderly transaction simulation

To Know

TENDERLY_USER,TENDERLY_PROJECT,TENDERLY_ACCESS_KEY can be found USER & PROJECT and ACCESS-KEY

Related Issues

#2488

@vercel
Copy link

vercel bot commented Jul 24, 2023

@ragingrahul is attempting to deploy a commit to the Abacus Works Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Collaborator

@jmrossy jmrossy left a comment

Choose a reason for hiding this comment

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

Thanks @ragingrahul for the PR! This is a good start but it's incomplete and a bit sloppy. Is there a way to use the Tenderly APIs without a user's secret access key? If not, how did you intend to get that from the user?

package.json Outdated
@@ -10,6 +10,7 @@
"@metamask/jazzicon": "https://github.com/jmrossy/jazzicon#7a8df28974b4e81129bfbe3cab76308b889032a6",
"@rainbow-me/rainbowkit": "^0.11.0",
"@tanstack/react-query": "^4.24.10",
"axios": "^1.4.0",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use the browser native fetch API, no need to add a new library just for a POST request :)

const [isOpen, setIsOpen] = useState(false);
const disabled=false
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 you have a var here if it never changes?

Comment on lines 245 to 247
<button onClick={async()=>{
handleClick()
await simulateCall({contract,handleCalldata,chainId})
Copy link
Collaborator

Choose a reason for hiding this comment

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

Move this line to the click handler

if (!debugResult?.calldataDetails) return null;
const { contract, handleCalldata } = debugResult.calldataDetails;
function handleClick() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

event handlers (like click) should use lambda (arrow fn) syntax to be bound correctly.

const [isOpen, setIsOpen] = useState(false);
const disabled=false
const [buttonText,setButtonText]=useState<string>("Simulate Handle Call")
Copy link
Collaborator

Choose a reason for hiding this comment

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

The <string> type is inferred so it's unnecessary here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Change to Simulate call with Tenderly

save_if_fails: true,
simulation_type: 'full',
network_id: chainId,
from: '0xdc6bdc37b2714ee601734cf55a05625c9e512461',//can be any address, doesn't matter
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use the 0 address if you just need a placeholder (ethers.constants.zeroAddress)

Comment on lines 277 to 279
gas: 8000000,
gas_price: 0,
value: 0,
Copy link
Collaborator

Choose a reason for hiding this comment

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

You'll need to use the real values from the message for an accurate simulation.

}
);
console.timeEnd('Simulation');
console.log(resp.data)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use the logger utility instead of console and add a message to provide context for the data you're logging

}
)
console.log(share)
window.location.assign(`https://dashboard.tenderly.co/shared/simulation/${resp.data.simulation.id}`)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please open the tenderly window in a new tab

@ragingrahul ragingrahul reopened this Jul 28, 2023
Copy link
Collaborator

@jmrossy jmrossy left a comment

Choose a reason for hiding this comment

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

Good progress but please be more mindful to stay consistent with other parts of the codebase

src/consts/config.ts Show resolved Hide resolved
Comment on lines 223 to 224
setDisabled(false)
setShowSpinner(false)
Copy link
Collaborator

Choose a reason for hiding this comment

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

The disabled state always equals the showSpinner state so there's no reason to create 2 state vars. Can you please use the replace them with a single [loading, setLoading] state that is the inverse of disabled now?

from: '0x0000000000000000000000000000000000000000',//can be any address, doesn't matter
to: contract,
input:handleCalldata,
gas: Number(message.totalGasAmount),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use BigNumber.from(message.totalGasAmount).toNumber()

to: contract,
input:handleCalldata,
gas: Number(message.totalGasAmount),
gas_price: Number(message.totalPayment)/Number(message.totalGasAmount),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use the computeAvgGasPrice util function here. It handles possible rounding issues:
https://github.com/hyperlane-xyz/hyperlane-explorer/blob/main/src/features/messages/cards/GasDetailsCard.tsx#L168

value: 0,
}
const resp=await fetch(
`https://explorer.hyperlane.xyz/api/simulation`,{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove the https://explorer.hyperlane.xyz prefix. It's implied when coming from the same domain and will break the feature in dev builds

src/features/messages/cards/TransactionCard.tsx Outdated Show resolved Hide resolved
src/features/messages/cards/TransactionCard.tsx Outdated Show resolved Hide resolved
src/pages/api/simulation.ts Outdated Show resolved Hide resolved
const data=req.body

const resp = await fetch(
`https://api.tenderly.co/api/v1/account/${TENDERLY_USER}/project/${TENDERLY_PROJECT}/simulate`,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Check that these env vars are defined and throw a helpful here at the top if they're not

},
}
)
res.json(simulationId)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator

@jmrossy jmrossy left a comment

Choose a reason for hiding this comment

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

Almost there!

Comment on lines 265 to 266


Copy link
Collaborator

Choose a reason for hiding this comment

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

Spacing? Please run yarn prettier and the files will get auto-formatted :)


}

function computeAvgGasPrice(unit: string, gasAmount?: BigNumber.Value, payment?: BigNumber.Value) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why did you duplicate this function here? Please de-dupe with the copy in GasDetailsCard and move it to messages/utils.ts

src/types.ts Show resolved Hide resolved
</div>
</Modal>
</>
);
}
async function simulateCall({contract,handleCalldata,chainId,message}:{contract:string,handleCalldata:string,chainId:ChainId,message:Message}){

Copy link
Collaborator

Choose a reason for hiding this comment

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

Wrap the function contents here in a try/catch and show an error message with toast.error on failure

Copy link
Author

Choose a reason for hiding this comment

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

Didn't wrap this in try/catch, rather wrapped the backend call which returns failure call and checking if the call is success or failure here.

Copy link
Collaborator

@jmrossy jmrossy left a comment

Choose a reason for hiding this comment

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

Code looks okay, just one small comment, but there should be no yarn.lock file changes. That's likely why the CI is failing.

)
res.json(successResult(simulationId))
} catch (error) {
res.json(failureResult("Could not simulate"))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please change to "Error preparing Tenderly simluation"

export default async function handler(req, res) {
const data = req.body;
if (!TENDERLY_ACCESS_KEY || !TENDERLY_PROJECT || !TENDERLY_USER) {
console.log('ENV not defined');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use logger instead of console, I believe this will raise a linter warning

Copy link
Collaborator

Choose a reason for hiding this comment

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

Change log message to something more descriptive: Tenderly key, project, or user not defined in env

const data = req.body;
if (!TENDERLY_ACCESS_KEY || !TENDERLY_PROJECT || !TENDERLY_USER) {
console.log('ENV not defined');
res.json(failureResult('Explorer Issues'));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Change to 'Tenderly credentials missing'

@@ -236,11 +258,51 @@ function CallDataModal({ debugResult }: { debugResult?: MessageDebugResult }) {
</p>
<LabelAndCodeBlock label="Recipient contract address:" value={contract} />
<LabelAndCodeBlock label="Handle function input calldata:" value={handleCalldata} />
<button onClick={handleClick} disabled={loading} className="underline text-blue-400">
Copy link
Collaborator

Choose a reason for hiding this comment

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

Show only when not loading (see feedback on discord).
Please also reduce text size: text-sm

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.

2 participants