-
Notifications
You must be signed in to change notification settings - Fork 400
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
Mezoification: Add base state and UI elements #3785
base: main
Are you sure you want to change the base?
Changes from 13 commits
5bb9810
0f25b31
0a7d996
0ac12cf
141f7de
9c2ac79
52bd1e9
ee66fe0
6422370
789b942
ef04377
ae1f3c5
09361e2
77f3ba0
4a9f079
e56f90d
4671a6e
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,28 @@ | ||
import { Interface } from "ethers/lib/utils" | ||
import { AnyEVMTransaction, sameNetwork } from "../networks" | ||
import { MEZO_TESTNET } from "../constants" | ||
import { sameEVMAddress } from "./utils" | ||
|
||
const BORROWER_CONTRACT_ADDRESS = "0x20fAeA18B6a1D0FCDBCcFfFe3d164314744baF30" | ||
|
||
const BorrowerABI = new Interface([ | ||
"function openTrove(uint256 _maxFeePercentage, uint256 debtAmount, uint256 _assetAmount, address _upperHint, address _lowerHint)", | ||
]) | ||
|
||
// eslint-disable-next-line import/prefer-default-export | ||
export const checkIsBorrowingTx = (tx: AnyEVMTransaction) => { | ||
if ( | ||
!sameNetwork(tx.network, MEZO_TESTNET) || | ||
!tx.blockHash || | ||
!sameEVMAddress(tx.to, BORROWER_CONTRACT_ADDRESS) | ||
) { | ||
return false | ||
} | ||
|
||
try { | ||
const data = BorrowerABI.decodeFunctionData("openTrove", tx.input ?? "") | ||
return data.debtAmount > 0n | ||
} catch (error) { | ||
return false | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,13 @@ export const defaultSettings = { | |
autoLockInterval: DEFAULT_AUTOLOCK_INTERVAL, | ||
} | ||
|
||
export type MezoClaimStatus = | ||
| "not-eligible" | ||
| "eligible" | ||
| "claimed-sats" | ||
| "borrowed" | ||
| "campaign-complete" | ||
|
||
export type UIState = { | ||
selectedAccount: AddressOnNetwork | ||
showingActivityDetailID: string | null | ||
|
@@ -47,6 +54,13 @@ export type UIState = { | |
routeHistoryEntries?: Partial<Location>[] | ||
slippageTolerance: number | ||
accountSignerSettings: AccountSignerSettings[] | ||
activeCampaigns: { | ||
"mezo-claim"?: { | ||
dateFrom: string | ||
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. Guessing if we make this 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. Yup, it will remain a string 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. I wonder if we should give our serializer/deserializer the ability to deal with dates tbh (not as a blocker though). |
||
dateTo: string | ||
state: MezoClaimStatus | ||
} | ||
} | ||
} | ||
|
||
export type Events = { | ||
|
@@ -78,6 +92,7 @@ export const initialState: UIState = { | |
snackbarMessage: "", | ||
slippageTolerance: 0.01, | ||
accountSignerSettings: [], | ||
activeCampaigns: {}, | ||
} | ||
|
||
const uiSlice = createSlice({ | ||
|
@@ -222,6 +237,22 @@ const uiSlice = createSlice({ | |
...state, | ||
settings: { ...state.settings, autoLockInterval: payload }, | ||
}), | ||
updateCampaignState: <T extends keyof UIState["activeCampaigns"]>( | ||
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. When we start pulling |
||
immerState: UIState, | ||
{ | ||
payload, | ||
}: { | ||
payload: [T, Partial<UIState["activeCampaigns"][T]>] | ||
}, | ||
) => { | ||
const [campaignId, update] = payload | ||
|
||
immerState.activeCampaigns ??= {} | ||
immerState.activeCampaigns[campaignId] = { | ||
...immerState.activeCampaigns[campaignId], | ||
...update, | ||
} | ||
}, | ||
}, | ||
}) | ||
|
||
|
@@ -246,6 +277,7 @@ export const { | |
setSlippageTolerance, | ||
setAccountsSignerSettings, | ||
setAutoLockInterval, | ||
updateCampaignState, | ||
} = uiSlice.actions | ||
|
||
export default uiSlice.reducer | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,8 @@ interface Events extends ServiceLifecycleEvents { | |
* handling sending and persistance concerns. | ||
*/ | ||
export default class AnalyticsService extends BaseService<Events> { | ||
#analyticsUUID: string | undefined = undefined | ||
|
||
/* | ||
* Create a new AnalyticsService. The service isn't initialized until | ||
* startService() is called and resolved. | ||
|
@@ -93,6 +95,7 @@ export default class AnalyticsService extends BaseService<Events> { | |
|
||
protected override async internalStartService(): Promise<void> { | ||
await super.internalStartService() | ||
const { uuid, isNew } = await this.getOrCreateAnalyticsUUID() | ||
|
||
let { isEnabled, hasDefaultOnBeenTurnedOn } = | ||
await this.preferenceService.getAnalyticsPreferences() | ||
|
@@ -114,8 +117,6 @@ export default class AnalyticsService extends BaseService<Events> { | |
} | ||
|
||
if (isEnabled) { | ||
const { uuid, isNew } = await this.getOrCreateAnalyticsUUID() | ||
|
||
browser.runtime.setUninstallURL( | ||
process.env.NODE_ENV === "development" | ||
? "about:blank" | ||
|
@@ -126,6 +127,8 @@ export default class AnalyticsService extends BaseService<Events> { | |
await this.sendAnalyticsEvent(AnalyticsEvent.NEW_INSTALL) | ||
} | ||
} | ||
|
||
this.#analyticsUUID = uuid | ||
} | ||
|
||
protected override async internalStopService(): Promise<void> { | ||
|
@@ -134,6 +137,15 @@ export default class AnalyticsService extends BaseService<Events> { | |
await super.internalStopService() | ||
} | ||
|
||
get analyticsUUID() { | ||
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. From below it looks like we can lose this? 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. If you're referring to the error below, that's just to block access until service has initialized. This could happen during tests or if there's an attempt to get this data from within another service's initialization without awaiting 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. No, I meant that it doesn't look like we're accessing this as a property anywhere—which is good, as leaking the UUID feels like leaking the private state of the analytics service and leaking the implementation detail of using PostHog. 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. Hmmm I'm not following, we need this id to get the wallet's campaign state 🤔 |
||
if (!this.#analyticsUUID) { | ||
throw new Error( | ||
"Attempted to access analytics UUID before service started", | ||
) | ||
} | ||
return this.#analyticsUUID | ||
} | ||
|
||
async sendAnalyticsEvent( | ||
eventName: AnalyticsEvent, | ||
payload?: Record<string, unknown>, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
import browser from "webextension-polyfill" | ||
import { FiatCurrency } from "../../assets" | ||
import { AddressOnNetwork, NameOnNetwork } from "../../accounts" | ||
import { ServiceLifecycleEvents, ServiceCreatorFunction } from "../types" | ||
|
@@ -277,18 +276,10 @@ export default class PreferenceService extends BaseService<Events> { | |
} | ||
|
||
async setShouldShowNotifications(shouldShowNotifications: boolean) { | ||
if (shouldShowNotifications) { | ||
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. I would love to still make it so that this can only set the db state if the permission is actually granted, rather than having it be a blind state updater. i.e., it would be good if we could guard against 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. Hmmm we can verify if permission has indeed been granted and guard that I think |
||
const granted = await browser.permissions.request({ | ||
permissions: ["notifications"], | ||
}) | ||
|
||
await this.db.setShouldShowNotifications(granted) | ||
this.emitter.emit("setNotificationsPermission", granted) | ||
|
||
return granted | ||
} | ||
await this.db.setShouldShowNotifications(shouldShowNotifications) | ||
this.emitter.emit("setNotificationsPermission", shouldShowNotifications) | ||
|
||
return false | ||
return shouldShowNotifications | ||
} | ||
|
||
async getAccountSignerSettings(): Promise<AccountSignerSettings[]> { | ||
|
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.
Lint disable is best accompanied by an explanation.
In this case my thought is that we probably move this into a Mezo or Mezo campaign service, which is where we deal with the Redux service's complexity as well (after we ship this, I mean). Wdyt?
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.
That's a good point, this is only used for the campaign. I initially put this under
/lib
because I thought this would be also used by the enrichment service.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.
For sure. I think once we're enriching we'll probably export more anyway—and I wonder if the better approach here is actually making this file an ABI export file (
background/lib/mezo/musd-trovemanager-abi.ts
or so) and then we implementcheckIsBorrowingTx
directly where we need it and let enrichment do its own things with the ABI.Anyway, none of that is blocking.