@agoric/fast-usdc 0.1.1-dev-1231911.0 → 0.1.1-dev-34f026b.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/fast-usdc",
3
- "version": "0.1.1-dev-1231911.0+1231911",
3
+ "version": "0.1.1-dev-34f026b.0+34f026b",
4
4
  "description": "CLI and library for Fast USDC product",
5
5
  "type": "module",
6
6
  "files": [
@@ -22,9 +22,9 @@
22
22
  "lint:eslint": "eslint ."
23
23
  },
24
24
  "devDependencies": {
25
- "@agoric/swingset-liveslots": "0.10.3-dev-1231911.0+1231911",
26
- "@agoric/vats": "0.15.2-dev-1231911.0+1231911",
27
- "@agoric/zone": "0.2.3-dev-1231911.0+1231911",
25
+ "@agoric/swingset-liveslots": "0.10.3-dev-34f026b.0+34f026b",
26
+ "@agoric/vats": "0.15.2-dev-34f026b.0+34f026b",
27
+ "@agoric/zone": "0.2.3-dev-34f026b.0+34f026b",
28
28
  "@fast-check/ava": "^2.0.1",
29
29
  "ava": "^5.3.0",
30
30
  "c8": "^10.1.2",
@@ -32,15 +32,15 @@
32
32
  "ts-blank-space": "^0.4.4"
33
33
  },
34
34
  "dependencies": {
35
- "@agoric/client-utils": "0.1.1-dev-1231911.0+1231911",
36
- "@agoric/ertp": "0.16.3-dev-1231911.0+1231911",
37
- "@agoric/internal": "0.3.3-dev-1231911.0+1231911",
38
- "@agoric/notifier": "0.6.3-dev-1231911.0+1231911",
39
- "@agoric/orchestration": "0.1.1-dev-1231911.0+1231911",
40
- "@agoric/store": "0.9.3-dev-1231911.0+1231911",
41
- "@agoric/vat-data": "0.5.3-dev-1231911.0+1231911",
42
- "@agoric/vow": "0.1.1-dev-1231911.0+1231911",
43
- "@agoric/zoe": "0.26.3-dev-1231911.0+1231911",
35
+ "@agoric/client-utils": "0.1.1-dev-34f026b.0+34f026b",
36
+ "@agoric/ertp": "0.16.3-dev-34f026b.0+34f026b",
37
+ "@agoric/internal": "0.3.3-dev-34f026b.0+34f026b",
38
+ "@agoric/notifier": "0.6.3-dev-34f026b.0+34f026b",
39
+ "@agoric/orchestration": "0.1.1-dev-34f026b.0+34f026b",
40
+ "@agoric/store": "0.9.3-dev-34f026b.0+34f026b",
41
+ "@agoric/vat-data": "0.5.3-dev-34f026b.0+34f026b",
42
+ "@agoric/vow": "0.1.1-dev-34f026b.0+34f026b",
43
+ "@agoric/zoe": "0.26.3-dev-34f026b.0+34f026b",
44
44
  "@cosmjs/proto-signing": "^0.32.4",
45
45
  "@cosmjs/stargate": "^0.32.4",
46
46
  "@endo/base64": "^1.0.9",
@@ -80,5 +80,5 @@
80
80
  "publishConfig": {
81
81
  "access": "public"
82
82
  },
83
- "gitHead": "1231911e6c1bb4d5604f0e49c3a26c99131eb52e"
83
+ "gitHead": "34f026b7be9ace7022458d7f7b890828cfa4e951"
84
84
  }
@@ -4,13 +4,16 @@ import { boardSlottingMarshaller } from '@agoric/client-utils';
4
4
  * @import {BridgeAction} from '@agoric/smart-wallet/src/smartWallet.js';
5
5
  */
6
6
 
7
- const marshaller = boardSlottingMarshaller();
7
+ const defaultMarshaller = boardSlottingMarshaller();
8
+
9
+ /** @typedef {ReturnType<boardSlottingMarshaller>} BoardSlottingMarshaller */
8
10
 
9
11
  /**
10
12
  * @param {BridgeAction} bridgeAction
11
13
  * @param {Pick<import('stream').Writable,'write'>} stdout
14
+ * @param {BoardSlottingMarshaller} marshaller
12
15
  */
13
- const outputAction = (bridgeAction, stdout) => {
16
+ const outputAction = (bridgeAction, stdout, marshaller) => {
14
17
  const capData = marshaller.toCapData(harden(bridgeAction));
15
18
  stdout.write(JSON.stringify(capData));
16
19
  stdout.write('\n');
@@ -25,8 +28,13 @@ export const sendHint =
25
28
  * stdout: Pick<import('stream').Writable,'write'>,
26
29
  * stderr: Pick<import('stream').Writable,'write'>,
27
30
  * }} io
31
+ * @param {BoardSlottingMarshaller | undefined} marshaller
28
32
  */
29
- export const outputActionAndHint = (bridgeAction, { stdout, stderr }) => {
30
- outputAction(bridgeAction, stdout);
33
+ export const outputActionAndHint = (
34
+ bridgeAction,
35
+ { stdout, stderr },
36
+ marshaller = defaultMarshaller,
37
+ ) => {
38
+ outputAction(bridgeAction, stdout, marshaller);
31
39
  stderr.write(sendHint);
32
40
  };
package/src/cli/cli.js CHANGED
@@ -1,11 +1,6 @@
1
1
  /* eslint-env node */
2
2
  /* global globalThis */
3
- import { assertParsableNumber } from '@agoric/zoe/src/contractSupport/ratio.js';
4
- import {
5
- Command,
6
- InvalidArgumentError,
7
- InvalidOptionArgumentError,
8
- } from 'commander';
3
+ import { Command } from 'commander';
9
4
  import { existsSync, mkdirSync, readFileSync } from 'fs';
10
5
  import { fileURLToPath } from 'url';
11
6
  import { dirname, resolve } from 'path';
@@ -19,6 +14,7 @@ import { addOperatorCommands } from './operator-commands.js';
19
14
  import * as configLib from './config.js';
20
15
  import transferLib from './transfer.js';
21
16
  import { makeFile } from '../util/file.js';
17
+ import { addLPCommands } from './lp-commands.js';
22
18
 
23
19
  const packageJson = JSON.parse(
24
20
  readFileSync(
@@ -83,51 +79,7 @@ export const initProgram = (
83
79
  env,
84
80
  now,
85
81
  });
86
-
87
- /** @param {string} value */
88
- const parseDecimal = value => {
89
- try {
90
- assertParsableNumber(value);
91
- } catch {
92
- throw new InvalidArgumentError('Not a decimal number.');
93
- }
94
- return value;
95
- };
96
-
97
- /**
98
- * @param {string} str
99
- * @returns {'auto' | number}
100
- */
101
- const parseFee = str => {
102
- if (str === 'auto') return 'auto';
103
- const num = parseFloat(str);
104
- if (Number.isNaN(num)) {
105
- throw new InvalidOptionArgumentError('Fee must be a number.');
106
- }
107
- return num;
108
- };
109
-
110
- program
111
- .command('deposit')
112
- .description('Offer assets to the liquidity pool')
113
- .argument('<give>', 'USDC to give', parseDecimal)
114
- .option('--id [offer-id]', 'Offer ID')
115
- .option('--fee [fee]', 'Cosmos fee', parseFee)
116
- .action(() => {
117
- console.error('TODO actually send deposit');
118
- // TODO: Implement deposit logic
119
- });
120
-
121
- program
122
- .command('withdraw')
123
- .description('Withdraw assets from the liquidity pool')
124
- .argument('<want>', 'USDC to withdraw', parseDecimal)
125
- .option('--id [offer-id]', 'Offer ID')
126
- .option('--fee [fee]', 'Cosmos fee', parseFee)
127
- .action(() => {
128
- console.error('TODO actually send withdrawal');
129
- // TODO: Implement withdraw logic
130
- });
82
+ addLPCommands(program, { fetch, stdout, stderr, env, now });
131
83
 
132
84
  program
133
85
  .command('transfer')
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @import {Command} from 'commander';
3
+ * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
4
+ * @import {ExecuteOfferAction} from '@agoric/smart-wallet/src/smartWallet.js';
5
+ * @import {USDCProposalShapes} from '../pool-share-math.js';
6
+ */
7
+
8
+ import { fetchEnvNetworkConfig, makeVstorageKit } from '@agoric/client-utils';
9
+ import { InvalidArgumentError } from 'commander';
10
+ import {
11
+ assertParsableNumber,
12
+ ceilDivideBy,
13
+ multiplyBy,
14
+ parseRatio,
15
+ } from '@agoric/zoe/src/contractSupport/ratio.js';
16
+ import { AmountMath } from '@agoric/ertp';
17
+ import { outputActionAndHint } from './bridge-action.js';
18
+
19
+ /** @param {string} arg */
20
+ const parseDecimal = arg => {
21
+ try {
22
+ assertParsableNumber(arg);
23
+ const n = Number(arg);
24
+ return n;
25
+ } catch {
26
+ throw new InvalidArgumentError('Not a number');
27
+ }
28
+ };
29
+
30
+ /**
31
+ * @param {string} amountString
32
+ * @param {Brand} usdc
33
+ */
34
+ const parseUSDCAmount = (amountString, usdc) => {
35
+ const USDC_DECIMALS = 6;
36
+ const unit = AmountMath.make(usdc, 10n ** BigInt(USDC_DECIMALS));
37
+ return multiplyBy(unit, parseRatio(amountString, usdc));
38
+ };
39
+
40
+ /**
41
+ * @param {Command} program
42
+ * @param {{
43
+ * fetch?: Window['fetch'];
44
+ * vstorageKit?: Awaited<ReturnType<typeof makeVstorageKit>>;
45
+ * stdout: typeof process.stdout;
46
+ * stderr: typeof process.stderr;
47
+ * env: typeof process.env;
48
+ * now: typeof Date.now;
49
+ * }} io
50
+ */
51
+ export const addLPCommands = (
52
+ program,
53
+ { fetch, vstorageKit, stderr, stdout, env, now },
54
+ ) => {
55
+ const loadVsk = async () => {
56
+ if (vstorageKit) {
57
+ return vstorageKit;
58
+ }
59
+ assert(fetch);
60
+ const networkConfig = await fetchEnvNetworkConfig({ env, fetch });
61
+ return makeVstorageKit({ fetch }, networkConfig);
62
+ };
63
+ /** @type {undefined | ReturnType<typeof loadVsk>} */
64
+ let vskP;
65
+
66
+ program
67
+ .command('deposit')
68
+ .description('Deposit USDC into pool')
69
+ .addHelpText(
70
+ 'after',
71
+ '\nPipe the STDOUT to a file such as deposit.json, then use the Agoric CLI to broadcast it:\n agoric wallet send --offer deposit.json --from gov1 --keyring-backend="test"',
72
+ )
73
+ .requiredOption('--amount <number>', 'USDC amount', parseDecimal)
74
+ .option('--offerId <string>', 'Offer id', String, `lpDeposit-${now()}`)
75
+ .action(async opts => {
76
+ vskP ||= loadVsk();
77
+ const vsk = await vskP;
78
+ /** @type {Brand<'nat'>} */
79
+ // @ts-expect-error it doesnt recognize usdc as a Brand type
80
+ const usdc = vsk.agoricNames.brand.USDC;
81
+ assert(usdc, 'USDC brand not in agoricNames');
82
+
83
+ const usdcAmount = parseUSDCAmount(opts.amount, usdc);
84
+
85
+ /** @type {USDCProposalShapes['deposit']} */
86
+ const proposal = {
87
+ give: {
88
+ USDC: usdcAmount,
89
+ },
90
+ };
91
+
92
+ /** @type {OfferSpec} */
93
+ const offer = {
94
+ id: opts.offerId,
95
+ invitationSpec: {
96
+ source: 'agoricContract',
97
+ instancePath: ['fastUsdc'],
98
+ callPipe: [['makeDepositInvitation', []]],
99
+ },
100
+ proposal,
101
+ };
102
+
103
+ /** @type {ExecuteOfferAction} */
104
+ const bridgeAction = {
105
+ method: 'executeOffer',
106
+ offer,
107
+ };
108
+
109
+ outputActionAndHint(bridgeAction, { stderr, stdout }, vsk.marshaller);
110
+ });
111
+
112
+ program
113
+ .command('withdraw')
114
+ .description("Withdraw USDC from the LP's pool share")
115
+ .addHelpText(
116
+ 'after',
117
+ '\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"',
118
+ )
119
+ .requiredOption('--amount <number>', 'USDC amount', parseDecimal)
120
+ .option('--offerId <string>', 'Offer id', String, `lpWithdraw-${now()}`)
121
+ .action(async opts => {
122
+ vskP ||= loadVsk();
123
+ const vsk = await vskP;
124
+
125
+ /** @type {Brand<'nat'>} */
126
+ // @ts-expect-error it doesnt recognize FastLP as a Brand type
127
+ const poolShare = vsk.agoricNames.brand.FastLP;
128
+ assert(poolShare, 'FastLP brand not in agoricNames');
129
+
130
+ /** @type {Brand<'nat'>} */
131
+ // @ts-expect-error it doesnt recognize usdc as a Brand type
132
+ const usdc = vsk.agoricNames.brand.USDC;
133
+ assert(usdc, 'USDC brand not in agoricNames');
134
+
135
+ const usdcAmount = parseUSDCAmount(opts.amount, usdc);
136
+
137
+ /** @type {import('../types.js').PoolMetrics} */
138
+ // @ts-expect-error it treats this as "unknown"
139
+ const metrics = await vsk.readPublished('fastUsdc.poolMetrics');
140
+ const fastLPAmount = ceilDivideBy(usdcAmount, metrics.shareWorth);
141
+
142
+ /** @type {USDCProposalShapes['withdraw']} */
143
+ const proposal = {
144
+ give: {
145
+ PoolShare: fastLPAmount,
146
+ },
147
+ want: {
148
+ USDC: usdcAmount,
149
+ },
150
+ };
151
+
152
+ /** @type {OfferSpec} */
153
+ const offer = {
154
+ id: opts.offerId,
155
+ invitationSpec: {
156
+ source: 'agoricContract',
157
+ instancePath: ['fastUsdc'],
158
+ callPipe: [['makeWithdrawInvitation', []]],
159
+ },
160
+ proposal,
161
+ };
162
+
163
+ outputActionAndHint(
164
+ { method: 'executeOffer', offer },
165
+ { stderr, stdout },
166
+ vsk.marshaller,
167
+ );
168
+ });
169
+
170
+ return program;
171
+ };
@@ -80,6 +80,10 @@ export const addOperatorCommands = (
80
80
  operator
81
81
  .command('attest')
82
82
  .description('Attest to an observed Fast USDC transfer')
83
+ .addHelpText(
84
+ 'after',
85
+ '\nPipe the STDOUT to a file such as attest.json, then use the Agoric CLI to broadcast it:\n agoric wallet send --offer attest.json --from gov1 --keyring-backend="test"',
86
+ )
83
87
  .requiredOption('--previousOfferId <string>', 'Offer id', String)
84
88
  .requiredOption('--forwardingChannel <string>', 'Channel id', String)
85
89
  .requiredOption('--recipientAddress <string>', 'bech32 address', String)