-
Notifications
You must be signed in to change notification settings - Fork 215
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
feat: more usable bidding CLI: integrated sign/broadcast #7256
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #7256 +/- ##
==========================================
+ Coverage 66.17% 66.19% +0.01%
==========================================
Files 312 313 +1
Lines 60018 60127 +109
Branches 3 3
==========================================
+ Hits 39718 39799 +81
- Misses 20232 20262 +30
+ Partials 68 66 -2
|
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.
Good stuff! Approving with assumption that the AGORIC_KEYRING_BACKEND
will get into the CLI help as suggested.
@@ -184,6 +186,9 @@ For example: | |||
.command('bid') | |||
.description('auction bidding commands'); | |||
|
|||
const sendHint = |
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 you don't opt for outputActionAndHint
at least put this const in lib/wallet. it's about wallet actions.
Currency: mk(bslot.IST, 50000000n), | ||
}, | ||
give: { Currency: mk(bslot.IST, 50_000_000n) }, | ||
want: { Collateral: mk(bslot.ATOM, 5_000_000n) }, |
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.
what happens if this doesn't match the want
in offerArgs?
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.
Good question... @Chris-Hibbert ?
I'd love to see contract unit tests in this area.
I considered adding one but figured maybe I have already spent too much time on this bidding CLI and I should check with some reviewers about how much testing and of what sort is cost-effective 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.
It's completely legal for the want
in the proposal to be different. The effect is that it specifies a minimum fill for the order. If we think people will want that functionality, we could add support for the auction contract to pay attention. Actually the auction wouldn't do anything different. If it couldn't completely satisfy the want
, it would exit the seat.
Currently it just allows Zoe to kill offers when the auction tries to reallocate less than the requested amount. Most of the time, if the want
is reasonable, the auction will be likely to surpass it.
collateralBrand, | ||
scaleDecimals(opts.wantCollateral), | ||
); | ||
|
||
const proposal = { | ||
give, | ||
...('price' in opts ? { want: { Collateral: wantAmt } } : {}), |
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 want
shouldn't be added to the proposal by default. It turns the bid into an all-or-nothing offer. If the auction tries to partially satisfy the offer, zoe will abort the transaction as not-offer-safe.
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.
Help me understand how the contract works in this respect?
Do you have a suggestion on what the CLI should look like?
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.
Help me understand how the contract works in this respect?
The auction has a pool of assets it's trying to sell. There are (hopefully) many buyers who have requested different amounts at varying price levels. The auctioneer serves requested buyers one at a time when their specified price is at or above the current price level. Each offer specifies a maximum amount of money to spend, and a maximum price at which to buy. When the auctioneer looks at one particular offer to buy, it may be able to satisfy it in full (use up all the available spend), or it may only have enough remaining assets to partially satisfy the offer.
The want
in the proposal
is orthogonal to the amount to spend specified by the offer, and is enforced by Zoe. The auction attempts to transfer to the offer as much of the available assets as it can afford. Since we want to support large outstanding orders that buy assets over time, the normal case is that partially filled orders remain in the book for the next auction. I have a PR in prep that allows offers to be exited immediately on partial fulfillment.
If an offer specifies a want
to Zoe, then Zoe will void the transaction if it doesn't give the offer everything it asked for. The contract could proactively look at the want
, but the only thing it would be able to do at that point would be to exit the offer early. It has no facility for hanging onto offers that are above the current auction price in order to use them in a future auction. Instead it wants to go on to the next offer and accept it instead.
IRL, an analogous order on stock markets is fill or kill, which must be filled in its entirety or removed from the book.
I hope I'm not over-explaining. Did I at least clarify what you were looking for?
Do you have a suggestion on what the CLI should look like?
I imagine a flag like --addWant <amount>
, which would have doc comments explaining that it disallows partial execution. But I'm not very familiar with the style of parameters currently in use. I'd be happy to discuss patterns of use that make sense to you.
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.
The re-use of want
from offer safety for the offerArg is a source of confusion. We also need them to be named differently in order for the CLI to take both arguments.
Zoe's want
can't be changed but the offerArg can. How about something like maxSpend
?
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 there something in the contract that suggested the use of want
for this in the CLI? I thought the contract's terminology around this was bidScaling
and price
.
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 there something in the contract that suggested the use of
want
for this in the CLI? I thought the contract's terminology around this wasbidScaling
andprice
.
want: M.or({ Collateral: AmountShape }, {}), |
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.
oops... rather:
{ want: collateralAmountShape }, |
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.
Sorry, Dan. You're right. The contract specifies that. (oops)
The replacement for want
in the offerArgs would be something more like targetPurchase
or desiredBuy
. I agree that want
is bad here. What should we change it to?
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.
desiredBuy
is closer to the style of give
/want
while being distinct enough. also "desired" makes clear that it's not a guarantee the way want
is.
I suppose this is a flake:
|
Darn. Have you seen it flake in master or just this PR? Maybe it's due to the offer safety constraint added in |
@@ -266,33 +388,68 @@ For example: | |||
|
|||
bidCmd | |||
.command('cancel') | |||
.description('Print a request to exit a bid offer') | |||
.description('Exit a bid offer') |
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 no "exit" operation, only "try exit", which may fail
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 wonder how I check whether it failed.
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.
Oh, that's a good one. tryExit()
is async and returns nothing. You can call E(seat).hasExited()
, and it will promptly return a boolean as to whether it has finished exiting. You can use E(seat).getExitSubscriber()
to be notified when it exits. But there's nothing that tells you whether tryExit()
succeeded.
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.
And for it to be useful from a CLI (or any other off-chain client), it has to be visible via chainStorage/RPC.
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.
tryExit() is async and returns nothing.
I'm wrong again.
It does return a promise for the result of the attempt to exit.
Based on alpha testing yesterday and today, I started expanding the scope of this branch substantially. I wonder if I should expand the scope of this PR or close it. I think I incorporated all the comments. I suppose I should land just this scope, but that would be extra work. hm. |
6882ea3
to
4c6a90e
Compare
␊ | ||
Options:␊ | ||
--from <address> wallet address literal or name␊ | ||
--generate-only print wallet action only␊ | ||
-h, --help display help for command` | ||
|
||
## Usage: inter reserve add |
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 noticed we already have a commands/reserve.js
. There's no particular reason to treat this as part of a bidding CLI. I better move it.
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.
a separate PR would be better, in fact.
c29b823
to
4983d7e
Compare
a05f324
to
fa305ac
Compare
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.
Has some rough edges and tech debt that don't belong in product code. However, this tool is for testing and it that bar. These features will help a lot so LGTM to merge as is.
const makeCollateral = x => | ||
AmountMath.make(collateralBrand, scaleDecimals(x)); | ||
|
||
const makeBidOffer = (parseAmount, opts) => { |
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 makes this offer maker different than all the rest in here. I think we should maintain an ClientOfferMaker function signature. Can't enforce that until we upgrade to TS 5.0 though: https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#satisfies-support-in-jsdoc
I won't block on this but please leave an XXX comment or make a new issue to get consistency.
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.
added XXX
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 second thought, in order to address some testing feedback from CH above, I moved parseAmount
in to opts
so that this one follows the convention.
816d452
to
c0fb26b
Compare
flake?
|
because --keyring-backend=test gets boring
BREAKING CHANGE: --giveCurrency option becomes --give and likewise --wantCollateral -> --want. Use snake-case for options throughout to match cosmos-sdk style - `bid` commands integrate `wallet send` step - show bid result - use only liveOffers for inter bid list by default - to show all: --all - fix: provide --allow-spend for tryExitOffer unless/until we change the wallet contract - don't show redundant result in error case - trial: use offer safe want in by-price bids - leave exit onDemand implicit - refactor: - factor out outputActionAndHint - allow explicit io for execSwingsetTransaction - combine options into one object - factor out storedWalletState - factor pollBlocks out of pollTx - update tests feat: inter bid by-discount sends; --generate-only; list --all - bid by-discount, like by-price, sends the tx - factor out placeBid, SharedBidOpts, withSharedBidOptions - bid list uses activeOffers unless --all is given - support --generate-only - use snake-case for option names; avoid [xx] optional syntax - give PATH clue everywhere execFileSync is used - test.todo()s - code polish: - expand file, function docs - refactor: hoist bidInvitationShape
- chore: bid "want" is required but different from proposal.want
- docs: normalizeAddress: keyring type tweak
closes: #6930
Description
Rather than just printing an offer, sign and broadcast it, wait for it to appear in a block, and wait for the effect in the wallet state. Give non-zero exit code on errors.
agops inter bid cancel <id>
command (with snapshot reference docs).agops inter bid
, the "want" defaults to a very high number (1_000_000n). Note: this is not "want" in the Zoe sense; it's more like "maxPurchase"agd
is not in$PATH
, give a reasonable diagnostic rather than a stack trace--keyring-background
default fromenv.AGORIC_KEYRING_BACKGROUND
Security Considerations
not much... though making it less error prone contributes to security
Scaling Considerations
polls every 3 seconds (Nyquist freq of 6 sec block time) when waiting for tx to appear in a block or for wallet state change.
Documentation Considerations
See #7295 for an attempt at somewhat reasonable docs.
agops inter bid cancel
has reference docs by way of a snapshot test, as usual.I didn't add any docs for
$AGORIC_KEYRING_BACKGROUND
.Testing Considerations
Significant manual testing, though not all on the same version.
I tested
agops inter bid cancel
end-to-end on a testnet. Before,agops inter bid list
showed:then:
and after, we got our money back: