-
Notifications
You must be signed in to change notification settings - Fork 28
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
fix: change server #411
fix: change server #411
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## dev #411 +/- ##
========================================
- Coverage 9.41% 9.36% -0.05%
========================================
Files 114 114
Lines 5097 5123 +26
Branches 677 684 +7
========================================
Hits 480 480
- Misses 3975 3994 +19
- Partials 642 649 +7
☔ View full report in Codecov by Sentry. |
|
||
if (networkChanged) { | ||
// need to clean the storage, including registered tokens. | ||
await wallet.storage.cleanStorage(true, true, true); |
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 don't we make the wallet.stop
method above accept a new cleanTokens
param instead of calling the wallet.storage
directly?
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.
Stopping a wallet should not remove registered tokens, this is necessary here because we will be moving to another network where these tokens do not exist and leaving the tokens on the storage would make the wallet screen show tokens that do not exist on the connected network.
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.
My question is not about the logic, I think the logic is great.
It's just that something like this could be better, because it would keep the pattern already in use for the other options:
async changeServer(wallet, pin, routerHistory, networkChanged) {
// We only clean the storage if the network has changed
const options = { cleanStorage: true, cleanAddresses: true };
if (networkChanged) {
options["cleanTokens"] = true;
}
await wallet.stop(options);
This way we don't have to call the wallet.storage
directly, and we keep the option available and documented in the stop method in case anyone needs it as well.
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.
Created this issue to track this change on the wallet-lib HathorNetwork/hathor-wallet-lib#575
src/sagas/wallet.js
Outdated
} else { | ||
console.error(e); | ||
// Return to locked screen when the wallet fails to start | ||
LOCAL_STORE.lock(); | ||
routerHistory.push('/locked/'); |
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.
Sometimes the wallet would be stuck on loading addresses, the error I got was that the configured network and server network did not match, it was raised during the start, but we already have a try..catch
it just didn't handle the error, so the sagas would be waiting on a wallet that was not started.
The solution here is just to go back in the locked screen, but we can also add an error message in the future.
The reason I was having this error was because the change server error this PR solves would change the server but did not change the network so I do not expect to have this error again but i'm leaving this to make debugging future errors of this nature easier.
for (const output of data.tx.outputs) { | ||
if (!output.token) { | ||
if (output.token_data === 0) { | ||
output.token = hathorLib.constants.HATHOR_TOKEN_CONFIG.uid; | ||
} else { | ||
output.token = data.tx.tokens[(output.token_data & hathorLib.constants.TOKEN_INDEX_MASK) -1].uid; | ||
} | ||
} | ||
} | ||
|
||
for (const input of data.tx.inputs) { | ||
if (!input.token) { | ||
if (input.token_data === 0) { | ||
input.token = hathorLib.constants.HATHOR_TOKEN_CONFIG.uid; | ||
} else { | ||
input.token = data.tx.tokens[(input.token_data & hathorLib.constants.TOKEN_INDEX_MASK) -1].uid; | ||
} | ||
} | ||
} |
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.
getFullTxById
fetches the transaction from the api, which uses has a slightly different structure from the websocket transactions and transactions received via history sync.
These lines just add the token
uid where the helper will need it.
The issue here was that not having the token
would make the transaction balance think that there was only a single token of uid undefined
.
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 not sure I get this: would we have some problem if we implemented this in the lib itself, so the getFullTxById
method always returns with the right token?
I mean, when using this method in other wallets, won't they need to perform a similar treatment to this response?
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 absolutely right, the only other place this is used is on the decode api of the headless and when it is used the token would be missing. I created a PR to fix this on the headless HathorNetwork/hathor-wallet-headless#342
The main problem in my opinion is that the same transaction can have multiple structures depending on which api is used to fetch it from the fullnode or if it comes from the websocket.
Maybe the best solution would be to normalize the transaction model sent by the fullnode and the wallet-lib would be more stable.
Since solving this on the wallets is the simpler approach I think we should stick with it for now.
What do you think?
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 think it's ok to stick to the simpler approach. But we should have an issue to implement the best solution in the future.
@@ -94,6 +94,25 @@ class TransactionDetail extends React.Component { | |||
|
|||
try { | |||
const data = await this.props.wallet.getFullTxById(this.props.match.params.id); | |||
for (const output of data.tx.outputs) { |
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 we have unit tests for this?
As a suggestion, it might be a good idea to avoid adding too much business logic here so we have a clearer separation between presentation layer components and business logic (something like https://blog.bitsrc.io/improve-react-component-maintainability-with-layered-architecture-25e74ba86430)
It could also facilitate unit tests for the business logic, since by putting it here you would have to mount the component and all its dependencies in order to test this logic.
Does it make sense?
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.
Maybe, this only affects the UI, but it is a pretty important piece of UI on the transaction data.
But I don't think it's in the scope of this PR, since we should think of how to structure the UI and business logic tests with electron.
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 ok for me. But if you think this is important, we should create an issue or KTLO, so we don't forget.
Acceptance Criteria
Security Checklist