-
Notifications
You must be signed in to change notification settings - Fork 482
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
Support symbolic amount/bid=everything which spends all funds from selected account/wallets. #3605
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
--everything
doc state that user must specify0
for the amount. - Require user to enter
0
for amount following by--everything
when they want to spend everything and check this indaemon.py
. - For consistency, all of the
--everything
flags should be the same for all of the commands for which anamount
is defined (instead of the--everything
,--amount_everything
,--bid_everything
, etc)
Internally
- Convert the user input of
amount=0 everything=True
intoamount=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.
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.
""" | ||
Send the same number of credits to multiple addresses using all accounts in wallet to | ||
fund the transaction and the default account to receive any change. | ||
|
||
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>
.
[--change_account_id=None] [--funding_account_ids=<funding_account_ids>...] | ||
[--blocking] | ||
|
||
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.
@@ -5470,11 +5509,11 @@ async def resolve(self, accounts, urls, **kwargs): | |||
return results | |||
|
|||
@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?