Skip to content

Commit

Permalink
fixup! feat(fast-usdc): cli for lp deposit and withdraw
Browse files Browse the repository at this point in the history
  • Loading branch information
samsiegart committed Dec 10, 2024
1 parent 2411b6a commit d10cfb9
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 30 deletions.
72 changes: 46 additions & 26 deletions packages/fast-usdc/src/cli/lp-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,20 @@
* @import {Command} from 'commander';
* @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
* @import {ExecuteOfferAction} from '@agoric/smart-wallet/src/smartWallet.js';
* @import {USDCProposalShapes} from '../pool-share-math.js';
*/

import { fetchEnvNetworkConfig, makeVstorageKit } from '@agoric/client-utils';
import { InvalidArgumentError } from 'commander';
import {
assertParsableNumber,
ceilDivideBy,
multiplyBy,
parseRatio,
} from '@agoric/zoe/src/contractSupport/ratio.js';
import { Nat } from '@endo/nat';
import { AmountMath } from '@agoric/ertp';
import { outputActionAndHint } from './bridge-action.js';

/** @param {string} arg */
const parseNat = arg => {
try {
const n = Nat(BigInt(arg));
return n;
} catch {
throw new InvalidArgumentError('Not a number');
}
};

/** @param {string} arg */
const parseDecimal = arg => {
try {
Expand All @@ -36,6 +27,16 @@ const parseDecimal = arg => {
}
};

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

/**
* @param {Command} program
* @param {{
Expand Down Expand Up @@ -79,9 +80,14 @@ export const addLPCommands = (
const usdc = vsk.agoricNames.brand.USDC;
assert(usdc, 'USDC brand not in agoricNames');

const USDC_DECIMALS = 6;
const unit = AmountMath.make(usdc, 10n ** BigInt(USDC_DECIMALS));
const usdcAmount = multiplyBy(unit, parseRatio(opts.amount, usdc));
const usdcAmount = parseUSDCAmount(opts.amount, usdc);

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

/** @type {OfferSpec} */
const offer = {
Expand All @@ -91,11 +97,7 @@ export const addLPCommands = (
instancePath: ['fastUsdc'],
callPipe: [['makeDepositInvitation', []]],
},
proposal: {
give: {
USDC: usdcAmount,
},
},
proposal,
};

/** @type {ExecuteOfferAction} */
Expand All @@ -114,17 +116,39 @@ export const addLPCommands = (
'after',
'\nPipe the STDOUT to a file such as withdraw.json, then use the Agoric CLI to broadcast it:\n agoric wallet send --offer withdraw.json --from gov1 --keyring-backend="test"',
)
.requiredOption('--amount <number>', 'FastLP amount', parseNat)
.requiredOption('--amount <number>', 'USDC amount', parseDecimal)
.option('--offerId <string>', 'Offer id', String, `lpWithdraw-${now()}`)
.action(async opts => {
vskP ||= loadVsk();
const vsk = await vskP;

/** @type {Brand<'nat'>} */
// @ts-expect-error it doesnt recognize usdc as a Brand type
// @ts-expect-error it doesnt recognize FastLP as a Brand type
const poolShare = vsk.agoricNames.brand.FastLP;
assert(poolShare, 'FastLP brand not in agoricNames');

/** @type {Brand<'nat'>} */
// @ts-expect-error it doesnt recognize usdc as a Brand type
const usdc = vsk.agoricNames.brand.USDC;
assert(usdc, 'USDC brand not in agoricNames');

const usdcAmount = parseUSDCAmount(opts.amount, usdc);

/** @type {import('../types.js').PoolMetrics} */
// @ts-expect-error it treats this as "unknown"
const metrics = await vsk.readPublished('fastUsdc.poolMetrics');
const fastLPAmount = ceilDivideBy(usdcAmount, metrics.shareWorth);

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

/** @type {OfferSpec} */
const offer = {
id: opts.offerId,
Expand All @@ -133,11 +157,7 @@ export const addLPCommands = (
instancePath: ['fastUsdc'],
callPipe: [['makeWithdrawInvitation', []]],
},
proposal: {
give: {
PoolShare: { brand: poolShare, value: opts.amount },
},
},
proposal,
};

outputActionAndHint(
Expand Down
20 changes: 16 additions & 4 deletions packages/fast-usdc/test/cli/lp-commands.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Far, makeMarshal } from '@endo/marshal';
import anyTest, { type TestFn } from 'ava';
import { Command } from 'commander';
import { makeRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
import { flags } from '../../tools/cli-tools.js';
import { mockStream } from '../../tools/mock-io.js';
import { addLPCommands } from '../../src/cli/lp-commands.js';
Expand Down Expand Up @@ -35,6 +36,14 @@ const makeTestContext = () => {
// @ts-expect-error fake brands
agoricNames: { brand: { FastLP, USDC } },
marshaller,
// @ts-expect-error ignore fancy return type
readPublished: async (path: string) => {
if (path === 'fastUsdc.poolMetrics') {
// @ts-expect-error not real brands
return { shareWorth: makeRatio(110n, USDC, 100n, FastLP) };
}
return {};
},
},
stdout: mockStream<typeof process.stdout>(out),
stderr: mockStream<typeof process.stderr>(err),
Expand All @@ -48,7 +57,7 @@ const makeTestContext = () => {
const test = anyTest as TestFn<Awaited<ReturnType<typeof makeTestContext>>>;
test.beforeEach(async t => (t.context = await makeTestContext()));

test('fast-usdc lp deposit sub-command', async t => {
test('fast-usdc deposit command', async t => {
const { program, marshaller, out, err, USDC } = t.context;
const amount = 100.05;
const argv = [...`node fast-usdc deposit`.split(' '), ...flags({ amount })];
Expand Down Expand Up @@ -79,8 +88,8 @@ test('fast-usdc lp deposit sub-command', async t => {
);
});

test('fast-usdc lp withdraw sub-command', async t => {
const { program, marshaller, out, err, FastLP, now } = t.context;
test('fast-usdc withdraw command', async t => {
const { program, marshaller, out, err, FastLP, USDC } = t.context;
const amount = 100;
const argv = [...`node fast-usdc withdraw`.split(' '), ...flags({ amount })];
t.log(...argv);
Expand All @@ -98,7 +107,10 @@ test('fast-usdc lp withdraw sub-command', async t => {
},
proposal: {
give: {
PoolShare: { brand: FastLP, value: 100n },
PoolShare: { brand: FastLP, value: 90_909_091n },
},
want: {
USDC: { brand: USDC, value: 100_000_000n },
},
},
},
Expand Down

0 comments on commit d10cfb9

Please sign in to comment.