Skip to content
This repository has been archived by the owner on Nov 10, 2023. It is now read-only.

Enhancement: cache owned Safes in localStorage #3066

Merged
merged 6 commits into from
Dec 2, 2021
Merged

Enhancement: cache owned Safes in localStorage #3066

merged 6 commits into from
Dec 2, 2021

Conversation

katspaugh
Copy link
Member

What it solves

Owned safes on other networks are gone when you refresh the page.

How this PR fixes it

Keeps them in localStorage.

I've added a wrapper around localStorage that does that. Plus a hook.

How to test it

  • Open the sidebar, switch between networks.
  • Refresh the page
  • Owned safes on all networks should be still in the sidebar

@github-actions
Copy link

CLA Assistant Lite All Contributors have signed the CLA.

@katspaugh katspaugh added the Enhancement ✨ Minor Improvement / changes to existing functionality label Nov 26, 2021
@github-actions
Copy link

github-actions bot commented Nov 26, 2021

ESLint Summary View Full Report

Annotations are provided inline on the Files Changed tab. You can also see all annotations that were generated on the annotations page.

Type Occurrences Fixable
Errors 0 0
Warnings 0 0
Ignored 3 N/A
  • Result: ✅ success
  • Annotations: 0 total

Report generated by eslint-plus-action

@coveralls
Copy link

coveralls commented Nov 26, 2021

Pull Request Test Coverage Report for Build 1526576110

  • 33 of 50 (66.0%) changed or added relevant lines in 8 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.01%) to 32.751%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/utils/storage/index.ts 6 8 75.0%
src/utils/storage/Storage.ts 22 25 88.0%
src/logic/safe/hooks/useOwnerSafes.ts 0 4 0.0%
src/utils/storage/useStoredState.ts 0 8 0.0%
Totals Coverage Status
Change from base Build 1526428491: -0.01%
Covered Lines: 3110
Relevant Lines: 8463

💛 - Coveralls

Copy link
Member

@iamacook iamacook left a comment

Choose a reason for hiding this comment

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

Looking good! I think there is some duplicate logic of what we already have though.

@@ -0,0 +1,31 @@
import { getItem, setItem } from '../local'
Copy link
Member

@iamacook iamacook Nov 26, 2021

Choose a reason for hiding this comment

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

I'm surprised this passes. Normally I have to mock the localStorage.

Copy link
Member Author

Choose a reason for hiding this comment

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

Somehow it's already mocked.

@@ -0,0 +1,20 @@
const PREFIX = 'SAFE__'

const prefixKey = (key: string): string => `${PREFIX}${key}`
Copy link
Member

Choose a reason for hiding this comment

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

We already have a function for getting the prefix?

Copy link
Member Author

Choose a reason for hiding this comment

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

Can you point me to it?

Copy link
Member

Choose a reason for hiding this comment

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

getStoragePrefix() at src/utils/storage/index.ts

Copy link
Member Author

Choose a reason for hiding this comment

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

That one is for immortal.

Copy link
Member

Choose a reason for hiding this comment

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

Do we want to follow a versioning convention though, just in case we make any drastic changes?

Copy link
Member Author

Choose a reason for hiding this comment

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

We'll have to live with two keys for now: the legacy immortal ones and the new SAFE ones.
The first ones, we'll need to eventually migrate (not a high prio I think).

As for versioning, We can always slap a version on top of the new key, e.g. SAFE_v2. Once there's a need.


const prefixKey = (key: string): string => `${PREFIX}${key}`

export const getItem = <T>(key: string): T | undefined => {
Copy link
Member

Choose a reason for hiding this comment

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

Why are you not using the functions we already have for storage interaction?

Copy link
Member Author

Choose a reason for hiding this comment

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

Which ones?

Copy link
Member

Choose a reason for hiding this comment

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

loadFromStorage() and saveToStorage() at src/utils/storage/index.ts

Copy link
Member

Choose a reason for hiding this comment

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

I created some for the sessionStorage at src/utils/storage/session.ts that don't rely on ImmortalDB. They might be of help.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll merge session and local, they share 99% of the code.

@github-actions
Copy link

Deployment links

🟠 Safe Rinkeby Safe Mainnet 🟣 Safe Polygon 🟡 Safe BSC Safe Arbitrum 🟢 Safe xDai

@github-actions
Copy link

github-actions bot commented Nov 26, 2021

E2E Tests Failed
Check the results here: https://github.com/gnosis/safe-react-e2e-tests/actions/runs/1526621355

Failed tests:

  • ❌ Address book Address book
  • ❌ Safe Apps List Safe Apps List
  • ❌ Read-only transaction creation and review Create and review a Send Funds transaction

Copy link
Member

@iamacook iamacook left a comment

Choose a reason for hiding this comment

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

Looking good. Just a few things

@@ -43,7 +43,7 @@ const isNetworkId = (id: unknown): id is ETHEREUM_NETWORK => {
return Object.values(ETHEREUM_NETWORK).some((network) => network === id)
}

export const NETWORK_ID_KEY = 'SAFE__networkId'
export const NETWORK_ID_KEY = 'networkId'
Copy link
Member

Choose a reason for hiding this comment

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

In the chains migration, I am trying to move all networkId references to chainId. Do you think it's worthwhile including this here too?

Copy link
Member Author

Choose a reason for hiding this comment

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

Out of scope, I'm just removing the prefix here.

@@ -30,9 +30,6 @@ enum ErrorCodes {
_701 = '701: Failed to save a localStorage item',
_702 = '702: Failed to remove a localStorage item',
_703 = '703: Error migrating localStorage',
_704 = '704: Failed to load a sessionStorage item',
Copy link
Member

Choose a reason for hiding this comment

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

Why have you removed these? The /load and /open routes use the sessionStorage to retrieve the current chainId.

Copy link
Member Author

@katspaugh katspaugh Nov 29, 2021

Choose a reason for hiding this comment

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

I know but there's little value in having two sets of error messages depending on which storage this is. Besides, we're not even tracking them. I can change localStorage -> storage.

Copy link
Member

Choose a reason for hiding this comment

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

Alright, I would suggest generalising 701-703 then.

}
}

return data as unknown as T | undefined
Copy link
Member

Choose a reason for hiding this comment

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

Why not just return on line 32/35? You won't need to cast to both types, only line 32 to T.

// We need this to update on run time depending on selected network name
export const getStoragePrefix = (networkName = getNetworkName()): string => `v2_${networkName}`
// We need this to update the key in runtime depending on selected network name
export const getStoragePrefix = (networkName = getNetworkName()): string => `_immortal|v2_${networkName}__`

export const loadFromStorage = async <T = unknown>(
Copy link
Member

Choose a reason for hiding this comment

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

Need this still be async?

Copy link
Member Author

Choose a reason for hiding this comment

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

The code that uses it still expects a promise.

Copy link
Member

Choose a reason for hiding this comment

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

Do you not think it's worthwhile changing it? Or create a new issue to do that?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we should eventually un-async all that code. 👍
Created #3073

import { useState, useEffect } from 'react'
import local from './local'

const useStoredState = <T>(key: string): [T | undefined, React.Dispatch<React.SetStateAction<T>>] => {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe this should be name something like useLocalState just to be clear that it isn't involving the sessionStorage.

Copy link
Member Author

Choose a reason for hiding this comment

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

"Local" state, to me, doesn't imply that it's stored in a permanent place. I would keep this name.

@francovenica
Copy link
Contributor

Looks good to me.
Still a mystery were you actually save them, I've checked the local storage and I was expecting to find the almost 700 safes I have with one of my owners in rinkeby :D

Checked:
The owned safes are remembered while switching networks. The list remains there is accessible and they don't have to load every time you switch networks
They have to be refreshed if you switch owners ( you have to visit every network again) which is ok.
If you disconnect the "owner safes" dropdown disappears which is correct as well.

image

@katspaugh
Copy link
Member Author

@francovenica thanks! They are stored under SAFE__ownedSafes.

@katspaugh katspaugh merged commit 134c787 into dev Dec 2, 2021
@katspaugh katspaugh deleted the cache-owned branch December 2, 2021 08:53
@github-actions github-actions bot locked and limited conversation to collaborators Dec 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Enhancement ✨ Minor Improvement / changes to existing functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants