-
Notifications
You must be signed in to change notification settings - Fork 9
[wallet/common] feat: create core project #1473
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
base: dev
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## dev #1473 +/- ##
==========================================
- Coverage 98.26% 98.22% -0.05%
==========================================
Files 163 157 -6
Lines 6691 6477 -214
Branches 143 143
==========================================
- Hits 6575 6362 -213
+ Misses 116 115 -1
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
2aa31ee
to
3720484
Compare
… fix incorrect types, add missing method to ProtocolApi class
@cryptoBeliever thanks, new changes pushed! |
@@ -0,0 +1,19 @@ | |||
{ | |||
"name": "@wallet/common-core", | |||
"main": "./src/index.js", |
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.
Does the package need a version? How do the other components comsume this module?
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.
I'm thinking of using it as a local package, e.g.:
{
"dependencies": {
"@wallet/common-core": "file:../../common/core"
}
}
Does the package need a version?
I will add the version.
"devDependencies": { | ||
"c8": "~10.1.2", | ||
"eslint": "~8.57.0", | ||
"eslint-config-airbnb": "~19.0.4", |
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.
eslint-config-airbnb
has not been updated to support ESLint 9. We may need to replace it if it is not updated. Don't need to change now, but just making a note.
constructor(code, message) { | ||
super(message); | ||
this.name = this.constructor.name; | ||
this.code = code; |
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.
Should the code
be included in the toString()?
/** @typedef {import('../types/Transaction').SignedTransactionDTO} SignedTransactionDTO */ | ||
|
||
/** | ||
* @callback FetchAccountInfoFn |
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.
should this be FetchAccountInfoCallback
?
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 function does not truly represent a callback function. It wasn't clear until I saw the code. For JavaScript, any function parameter is considered a callback. 😅
This is the Strategy pattern, where you allow different implementations? Is this support for NEM and Symbol only?
[wallet-common-core-lint]: https://jenkins.symbolsyndicate.us/buildStatus/icon?job=Symbol%2Fgenerated%2Fproduct%2Fwallet-common-core%2Fdev%2F&config=wallet-common-core-lint | ||
[wallet-common-core-test]: https://jenkins.symbolsyndicate.us/buildStatus/icon?job=Symbol%2Fgenerated%2Fproduct%2Fwallet-common-core%2Fdev%2F&config=wallet-common-core-test | ||
[wallet-common-core-cov]: https://codecov.io/gh/symbol/product/branch/dev/graph/badge.svg?token=SSYYBMK0M7&flag=wallet-common-core | ||
[wallet-common-core-cov-link]: https://codecov.io/gh/symbol/product/tree/dev/tools/vanity |
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.
tools/vanity => wallet/common/core?
*/ | ||
clear = async () => { | ||
await Promise.all(Object.values(PersistentStorageRepository.STORAGE_KEYS).map(key => this.storage.removeItem(key))); | ||
}; |
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.
Would this.storage.clear()
work better instead of removing each item, since I am assuming localStorage is used?
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.
If not, you might want to check if the storage is empty
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.
We only want to remove the keys that are managed by this repository. Since the same storage may be shared across multiple repositories, it's important to ensure that only data related to the current repository is cleared.
localStorage is used by the browser extension wallet and mobile wallets use an API for device storage and encrypted storage.
If not, you might want to check if the storage is empty
Removing a non-existent value from localStorage doesn’t throw an error, so checking whether a value exists beforehand is unnecessary in this case. If other storage implementations behave differently and throw an error, such checks should be handled inside the StorageInterface, IMO.
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.
Ok. That makes sense.
across multiple repositories
What do you mean by multiple repositories? Is it when multiple users use the wallet on the same device?
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.
We have two separate repositories: PersistentStorageRepository for storing WalletController-related data (like public account info), and SecureStorageRepository for storing sensitive encrypted data (such as private keys). Both repositories rely on a shared StorageInterface, which provides methods like set, get, and remove.
In the mobile wallet, these repositories use different StorageInterface implementations (AsyncStorage and EncryptedStorage). However, in the browser extension wallet, both repositories use the same underlying storage - LocalStorage. As a result, calling localStorage.clear() from PersistentStorageRepository would clear data managed by SecureStorageRepository as well. This is why I avoid using .clear() and instead remove only the relevant keys tied to each repository.
|
||
packageId = 'wallet-common-core' | ||
|
||
codeCoverageTool = 'c8' |
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.
Did you want to set the minimumCodeCoverage
?
|
||
/** | ||
* @callback SignTransactionFn | ||
* @param {NetworkProperties} networkProperties - The network properties. |
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.
Is the networkProperties needed to get the generationHashSeed for tx signing?
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.
In Symbol implementation we use networkIdentifier
to create SymbolFasade('testnet' | 'mainnet')
, networkCurrency.divisibility
for fee
and epochAdjustment
for deadline
.
Looks like generationHashSeed
is not used.
|
||
/** | ||
* @callback CosignTransactionFn | ||
* @param {NetworkProperties} networkProperties - The network properties. |
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.
Why is the networkProperties needed here?
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.
You are right, networkProperties
doesn't needed here. We don't need to create instance of SymbolFacade
since cosignTransactionHash
is a static method.
Problem:
We didn't yet have a shared, reusable, protocol-agnostic core library for managing wallets, accounts, signing, storage, and network connections across different wallet apps (mobile, desktop, browser extension).
Each app would have to implement its own controller, storage abstraction, keystore logic, and protocol integration, leading to duplicated effort, inconsistent APIs, and maintenance overhead.
Solution:
This PR creates the new Wallet Common Core project, providing:
WalletController
)- Abstracted storage interface
This project/package can be consumed by any wallet app <NEM|Symbol><Desktop|Mobile|Extension>Wallet to handle core wallet functionality.