@agoric/fast-usdc 0.1.1-dev-9f46b37.0 → 0.1.1-dev-fdc566c.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-9f46b37.0+9f46b37",
3
+ "version": "0.1.1-dev-fdc566c.0+fdc566c",
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-9f46b37.0+9f46b37",
26
- "@agoric/vats": "0.15.2-dev-9f46b37.0+9f46b37",
27
- "@agoric/zone": "0.2.3-dev-9f46b37.0+9f46b37",
25
+ "@agoric/swingset-liveslots": "0.10.3-dev-fdc566c.0+fdc566c",
26
+ "@agoric/vats": "0.15.2-dev-fdc566c.0+fdc566c",
27
+ "@agoric/zone": "0.2.3-dev-fdc566c.0+fdc566c",
28
28
  "@fast-check/ava": "^2.0.1",
29
29
  "ava": "^5.3.0",
30
30
  "c8": "^10.1.2",
@@ -32,16 +32,16 @@
32
32
  "ts-blank-space": "^0.4.4"
33
33
  },
34
34
  "dependencies": {
35
- "@agoric/client-utils": "0.1.1-dev-9f46b37.0+9f46b37",
36
- "@agoric/cosmic-proto": "0.4.1-dev-9f46b37.0+9f46b37",
37
- "@agoric/ertp": "0.16.3-dev-9f46b37.0+9f46b37",
38
- "@agoric/internal": "0.3.3-dev-9f46b37.0+9f46b37",
39
- "@agoric/notifier": "0.6.3-dev-9f46b37.0+9f46b37",
40
- "@agoric/orchestration": "0.1.1-dev-9f46b37.0+9f46b37",
41
- "@agoric/store": "0.9.3-dev-9f46b37.0+9f46b37",
42
- "@agoric/vat-data": "0.5.3-dev-9f46b37.0+9f46b37",
43
- "@agoric/vow": "0.1.1-dev-9f46b37.0+9f46b37",
44
- "@agoric/zoe": "0.26.3-dev-9f46b37.0+9f46b37",
35
+ "@agoric/client-utils": "0.1.1-dev-fdc566c.0+fdc566c",
36
+ "@agoric/cosmic-proto": "0.4.1-dev-fdc566c.0+fdc566c",
37
+ "@agoric/ertp": "0.16.3-dev-fdc566c.0+fdc566c",
38
+ "@agoric/internal": "0.3.3-dev-fdc566c.0+fdc566c",
39
+ "@agoric/notifier": "0.6.3-dev-fdc566c.0+fdc566c",
40
+ "@agoric/orchestration": "0.1.1-dev-fdc566c.0+fdc566c",
41
+ "@agoric/store": "0.9.3-dev-fdc566c.0+fdc566c",
42
+ "@agoric/vat-data": "0.5.3-dev-fdc566c.0+fdc566c",
43
+ "@agoric/vow": "0.1.1-dev-fdc566c.0+fdc566c",
44
+ "@agoric/zoe": "0.26.3-dev-fdc566c.0+fdc566c",
45
45
  "@cosmjs/proto-signing": "^0.32.4",
46
46
  "@cosmjs/stargate": "^0.32.4",
47
47
  "@endo/base64": "^1.0.9",
@@ -81,5 +81,5 @@
81
81
  "publishConfig": {
82
82
  "access": "public"
83
83
  },
84
- "gitHead": "9f46b37ac0e67f89e6f346c9371032409b688633"
84
+ "gitHead": "fdc566ceba2386ac9cccd2e095741dcd316b575b"
85
85
  }
@@ -0,0 +1,93 @@
1
+ /** @file core eval module to collect fees. */
2
+ import { AmountMath } from '@agoric/ertp';
3
+ import { floorMultiplyBy } from '@agoric/zoe/src/contractSupport/index.js';
4
+ import { E } from '@endo/far';
5
+ import { makeTracer } from '@agoric/internal';
6
+ import { fromExternalConfig } from './utils/config-marshal.js';
7
+
8
+ /**
9
+ * @import {DepositFacet} from '@agoric/ertp';
10
+ * @import {FastUSDCCorePowers} from '@agoric/fast-usdc/src/start-fast-usdc.core.js';
11
+ * @import {CopyRecord} from '@endo/pass-style'
12
+ * @import {BootstrapManifestPermit} from '@agoric/vats/src/core/lib-boot.js'
13
+ * @import {LegibleCapData} from './utils/config-marshal.js'
14
+ */
15
+
16
+ /**
17
+ * @typedef {{ destinationAddress: string } &
18
+ * ({ feePortion: Ratio} | {fixedFees: Amount<'nat'>}) &
19
+ * CopyRecord
20
+ * } FeeDistributionTerms
21
+ */
22
+
23
+ const kwUSDC = 'USDC'; // keyword in AmountKeywordRecord
24
+ const issUSDC = 'USDC'; // issuer name
25
+
26
+ const trace = makeTracer('FUCF', true);
27
+
28
+ /**
29
+ * @param {BootstrapPowers & FastUSDCCorePowers } permittedPowers
30
+ * @param {{ options: LegibleCapData<{ feeTerms: FeeDistributionTerms}> }} config
31
+ */
32
+ export const distributeFees = async (permittedPowers, config) => {
33
+ trace('distributeFees...', config.options);
34
+
35
+ const { agoricNames, namesByAddress, zoe } = permittedPowers.consume;
36
+ /** @type {Brand<'nat'>} */
37
+ const usdcBrand = await E(agoricNames).lookup('brand', issUSDC);
38
+ /** @type {{ feeTerms: FeeDistributionTerms}} */
39
+ const { feeTerms: terms } = fromExternalConfig(config.options, {
40
+ USDC: usdcBrand,
41
+ });
42
+
43
+ const { creatorFacet } = await permittedPowers.consume.fastUsdcKit;
44
+ const want = {
45
+ [kwUSDC]: await ('fixedFees' in terms
46
+ ? terms.fixedFees
47
+ : E(creatorFacet)
48
+ .getContractFeeBalance()
49
+ .then(balance => floorMultiplyBy(balance, terms.feePortion))),
50
+ };
51
+ const proposal = harden({ want });
52
+
53
+ /** @type {DepositFacet} */
54
+ const depositFacet = await E(namesByAddress).lookup(
55
+ terms.destinationAddress,
56
+ 'depositFacet',
57
+ );
58
+ trace('to:', terms.destinationAddress, depositFacet);
59
+
60
+ const toWithdraw = await E(creatorFacet).makeWithdrawFeesInvitation();
61
+ trace('invitation:', toWithdraw, 'proposal:', proposal);
62
+ const seat = E(zoe).offer(toWithdraw, proposal);
63
+ const result = await E(seat).getOfferResult();
64
+ trace('offer result', result);
65
+ const payout = await E(seat).getPayout(kwUSDC);
66
+ /** @type {Amount<'nat'>} */
67
+ // @ts-expect-error USDC is a nat brand
68
+ const rxd = await E(depositFacet).receive(payout);
69
+ trace('received', rxd);
70
+ if (!AmountMath.isGTE(rxd, proposal.want[kwUSDC])) {
71
+ trace('🚨 expected', proposal.want[kwUSDC], 'got', rxd);
72
+ }
73
+ trace('done');
74
+ };
75
+ harden(distributeFees);
76
+
77
+ /** @satisfies {BootstrapManifestPermit} */
78
+ const permit = {
79
+ consume: {
80
+ fastUsdcKit: true,
81
+ agoricNames: true,
82
+ namesByAddress: true,
83
+ zoe: true,
84
+ },
85
+ };
86
+
87
+ /**
88
+ * @param {unknown} _utils
89
+ * @param {Parameters<typeof distributeFees>[1]} config
90
+ */
91
+ export const getManifestForDistributeFees = (_utils, { options }) => {
92
+ return { manifest: { [distributeFees.name]: permit }, options };
93
+ };
@@ -1,4 +1,4 @@
1
- import { AmountMath } from '@agoric/ertp';
1
+ import { AmountMath, AmountShape } from '@agoric/ertp';
2
2
  import {
3
3
  makeRecorderTopic,
4
4
  TopicsRecordShape,
@@ -107,11 +107,18 @@ export const prepareLiquidityPoolKit = (zone, zcf, USDC, tools) => {
107
107
  withdrawHandler: M.interface('withdrawHandler', {
108
108
  handle: M.call(SeatShape, M.any()).returns(M.promise()),
109
109
  }),
110
+ withdrawFeesHandler: M.interface('withdrawFeesHandler', {
111
+ handle: M.call(SeatShape, M.any()).returns(M.promise()),
112
+ }),
110
113
  public: M.interface('public', {
111
114
  makeDepositInvitation: M.call().returns(M.promise()),
112
115
  makeWithdrawInvitation: M.call().returns(M.promise()),
113
116
  getPublicTopics: M.call().returns(TopicsRecordShape),
114
117
  }),
118
+ feeRecipient: M.interface('feeRecipient', {
119
+ getContractFeeBalance: M.call().returns(AmountShape),
120
+ makeWithdrawFeesInvitation: M.call().returns(M.promise()),
121
+ }),
115
122
  },
116
123
  /**
117
124
  * @param {ZCFMint<'nat'>} shareMint
@@ -326,6 +333,21 @@ export const prepareLiquidityPoolKit = (zone, zcf, USDC, tools) => {
326
333
  external.publishPoolMetrics();
327
334
  },
328
335
  },
336
+ withdrawFeesHandler: {
337
+ /** @param {ZCFSeat} seat */
338
+ async handle(seat) {
339
+ const { feeSeat } = this.state;
340
+
341
+ const { want } = seat.getProposal();
342
+ const available = feeSeat.getAmountAllocated('USDC', want.USDC.brand);
343
+ isGTE(available, want.USDC) ||
344
+ Fail`cannot withdraw ${want.USDC}; only ${available} available`;
345
+
346
+ // COMMIT POINT
347
+ zcf.atomicRearrange(harden([[feeSeat, seat, want]]));
348
+ seat.exit();
349
+ },
350
+ },
329
351
  public: {
330
352
  makeDepositInvitation() {
331
353
  return zcf.makeInvitation(
@@ -353,6 +375,22 @@ export const prepareLiquidityPoolKit = (zone, zcf, USDC, tools) => {
353
375
  };
354
376
  },
355
377
  },
378
+ feeRecipient: {
379
+ getContractFeeBalance() {
380
+ const { feeSeat } = this.state;
381
+ /** @type {Amount<'nat'>} */
382
+ const balance = feeSeat.getCurrentAllocation().USDC;
383
+ return balance;
384
+ },
385
+ makeWithdrawFeesInvitation() {
386
+ return zcf.makeInvitation(
387
+ this.facets.withdrawFeesHandler,
388
+ 'Withdraw Fees',
389
+ undefined,
390
+ this.state.proposalShapes.withdrawFees,
391
+ );
392
+ },
393
+ },
356
394
  },
357
395
  {
358
396
  finish: ({ facets: { external } }) => {
@@ -161,6 +161,13 @@ export const contract = async (zcf, privateArgs, zone, tools) => {
161
161
  removeOperator(operatorId) {
162
162
  return feedKit.creator.removeOperator(operatorId);
163
163
  },
164
+ async getContractFeeBalance() {
165
+ return poolKit.feeRecipient.getContractFeeBalance();
166
+ },
167
+ /** @type {() => Promise<Invitation<unknown>>} */
168
+ async makeWithdrawFeesInvitation() {
169
+ return poolKit.feeRecipient.makeWithdrawFeesInvitation();
170
+ },
164
171
  async connectToNoble() {
165
172
  return vowTools.when(nobleAccountV, nobleAccount => {
166
173
  trace('nobleAccount', nobleAccount);
@@ -44,6 +44,9 @@ export const makeParity = (numerator, denominatorBrand) => {
44
44
  * withdraw: {
45
45
  * give: { PoolShare: Amount<'nat'> }
46
46
  * want: { USDC: Amount<'nat'> },
47
+ * },
48
+ * withdrawFees: {
49
+ * want: { USDC: Amount<'nat'> }
47
50
  * }
48
51
  * }} USDCProposalShapes
49
52
  */
@@ -1,22 +1,22 @@
1
1
  import { deeplyFulfilledObject, makeTracer } from '@agoric/internal';
2
- import { Fail } from '@endo/errors';
3
2
  import { E } from '@endo/far';
4
- import { makeMarshal } from '@endo/marshal';
5
3
  import { FastUSDCConfigShape } from './type-guards.js';
6
4
  import { fromExternalConfig } from './utils/config-marshal.js';
7
- import { inviteOracles, publishFeedPolicy } from './utils/core-eval.js';
5
+ import {
6
+ inviteOracles,
7
+ publishDisplayInfo,
8
+ publishFeedPolicy,
9
+ } from './utils/core-eval.js';
8
10
 
9
11
  /**
10
- * @import {Amount, Brand, DepositFacet, Issuer, Payment} from '@agoric/ertp';
11
- * @import {TypedPattern} from '@agoric/internal'
12
+ * @import {Brand, Issuer} from '@agoric/ertp';
12
13
  * @import {Instance, StartParams} from '@agoric/zoe/src/zoeService/utils'
13
14
  * @import {Board} from '@agoric/vats'
14
15
  * @import {ManifestBundleRef} from '@agoric/deploy-script-support/src/externalTypes.js'
15
16
  * @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js'
16
- * @import {Passable} from '@endo/pass-style'
17
17
  * @import {LegibleCapData} from './utils/config-marshal.js'
18
18
  * @import {FastUsdcSF} from './fast-usdc.contract.js'
19
- * @import {FeedPolicy, FastUSDCConfig} from './types.js'
19
+ * @import {FastUSDCConfig} from './types.js'
20
20
  */
21
21
 
22
22
  const ShareAssetInfo = /** @type {const} */ harden({
@@ -46,26 +46,6 @@ const makePublishingStorageKit = async (path, { chainStorage, board }) => {
46
46
  return { storageNode, marshaller };
47
47
  };
48
48
 
49
- const BOARD_AUX = 'boardAux';
50
- const marshalData = makeMarshal(_val => Fail`data only`);
51
- /**
52
- * @param {Brand} brand
53
- * @param {Pick<BootstrapPowers['consume'], 'board' | 'chainStorage'>} powers
54
- */
55
- const publishDisplayInfo = async (brand, { board, chainStorage }) => {
56
- // chainStorage type includes undefined, which doesn't apply here.
57
- // @ts-expect-error UNTIL https://github.com/Agoric/agoric-sdk/issues/8247
58
- const boardAux = E(chainStorage).makeChildNode(BOARD_AUX);
59
- const [id, displayInfo, allegedName] = await Promise.all([
60
- E(board).getId(brand),
61
- E(brand).getDisplayInfo(),
62
- E(brand).getAllegedName(),
63
- ]);
64
- const node = E(boardAux).makeChildNode(id);
65
- const aux = marshalData.toCapData(harden({ allegedName, displayInfo }));
66
- await E(node).setValue(JSON.stringify(aux));
67
- };
68
-
69
49
  const POOL_METRICS = 'poolMetrics';
70
50
 
71
51
  /**
@@ -79,7 +59,7 @@ const POOL_METRICS = 'poolMetrics';
79
59
  * }} FastUSDCCorePowers
80
60
  *
81
61
  * @typedef {StartedInstanceKitWithLabel & {
82
- * creatorFacet: Awaited<ReturnType<FastUsdcSF>>['creatorFacet'];
62
+ * creatorFacet: StartedInstanceKit<FastUsdcSF>['creatorFacet'];
83
63
  * privateArgs: StartParams<FastUsdcSF>['privateArgs'];
84
64
  * }} FastUSDCKit
85
65
  */
@@ -245,10 +225,10 @@ export const getManifestForFastUSDC = (
245
225
  board: true,
246
226
  },
247
227
  issuer: {
248
- produce: { FastLP: true }, // UNTIL #10432
228
+ produce: { FastLP: true },
249
229
  },
250
230
  brand: {
251
- produce: { FastLP: true }, // UNTIL #10432
231
+ produce: { FastLP: true },
252
232
  },
253
233
  instance: {
254
234
  produce: { fastUsdc: true },
@@ -34,7 +34,11 @@ export const makeProposalShapes = ({ PoolShares, USDC }) => {
34
34
  give: { PoolShare: makeNatAmountShape(PoolShares, 1n) },
35
35
  want: { USDC: makeNatAmountShape(USDC, 1n) },
36
36
  });
37
- return harden({ deposit, withdraw });
37
+ /** @type {TypedPattern<USDCProposalShapes['withdrawFees']>} */
38
+ const withdrawFees = M.splitRecord({
39
+ want: { USDC: makeNatAmountShape(USDC, 1n) },
40
+ });
41
+ return harden({ deposit, withdraw, withdrawFees });
38
42
  };
39
43
 
40
44
  /** @type {TypedPattern<FastUsdcTerms>} */
@@ -6,9 +6,7 @@ import { makeMarshal } from '@endo/marshal';
6
6
  const trace = makeTracer('FUCoreEval');
7
7
 
8
8
  /**
9
- * @import {Amount, Brand, DepositFacet, Issuer, Payment} from '@agoric/ertp';
10
- * @import {Passable} from '@endo/pass-style'
11
- * @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js'
9
+ * @import {Brand, DepositFacet} from '@agoric/ertp';
12
10
  * @import {FastUSDCKit} from '../start-fast-usdc.core.js'
13
11
  * @import {FeedPolicy} from '../types.js'
14
12
  */
@@ -54,3 +52,22 @@ export const inviteOracles = async (
54
52
  }),
55
53
  );
56
54
  };
55
+
56
+ const BOARD_AUX = 'boardAux';
57
+ /**
58
+ * @param {Brand} brand
59
+ * @param {Pick<BootstrapPowers['consume'], 'board' | 'chainStorage'>} powers
60
+ */
61
+ export const publishDisplayInfo = async (brand, { board, chainStorage }) => {
62
+ // chainStorage type includes undefined, which doesn't apply here.
63
+ // @ts-expect-error UNTIL https://github.com/Agoric/agoric-sdk/issues/8247
64
+ const boardAux = E(chainStorage).makeChildNode(BOARD_AUX);
65
+ const [id, displayInfo, allegedName] = await Promise.all([
66
+ E(board).getId(brand),
67
+ E(brand).getDisplayInfo(),
68
+ E(brand).getAllegedName(),
69
+ ]);
70
+ const node = E(boardAux).makeChildNode(id);
71
+ const aux = marshalData.toCapData(harden({ allegedName, displayInfo }));
72
+ await E(node).setValue(JSON.stringify(aux));
73
+ };