-
-
Notifications
You must be signed in to change notification settings - Fork 4
Fixes and Performance Improvements #489
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
Changes from all commits
ae5570e
5cc3e6f
53bed83
c411d86
bacff60
3e40c58
77ef1e0
26870c4
8135396
c6a93c6
b4c89ba
f973013
e719e08
3ab27bc
e892ffa
2954294
43e9e99
f60b3b0
a2c83ae
144a083
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| import type { OnCronjobHandler } from '@metamask/snaps-sdk'; | ||
|
|
||
| import { ConfirmTransactionRequest } from '../../../../features/confirmation/views/ConfirmTransactionRequest/ConfirmTransactionRequest'; | ||
| import type { ConfirmTransactionRequestContext } from '../../../../features/confirmation/views/ConfirmTransactionRequest/types'; | ||
| import { state, transactionScanService } from '../../../../snapContext'; | ||
| import type { UnencryptedStateValue } from '../../../services/state/State'; | ||
| import { | ||
| CONFIRM_SIGN_AND_SEND_TRANSACTION_INTERFACE_NAME, | ||
| getInterfaceContextOrThrow, | ||
| updateInterface, | ||
| } from '../../../utils/interface'; | ||
| import baseLogger, { createPrefixedLogger } from '../../../utils/logger'; | ||
|
|
||
| export const refreshConfirmationEstimation: OnCronjobHandler = async () => { | ||
| const logger = createPrefixedLogger( | ||
| baseLogger, | ||
| '[refreshConfirmationEstimation]', | ||
| ); | ||
|
|
||
| logger.info(`Background event triggered`); | ||
|
|
||
| const mapInterfaceNameToId = | ||
| (await state.getKey<UnencryptedStateValue['mapInterfaceNameToId']>( | ||
| 'mapInterfaceNameToId', | ||
| )) ?? {}; | ||
|
|
||
| const confirmationInterfaceId = | ||
| mapInterfaceNameToId[CONFIRM_SIGN_AND_SEND_TRANSACTION_INTERFACE_NAME]; | ||
|
|
||
| // Don't do anything if the confirmation interface is not open | ||
| if (!confirmationInterfaceId) { | ||
| logger.info(`No interface context found`); | ||
| return; | ||
| } | ||
|
|
||
| // Schedule the next run | ||
| await snap.request({ | ||
| method: 'snap_scheduleBackgroundEvent', | ||
| params: { | ||
| duration: 'PT20S', | ||
| request: { method: 'refreshConfirmationEstimation' }, | ||
| }, | ||
| }); | ||
|
|
||
| // Update the interface context with the new rates. | ||
| try { | ||
| // Get the current context | ||
| const interfaceContext = | ||
| await getInterfaceContextOrThrow<ConfirmTransactionRequestContext>( | ||
| confirmationInterfaceId, | ||
| ); | ||
|
|
||
| if ( | ||
| !interfaceContext.account?.address || | ||
| !interfaceContext.transaction || | ||
| !interfaceContext.scope || | ||
| !interfaceContext.method | ||
| ) { | ||
| logger.info(`Context is missing required fields`); | ||
| return; | ||
| } | ||
|
|
||
| // Skip transaction simulation if the preference is disabled | ||
| if (!interfaceContext.preferences?.simulateOnChainActions) { | ||
| logger.info(`Transaction simulation is disabled in preferences`); | ||
| return; | ||
| } | ||
|
|
||
| const fetchingConfirmationContext = { | ||
| ...interfaceContext, | ||
| scanFetchStatus: 'fetching', | ||
| } as ConfirmTransactionRequestContext; | ||
|
|
||
| await updateInterface( | ||
| confirmationInterfaceId, | ||
| <ConfirmTransactionRequest context={fetchingConfirmationContext} />, | ||
| fetchingConfirmationContext, | ||
| ); | ||
|
|
||
| const [scan, updatedInterfaceContextFinal] = await Promise.all([ | ||
| transactionScanService.scanTransaction({ | ||
| method: interfaceContext.method, | ||
| accountAddress: interfaceContext.account.address, | ||
| transaction: interfaceContext.transaction, | ||
| scope: interfaceContext.scope, | ||
| origin: interfaceContext.origin, | ||
| account: interfaceContext.account, | ||
| }), | ||
| getInterfaceContextOrThrow<ConfirmTransactionRequestContext>( | ||
| confirmationInterfaceId, | ||
| ), | ||
| ]); | ||
|
|
||
| // Update the current context with the new rates | ||
| const updatedInterfaceContext = { | ||
| ...updatedInterfaceContextFinal, | ||
| scanFetchStatus: 'fetched' as const, | ||
| scan, | ||
| }; | ||
|
|
||
| logger.info(`New scan fetched`); | ||
|
|
||
| await updateInterface( | ||
| confirmationInterfaceId, | ||
| <ConfirmTransactionRequest context={updatedInterfaceContext} />, | ||
| updatedInterfaceContext, | ||
| ); | ||
|
|
||
| logger.info(`Background event suceeded`); | ||
| } catch (error) { | ||
| const fetchedInterfaceContext = | ||
| await getInterfaceContextOrThrow<ConfirmTransactionRequestContext>( | ||
| confirmationInterfaceId, | ||
| ); | ||
|
|
||
| const fetchingConfirmationContext = { | ||
| ...fetchedInterfaceContext, | ||
| scanFetchStatus: 'fetched', | ||
| } as ConfirmTransactionRequestContext; | ||
|
|
||
| await updateInterface( | ||
| confirmationInterfaceId, | ||
| <ConfirmTransactionRequest context={fetchingConfirmationContext} />, | ||
| fetchingConfirmationContext, | ||
| ); | ||
|
|
||
| logger.info( | ||
| { error }, | ||
| `Could not update the interface. But rolled back status to fetched.`, | ||
| ); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| import type { OnCronjobHandler } from '@metamask/snaps-sdk'; | ||
|
|
||
| import { DEFAULT_SEND_CONTEXT } from '../../../../features/send/render'; | ||
| import { Send } from '../../../../features/send/Send'; | ||
| import type { SendContext } from '../../../../features/send/types'; | ||
| import { assetsService, priceApiClient, state } from '../../../../snapContext'; | ||
| import type { UnencryptedStateValue } from '../../../services/state/State'; | ||
| import { | ||
| getInterfaceContextOrThrow, | ||
| getPreferences, | ||
| SEND_FORM_INTERFACE_NAME, | ||
| updateInterface, | ||
| } from '../../../utils/interface'; | ||
| import baseLogger, { createPrefixedLogger } from '../../../utils/logger'; | ||
|
|
||
| export const refreshSend: OnCronjobHandler = async () => { | ||
| const logger = createPrefixedLogger(baseLogger, '[refreshSend]'); | ||
|
|
||
| logger.info(`Background event triggered`); | ||
|
|
||
| const [assets, mapInterfaceNameToId, preferences] = await Promise.all([ | ||
| assetsService.getAll(), | ||
| state.getKey<UnencryptedStateValue['mapInterfaceNameToId']>( | ||
| 'mapInterfaceNameToId', | ||
| ), | ||
| getPreferences().catch(() => DEFAULT_SEND_CONTEXT.preferences), | ||
| ]); | ||
|
|
||
| const assetTypes = assets.flatMap((asset) => asset.assetType); | ||
|
|
||
| const sendFormInterfaceId = mapInterfaceNameToId?.[SEND_FORM_INTERFACE_NAME]; | ||
|
|
||
| // Don't do anything if the send form interface is not open | ||
| if (!sendFormInterfaceId) { | ||
| logger.info(`No send form interface found`); | ||
| return; | ||
| } | ||
cursor[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Schedule the next run | ||
| await snap.request({ | ||
| method: 'snap_scheduleBackgroundEvent', | ||
| params: { duration: 'PT30S', request: { method: 'refreshSend' } }, | ||
| }); | ||
|
|
||
| // First, fetch the token prices | ||
| const tokenPrices = await priceApiClient.getMultipleSpotPrices( | ||
| assetTypes, | ||
| preferences.currency, | ||
| ); | ||
|
|
||
| // Save them in the state | ||
| await state.setKey('tokenPrices', tokenPrices); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Token Refresh Errors and Unnecessary SchedulingThe
|
||
|
|
||
| // Get the current context | ||
| const interfaceContext = | ||
| await getInterfaceContextOrThrow<SendContext>(sendFormInterfaceId); | ||
|
|
||
| // We only want to refresh the token prices when the user is in the transaction confirmation stage | ||
| if (interfaceContext.stage !== 'transaction-confirmation') { | ||
| logger.info(`❌ Not in transaction confirmation stage`); | ||
| return; | ||
| } | ||
|
|
||
| if (!interfaceContext.assets) { | ||
| logger.info(`❌ No assets found`); | ||
| return; | ||
| } | ||
|
|
||
| // Update the current context with the new rates | ||
| const updatedInterfaceContext = { | ||
| ...interfaceContext, | ||
| tokenPrices: { | ||
| ...interfaceContext.tokenPrices, | ||
| ...tokenPrices, | ||
| }, | ||
| }; | ||
|
|
||
| await updateInterface( | ||
| sendFormInterfaceId, | ||
| <Send context={updatedInterfaceContext} />, | ||
| updatedInterfaceContext, | ||
| ); | ||
|
|
||
| logger.info(`✅ Background event suceeded`); | ||
| }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BugThe
As a result:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1 @@ | ||
| export enum CronjobMethod { | ||
| RefreshSend = 'refreshSend', | ||
| RefreshConfirmationEstimation = 'refreshConfirmationEstimation', | ||
| } | ||
| export enum CronjobMethod {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,5 @@ | ||
| import { type OnCronjobHandler } from '@metamask/snaps-sdk'; | ||
|
|
||
| import { CronjobMethod } from './CronjobMethod'; | ||
| import { refreshConfirmationEstimation } from './refreshConfirmationEstimation'; | ||
| import { refreshSend } from './refreshSend'; | ||
| import type { CronjobMethod } from './CronjobMethod'; | ||
|
|
||
| export const handlers: Record<CronjobMethod, OnCronjobHandler> = { | ||
| [CronjobMethod.RefreshSend]: refreshSend, | ||
| [CronjobMethod.RefreshConfirmationEstimation]: refreshConfirmationEstimation, | ||
| }; | ||
| export const handlers: Record<CronjobMethod, OnCronjobHandler> = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: This will run every 20 seconds or it will run just once? In the case of being periodic will it get cancelled when the confirmation interfaced gets closed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only schedules the next run.
Incidentally, if the confirmation interface gets closed, it runs, but doesn't schedule an other run.
It's basically a loop system, where we enter the loop when the confirmation interface renders, and exit the loop when the interface get closed.