Skip to content
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

Bugfix/tx history restore bump #945

Merged
merged 11 commits into from
Aug 18, 2023

Conversation

aristidesstaffieri
Copy link
Contributor

Ticket: https://stellarorg.atlassian.net/browse/WAL-1008

This adds handling for the bump or restore operations that are new in Soroban with preview 10.
Previously we assumed that any Soroban related transactions would be accounted for in our OPERATION_TYPES enum, and this was ok because we controlled what contracts we supported(just token basically).

P10 introduced state expiry which means that now any user may have restored or bumped state through a transaction which broke this model.

This is fixed in 2 ways -

  1. We add the OPERATION_TYPES key for bump and restore ops.
  2. We no longer assume anything about unknown op types and render them as generic host invoke functions.

Unrelated bug fix -
I found that the mint token history item was flawed because it assumed the the minter already had some of the token, and the token ID saved in their tokenIds list. It also didn't account for the mint to be to the current wallet, so it didn't properly show a change in balance.
This is fixed by attempting to fetch token details when the mint operation is for a token that we do not have in our tokenIds list, and accounting for a change in balance when the mint is to the current public key.

This also includes refactors/re-organization of Soroban related helpers/tooling.

moved helpers to the shared namespace.
added server helper for simTx.
added specific token helpers and refactored to use new simTx helper.
removed helpers that could be replaced by ones in soroban-client.

Unresolved Issues -
Working on this uncovered interesting UX fallout from now potentially dealing with tokens where the state or code can be expired. For either account details or account history, we could run into a scenario where the contract has an expired entry and then we fail to fetch token details through a transaction simualtion, we can do a few things -

If the contract is a SAC, we can get this info from Horizon and we should anyway because it's free.
Quote from Dima about knowing when a contract is a SAC -

that's a good question. I'm not sure how SAC tokens should be added. they can be added either via classic Asset or via contract id. in the latter case you can easily figure out that it's SAC (just lookup executable in the contract instance entry), and then I believe you can get Asset spec from the token name (it's ASSET_NAME:ISSUER_KEY)

We could also index Soroban to always have up to date data about every token contract that we care about, quote from Tomer on that

Using SAC optimizations is an ok temporary fix. With that said I think we should take a step back and acknowledge that soroban-rpc is actually a poor wallet backend. and that’s ok - that’s not what it was built for. So obviously we can tackle building a wallet backend, though that might be a lot of work. We can see if we can utilize the work of someone else in the ecosystem. maybe stellar.expert (I suspect orbit will have something like this ready) or one of the incoming indexers. Or, we can potentially solve some of these issues by having more robust client-side state management

There is also the option to fetch the ledger entry directly, but I am still gathering details about it and don't yet understand how that would be different from the RPC getting it.

@@ -80,7 +84,8 @@ export const HistoryItem = ({
sourceAssetCode = operation.source_asset_code;
}
const operationType = camelCase(type) as keyof typeof OPERATION_TYPES;
const operationString = `${OPERATION_TYPES[operationType]}${
const opTypeStr = OPERATION_TYPES[operationType] || t("Transaction");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was basically the source of the bug

</>
);
IconComponent = <Icon.ArrowUp className="HistoryItem__icon--sent" />;
React.useEffect(() => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I needed to make this async to better handle the mint token case, explained in the PR description.

const decimals = await getDecimals(contractId, server, txBuilders.decimals);
const name = await getName(contractId, server, txBuilders.name);
const symbol = await getSymbol(contractId, server, txBuilders.symbol);
const balance = await getBalance(
Copy link
Contributor

Choose a reason for hiding this comment

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

nice - I find this pattern a lot more straightforward!

try {
// handle a case where scValToNative doesn't properly handle scvString
convertedScVal = scVal.str().toString();
return convertedScVal;
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I believe this should be fixed now in the last soroban-client. So I don't think you need to handle this scvString case

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh yeah I did hear that also, I'll test it out to make sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in 1ba0450

.build();

const result = await simulateTx<string>(tx, server);
return result;
Copy link
Contributor

Choose a reason for hiding this comment

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

no need to do this now since things could still change - but if this API holds, in the future we could probably refactor these helpers to share some logic as they're all kinda doing the same thing.

Also, @Shaptic - do we consider this a common enough use case (getting balance + decimals + name + symbol) that soroban-client should offer this?

Copy link
Contributor Author

@aristidesstaffieri aristidesstaffieri Aug 17, 2023

Choose a reason for hiding this comment

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

Additionally - there's also a good convo happening about how we should be fetching data for Soroban now that expired state can be involved. It seems like we'll have to at least augment our approach anyway pretty soon. Some good ideas that came up includes -

  1. Caching things like decimals/name/symbol when a user firsts gets a balance of a token.
  2. Fetching the ledger entries directly(this is cheaper than the rpc call).
  3. Getting these details from Horizon when token is a SAC.
  4. Allowing users to restore their data when their token data is expired(implies we start storing expiration time along with other details).

Copy link

Choose a reason for hiding this comment

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

I don't think this belongs in soroban-client, per se, but maybe this be handled by using soroban-cli to generate the TypeScript bindings for the SAC? cc @chadoh @willemneal

const token = tokenBalances.find(
(balance) => attrs && balance.contractId === attrs.contractId,
);
const [txDetails, setTxDetails] = React.useState(transactionDetailPropsBase);
Copy link
Contributor

Choose a reason for hiding this comment

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

Super NIT: but in other files in the repo, we usually just import { useState } from "react" at the top of the file so we just call useState directly instead of calling React.useState. So minor, but would be good to keep the pattern consistent

Copy link
Contributor

Choose a reason for hiding this comment

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

Same deal with useEffect

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah whoops, yup will update.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in 1ba0450

@@ -28,6 +28,7 @@ export enum OPERATION_TYPES {
revokeTrustlineSponsorship = "Revoke Trustline Sponsorship",
setOptions = "Set Options",
setTrustLineFlags = "Set Trustline Flags",
bumpFootprintExpiration = "Bump Footprint Expiration",
Copy link

Choose a reason for hiding this comment

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

missing restoreFootprint?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes it is, thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in 05fa8fe

@@ -9,9 +9,11 @@ import {

import { settingsNetworkDetailsSelector } from "./ducks/settings";

const BASE_FEE = "100";
Copy link

Choose a reason for hiding this comment

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

you should use SorobanClient.BASE_FEE, I think

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks, I keep meaning to update that. Done in 05fa8fe

const params = [
new SorobanClient.Address(publicKey).toScVal(), // from
new SorobanClient.Address(destination).toScVal(), // to
SorobanClient.nativeToScVal(parsedAmount.toNumber(), { type: "i128" }), // amount
Copy link

Choose a reason for hiding this comment

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

new SorobanClient.XdrLargeInt('i128', parsedAmount).toScVal() may be faster/more direct, I think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in 05fa8fe

@socket-security
Copy link

Updated dependencies detected. Learn more about Socket for GitHub ↗︎

Packages Version New capabilities Transitives Size Publisher
soroban-client 0.9.1...0.9.2 None +3/-3 11.2 MB stellar-npm-ci

@aristidesstaffieri aristidesstaffieri changed the base branch from master to release/5.5.0 August 18, 2023 17:29
@aristidesstaffieri
Copy link
Contributor Author

New Entries look like this, also improved mint & transfer a bit.

Screenshot 2023-08-18 at 11 30 30 AM

@aristidesstaffieri aristidesstaffieri merged commit e756283 into release/5.5.0 Aug 18, 2023
6 checks passed
@aristidesstaffieri aristidesstaffieri deleted the bugfix/tx-history-restore-bump branch August 18, 2023 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants