-
Notifications
You must be signed in to change notification settings - Fork 489
Support symbolic amount/bid=everything which spends all funds from selected account/wallets. #3605
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: master
Are you sure you want to change the base?
Conversation
|
OK, so I've learned about GitHub actions & workflows, and I'm running that to do testing server-side on the forked repository. |
|
@moodyjon Thanks for the PR, let me know when you are ready to have it reviewed. In the meantime I do have a preliminary comment: the |
|
Getting a message in the Actions tab for moodyjon/lbry-sdk repository:
Have filed a ticket for it: I'm afraid they believe I'm mining LBC on GitHub servers. Or something like that. In the meantime, I found scripts/generate_gson_api.py and docs/api.json to be illuminating... though I was not able to run the script locally. I will post a change moving from --bid=everything (str/decimal) to --bid_everything (bool). |
|
In my environment (MacOS arm64) I have had partial success running integration tests and success running generate_json_api.py. Ready for review. No response on ticket: https://support.github.com/ticket/personal/0/1603371 |
|
GitHub support ticket was resolved, and I can run tests server-side again. |
|
@moodyjon thanks for continuing to work on this, can you rebase on latest master, there were some fixes related to running tests that will improve your test runs |
|
@eukreign Do you have your own test runners or are you using plain GitHub runners? Reason I ask is I sometimes get odd timeout or off-by-one errors using the free GitHub runners. |
06ef00e to
dd0ed39
Compare
|
Review ping to @eukreign or others. |
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.
Thanks for putting a lot of effort into this PR.
I'm struggling with a clean way to handle the --everything case without compromising the existing functionality... what about this:
Leave the requirement for amount as positional argument, this is the case currently. Then have the user enter 0 as the amount followed by the --everything flag to achieve the spending of all UTXOs. Since spending --everything is a significant operation, perhaps requiring an extra step of both amount=0 and --everything is not too bad. (Kind of like on github when you delete something important they ask you to enter a string into a text box.) This also solves the issue of not removing the positional argument.
Internally, instead of having two separate values passed around I think it's safe to convert a combination of amount=0 everything=True coming from API into amount=EVERYTHING (with EVERYTHING="EVERYTHING"). Passing amount=0 without --everything should still be an input error.
I could also be convinced to leave amount=0 internally but my hesitation with that is in case some code internally accidentally passes amount=0 due to some other computation without intending to spend everything (expecting nothing to be spent). By making it a string it reduces any inadvertent computation of amount variable without a if amount == EVERYTHING check (since things will break when doing math with strings thus preventing unintended/unguarded spends). Although another option for this particular case is to use -1 as --everything... on the other hand, one other advantage using "EVERYTHING" as a string is that in cases where an unrelated error message is printed but if it includes amount=EVERYTHING as part of the error output it will actually make sense to the user because that is what they intended.
In summary,
API
- Leave existing API for positional amounts argument unchanged.
- In
--everythingdoc state that user must specify0for the amount. - Require user to enter
0for amount following by--everythingwhen they want to spend everything and check this indaemon.py. - For consistency, all of the
--everythingflags should be the same for all of the commands for which anamountis defined (instead of the--everything,--amount_everything,--bid_everything, etc)
Internally
- Convert the user input of
amount=0 everything=Trueintoamount=EVERYTHING(you can defineEVERYTHING="EVERYTHING"inwallet/constants.py) to reduce number of arguments being passed around everywhere.
What do you think?
…arg. (Derived from 33bdb50 but without test code.)
…hing). Make bid and amount args optional as well as args following them. Fold agrument checks into get_dewies_or_error().
…in daemon.py. Unpack the generic amount in transaction.py and account.py. Eliminate separate "everything" keyword args.
eukreign
left a comment
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 getting closer but it's a big PR and would be great if anything extraneous could be moved into a separate PR and then to just limit the number of changed lines in this one to make it easier to review. See a bunch of inline comments below.
| Usage: | ||
| wallet_send <amount> <addresses>... [--wallet_id=<wallet_id>] [--preview] | ||
| wallet_send (<amount> | --amount=<amount> | --amount_everything) <addresses>... |
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 don't think you can have an optional followed by a required field. When calling wallet_send here it's not clear if the first value passed to the command would be an <amount> or an <address>.
| Options: | ||
| --amount=<amount> : (decimal) the amount to transfer lbc | ||
| --amount_everything : (bool) send everything from funding accounts (excluding claims), |
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.
Can this just be --everything?
lbry/wallet/transaction.py
Outdated
| all_utxos = [] | ||
| for acct in funding_accounts: | ||
| # TODO: Constraints for get_utxos()? | ||
| utxos = await acct.get_utxos() |
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.
UTXOs will include claims
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.
On the jsonrpc_account_fund() code path, it seems the only extraneous arg which could be interpreted as a constraint is from_account=None. Will investigate this...
Possibly this imposes a constraint to exclude claims?
lbry-sdk/lbry/wallet/ledger.py
Line 958 in dc427ec
| def constraint_spending_utxos(constraints): |
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.
TXO_TYPES = {
"other": 0,
"stream": 1,
"channel": 2,
"support": 3,
"purchase": 4,
"collection": 5,
"repost": 6,
}
def constraint_spending_utxos(constraints):
constraints['txo_type__in'] = (0, TXO_TYPES['purchase'])
More context:
7d333ef
I take it "other" is a generic txo carrying an amount of LBC created by wallet_send, and "purchase" is a purchase receipt txo created by purchase_create. It is unclear there is any non-zero amount associated with a purchase receipt txo. Is this correct?
The intention of the original bug was to send only "other" funds, NOT purchase receipts (and NOT the claim types as you say). Transferring both "other" and "purchase" inside jsonrpc_account_fund() kind of makes sense because in that context both from/to accounts are in the same wallet.
I will work to exclude "purchase" txos from funds transferred by support_create, channel_create, stream_create, etc.
|
|
||
| @staticmethod | ||
| def _old_get_temp_claim_info(tx, txo, address, claim_dict, name, bid): | ||
| def _old_get_temp_claim_info(tx, txo, address, claim_dict, name): |
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.
Can you do this change as a separate PR? It seems somewhat unrelated to this one and this PR is already large and complicated.
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.
Will do this next. I think the amount_to_dewies() and get_amount_or_error() stuff could also be unbundled. Then the function signatures and docstrings.
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.
Pull request: #3635
| from .util import coins_to_satoshis, satoshis_to_coins | ||
|
|
||
| # Symbolic amount EVERYTHING | ||
| AMOUNT_EVERYTHING = "EVERYTHING" |
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.
All caps variable already means this is a constant, doesn't need a comment above it saying the same.
| await self.assertBalance(self.account, '0.0') | ||
| self.assertEqual(len(tx['outputs']), 1) # no change | ||
| self.assertEqual(tx['outputs'][0]['amount'], '9.991457') | ||
| self.assertItemCount(await self.daemon.jsonrpc_channel_list(), 1) |
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.
Can you move this to the end of the test, this way you don't have to change the values of the other asserts.
…ludes purchase receipts.
|
Demote to draft status as I plan to unbundle some changes in subsidiary PRs. |
|
some of the unbundled PRs have been merged |
Fixes: #1628
I know this is lacking in tests for the higher-level functionality like Transaction.pay(), claim_create(), claim_update(), support(). I'm most concerned about claim_update().
However, I haven't been able to get integration tests to run in my environment (MacOS 12.3.1 arm64) and integration testing seems to be the way to work with claims and more complex wallet contents.
I've gone through multiple rounds installing the pieces (scribe, hub, ...) in different ways, but have not been able to get it fully working. Part of the problem is MacOS arm64 does not have a broad selection of pre-built packages at older versions. Part of it is I think I'm still missing pieces of the integration testing environment.
Can someone advise me how to get all the pieces in place for integration testing on my machine or run the integration tests in a supported environment and report back?