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

client support for Fast USDC #10735

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

client support for Fast USDC #10735

wants to merge 9 commits into from

Conversation

turadg
Copy link
Member

@turadg turadg commented Dec 18, 2024

refs: #10677

Description

Everything in #10677 except the offer makers. I think that'll come through Noble integration.

Security Considerations

none

Scaling Considerations

none

Documentation Considerations

none

Testing Considerations

nothing special

Upgrade Considerations

not yet released

Copy link

cloudflare-workers-and-pages bot commented Dec 18, 2024

Deploying agoric-sdk with  Cloudflare Pages  Cloudflare Pages

Latest commit: f4f6a52
Status: ✅  Deploy successful!
Preview URL: https://4fdd78cc.agoric-sdk.pages.dev
Branch Preview URL: https://10677-fu-client-support.agoric-sdk.pages.dev

View logs

@turadg turadg force-pushed the 10677-fu-client-support branch from c76dc1b to e49ad00 Compare December 18, 2024 23:42
@turadg turadg force-pushed the 10677-fu-client-support branch from e49ad00 to ea8de31 Compare January 14, 2025 01:16
Fixes this warning from typdoc,
```
./packages/SwingSet/src/controller/controller.js:480:21 - [warning] The relative path ../docs/run-policy.md is not a file and will not be copied to the output directory

480         * [`runPolicy`](../docs/run-policy.md) to rate-limit cleanups.
```
@turadg turadg force-pushed the 10677-fu-client-support branch from ea8de31 to 7374d68 Compare January 24, 2025 23:14
@turadg turadg requested review from dckc and samsiegart January 24, 2025 23:15
Copy link
Member

@dckc dckc left a comment

Choose a reason for hiding this comment

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

oops... I think I misinterpreted a request-for-review notification

So these comments might be a bit premature...

@@ -55,6 +55,11 @@ export interface TransactionRecord extends CopyRecord {
status: TxStatus;
}

export interface ContractRecord extends CopyRecord {
Copy link
Member

Choose a reason for hiding this comment

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

the name... does it refer to "the record you'll get from vstorage if you query the contract's node"?

docstring, please?

Comment on lines +41 to +44
: T extends 'agoricNames.instance'
? Array<[string, Instance]>
: T extends 'agoricNames.brand'
? Array<[string, Brand]>
Copy link
Member

Choose a reason for hiding this comment

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

A lot of the relevant code expects not just a Brand but a Brand<'nat'> or Brand<'set'>.

const { USDC, FastLP } = await agoricNamesQ(vstorageClient).brands('nat');

const { Invitation } = await agoricNamesQ(vsc).brands('set');

I suppose one can add as Brand<'nat'>, but it almost defeats the point. It's also helpful to reassemble the entries into a record. Do you want to add helpers for this sort of thing?

Copy link
Member Author

Choose a reason for hiding this comment

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

agreed this is low value because you'll often want the kind of brand. It's still true tho so I think it's worth having here.

Comment on lines +45 to +48
: T extends 'fastUsdc'
? ContractRecord
: T extends 'fastUsdc.poolMetrics'
? PoolMetrics
Copy link
Member

Choose a reason for hiding this comment

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

It still feels strange for client-utils to depend on fast-usdc. Should it depend on dapp-offer-up and dapp-agoric-basics likewise?

It seems like fast-usdc should extend the type from client-utils.

Copy link
Member Author

Choose a reason for hiding this comment

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

It is weird but ok for now. We'll have to solve it for #10811

Comment on lines 99 to 100
/** @type {import('../types.js').PoolMetrics} */
// @ts-expect-error it treats this as "unknown"
Copy link
Member

Choose a reason for hiding this comment

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

do you want to get rid of the type annotation while you're at it?

Copy link
Member Author

Choose a reason for hiding this comment

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

oh yeah thanks

Comment on lines +294 to -295
settlementAddress: ChainAddressShape,
intermediateRecipient: M.opt(ChainAddressShape),
settlementAddress: M.opt(ChainAddressShape),
Copy link
Member

Choose a reason for hiding this comment

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

good catch!

What prompted it, I wonder?

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't remember but I'm guessing some type feedback

@turadg
Copy link
Member Author

turadg commented Jan 25, 2025

these comments might be a bit premature...

Thanks they're helpful. I was just waiting for CI to get green before requesting.

In the interim I gave Aider with R1+Sonnet a spin. 88f0921 has its solution to adding a ClientSupport module. LGTM! Minor cleanup in f4f6a52.

@turadg turadg marked this pull request as ready for review January 25, 2025 00:12
@turadg turadg requested a review from a team as a code owner January 25, 2025 00:12
Copy link
Contributor

@samsiegart samsiegart left a comment

Choose a reason for hiding this comment

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

From description:

Everything in #10677 except the offer makers. I think that'll come through Noble integration.

I think you added the offer makers in packages/fast-usdc/src/clientSupport.js right? Also, by Noble integration do you mean Noble Express UI? Because that won't be submitting any offers AFAIK. Only LPs and OCW will.

I'm assuming we're going to change the CLI and multichain-testing to use these offer functions in a later PR?

The actual code changes in this PR LGTM, so approving.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to also add functions for accepting the operator invitation and submitting evidence?

Copy link
Contributor

Choose a reason for hiding this comment

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

Test for WithdrawFees?

@@ -15,7 +15,7 @@ import { parseArgs } from 'node:util';
/**
* @import {CoreEvalBuilder, DeployScriptFunction} from '@agoric/deploy-script-support/src/externalTypes.js'
* @import {ParseArgsConfig} from 'node:util'
* @import {FastUSDCConfig, FeedPolicy} from '@agoric/fast-usdc/src/types.js'
* @import {FastUSDCConfig, FeedPolicy} from '@agoric/fast-usdc';
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: there's a semicolon here but not for the lines above. I wonder if eslint/prettier should have a rule for this

Copy link
Member

@dckc dckc left a comment

Choose a reason for hiding this comment

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

Let's factor the offer makers out of existing code.

And as a result, let's leave BoardRemote behind and go from Number to ERTP ratio early.

* @param {number} opts.amount
* @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
*/
const makeDepositOffer = ({ brand }, instance, { offerId, amount }) => {
Copy link
Member

Choose a reason for hiding this comment

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

want is required, and the keyword is USDC, not Deposit.

I'd like us to re-use the existing fast usdc deposit type as in:

/** @type {USDCProposalShapes['deposit']} */
const proposal = {
give: {
USDC: usdcAmount,
},
want: {
PoolShare: fastLPAmount,
},
};

We could calculate the want for them if they pass in metrics or shareWorth as in...

const metrics = await swk.readPublished('fastUsdc.poolMetrics');
const fastLPAmount = floorDivideBy(usdcAmount, metrics.shareWorth);

We might want a slippage parameter.


/**
* @param {Pick<
* import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
Copy link
Member

Choose a reason for hiding this comment

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

Let's please stop using BoardRemote and hence AgoricNamesRemotes. Just use the ordinary types like Brand.

ref


// Reusable amount scaling similar to inter-protocol's approach
const COSMOS_UNIT = 1_000_000n;
const scaleDecimals = num => BigInt(num * Number(COSMOS_UNIT));
Copy link
Member

Choose a reason for hiding this comment

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

Using Number has weird edge cases. For example, if the product inside BigInt isn't an integer, it throws.

Let's stick to ERTP Amount and Ratio as in:

const parseUSDCAmount = (amountString, usdc) => {
const USDC_DECIMALS = 6;
const unit = AmountMath.make(usdc, 10n ** BigInt(USDC_DECIMALS));
return multiplyBy(unit, parseRatio(amountString, usdc));
};

parseRatio will take a Number or a string (anything that passes assertParsableNumber), so we could relax amountString likewise.

For commander-style arg parsing, we could export this one:

const parseDecimal = arg => {
try {
assertParsableNumber(arg);
const n = Number(arg);
return n;
} catch {
throw new InvalidArgumentError('Not a number');
}
};

},
proposal: {
give: {
Deposit: {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Deposit: {
USDC: {

* @param {number} opts.amount
* @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
*/
const makeWithdrawOffer = ({ brand }, instance, { offerId, amount }) => ({
Copy link
Member

Choose a reason for hiding this comment

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

give is not optional when withdrawing.

again, let's factor this helper out of...

program
.command('withdraw')
.description("Withdraw USDC from the LP's pool share")

});

/** @satisfies {Record<string, import('@agoric/smart-wallet/src/types.js').OfferMaker>} */
export const Offers = {
Copy link
Member

Choose a reason for hiding this comment

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

Is there any particular reason to export this Offers structure rather than the functions makeDepositOffer and such?

* @param {string} opts.offerId
* @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
*/
const makeWithdrawFeesOffer = (instance, { offerId }) => ({
Copy link
Member

Choose a reason for hiding this comment

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

This one is much less valuable; only a core-eval can withdraw fees.

But if we want to provide a helper, let's factor it out of...

export const distributeFees = async (permittedPowers, config) => {

Note support for both absolute amounts and proportions.

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