@agoric/fast-usdc 0.2.0-upgrade-18a-dev-4ee0508.0 → 0.2.0-upgrade-19-dev-aa5fa27.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.2.0-upgrade-18a-dev-4ee0508.0+4ee0508",
3
+ "version": "0.2.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
4
4
  "description": "CLI and library for Fast USDC product",
5
5
  "type": "module",
6
6
  "files": [
@@ -8,6 +8,7 @@
8
8
  "src",
9
9
  "tools"
10
10
  ],
11
+ "main": "src/main.js",
11
12
  "bin": {
12
13
  "fast-usdc": "./src/cli/bin.js"
13
14
  },
@@ -22,9 +23,9 @@
22
23
  "lint:eslint": "eslint ."
23
24
  },
24
25
  "devDependencies": {
25
- "@agoric/swingset-liveslots": "0.10.3-upgrade-18a-dev-4ee0508.0+4ee0508",
26
- "@agoric/vats": "0.16.0-upgrade-18a-dev-4ee0508.0+4ee0508",
27
- "@agoric/zone": "0.3.0-upgrade-18a-dev-4ee0508.0+4ee0508",
26
+ "@agoric/swingset-liveslots": "0.10.3-upgrade-19-dev-aa5fa27.0+aa5fa27",
27
+ "@agoric/vats": "0.16.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
28
+ "@agoric/zone": "0.3.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
28
29
  "@fast-check/ava": "^2.0.1",
29
30
  "ava": "^5.3.0",
30
31
  "c8": "^10.1.2",
@@ -32,29 +33,29 @@
32
33
  "ts-blank-space": "^0.4.4"
33
34
  },
34
35
  "dependencies": {
35
- "@agoric/client-utils": "0.2.0-upgrade-18a-dev-4ee0508.0+4ee0508",
36
- "@agoric/cosmic-proto": "0.5.0-upgrade-18a-dev-4ee0508.0+4ee0508",
37
- "@agoric/ertp": "0.16.3-upgrade-18a-dev-4ee0508.0+4ee0508",
38
- "@agoric/internal": "0.4.0-upgrade-18a-dev-4ee0508.0+4ee0508",
39
- "@agoric/notifier": "0.7.0-upgrade-18a-dev-4ee0508.0+4ee0508",
40
- "@agoric/orchestration": "0.2.0-upgrade-18a-dev-4ee0508.0+4ee0508",
41
- "@agoric/store": "0.9.3-upgrade-18a-dev-4ee0508.0+4ee0508",
42
- "@agoric/vat-data": "0.5.3-upgrade-18a-dev-4ee0508.0+4ee0508",
43
- "@agoric/vow": "0.2.0-upgrade-18a-dev-4ee0508.0+4ee0508",
44
- "@agoric/zoe": "0.26.3-upgrade-18a-dev-4ee0508.0+4ee0508",
36
+ "@agoric/client-utils": "0.2.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
37
+ "@agoric/cosmic-proto": "0.5.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
38
+ "@agoric/ertp": "0.16.3-upgrade-19-dev-aa5fa27.0+aa5fa27",
39
+ "@agoric/internal": "0.4.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
40
+ "@agoric/notifier": "0.7.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
41
+ "@agoric/orchestration": "0.2.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
42
+ "@agoric/store": "0.9.3-upgrade-19-dev-aa5fa27.0+aa5fa27",
43
+ "@agoric/vat-data": "0.5.3-upgrade-19-dev-aa5fa27.0+aa5fa27",
44
+ "@agoric/vow": "0.2.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
45
+ "@agoric/zoe": "0.27.0-upgrade-19-dev-aa5fa27.0+aa5fa27",
45
46
  "@cosmjs/proto-signing": "^0.32.4",
46
47
  "@cosmjs/stargate": "^0.32.4",
47
48
  "@endo/base64": "^1.0.9",
48
- "@endo/common": "^1.2.8",
49
- "@endo/errors": "^1.2.8",
50
- "@endo/eventual-send": "^1.2.8",
51
- "@endo/far": "^1.1.9",
52
- "@endo/init": "^1.1.7",
53
- "@endo/marshal": "^1.6.2",
54
- "@endo/nat": "^5.0.13",
55
- "@endo/pass-style": "^1.4.7",
56
- "@endo/patterns": "^1.4.7",
57
- "@endo/promise-kit": "^1.1.8",
49
+ "@endo/common": "^1.2.9",
50
+ "@endo/errors": "^1.2.9",
51
+ "@endo/eventual-send": "^1.3.0",
52
+ "@endo/far": "^1.1.10",
53
+ "@endo/init": "^1.1.8",
54
+ "@endo/marshal": "^1.6.3",
55
+ "@endo/nat": "^5.0.14",
56
+ "@endo/pass-style": "^1.4.8",
57
+ "@endo/patterns": "^1.4.8",
58
+ "@endo/promise-kit": "^1.1.9",
58
59
  "@nick134-bit/noblejs": "0.0.2",
59
60
  "bech32": "^2.0.0",
60
61
  "commander": "^12.1.0",
@@ -81,5 +82,5 @@
81
82
  "publishConfig": {
82
83
  "access": "public"
83
84
  },
84
- "gitHead": "4ee05088e5ada989a866a11ff65838d395505ce6"
85
+ "gitHead": "aa5fa276b7fb72283263b4ab05d7dec3807fa50c"
85
86
  }
@@ -0,0 +1,63 @@
1
+ import { makeTracer } from '@agoric/internal';
2
+ import { inviteOracles } from './utils/core-eval.js';
3
+
4
+ /**
5
+ * @import {ManifestBundleRef} from '@agoric/deploy-script-support/src/externalTypes.js'
6
+ * @import {BootstrapManifest} from '@agoric/vats/src/core/lib-boot.js'
7
+ * @import {LegibleCapData} from './utils/config-marshal.js'
8
+ * @import {FastUSDCConfig} from './types.js'
9
+ * @import {FastUSDCCorePowers, FastUSDCKit} from './start-fast-usdc.core.js';
10
+ */
11
+
12
+ const trace = makeTracer('FUSD-AddOperators', true);
13
+
14
+ /**
15
+ * @throws if oracle smart wallets are not yet provisioned
16
+ *
17
+ * @param {BootstrapPowers & FastUSDCCorePowers } powers
18
+ * @param {{ options: LegibleCapData<FastUSDCConfig> }} config
19
+ */
20
+ export const addOperators = async (
21
+ { consume: { namesByAddress, fastUsdcKit } },
22
+ config,
23
+ ) => {
24
+ trace(addOperators.name);
25
+
26
+ const kit = await fastUsdcKit;
27
+
28
+ const { creatorFacet } = kit;
29
+
30
+ trace(config);
31
+
32
+ // @ts-expect-error XXX LegibleCapData typedef
33
+ const { oracles } = config.options.structure;
34
+
35
+ await inviteOracles({ creatorFacet, namesByAddress }, oracles);
36
+ };
37
+ harden(addOperators);
38
+
39
+ /**
40
+ * @param {{
41
+ * restoreRef: (b: ERef<ManifestBundleRef>) => Promise<Installation>;
42
+ * }} utils
43
+ * @param {{
44
+ * options: LegibleCapData<FastUSDCConfig>;
45
+ * }} param1
46
+ */
47
+ export const getManifestForAddOperators = ({ restoreRef: _ }, { options }) => {
48
+ return {
49
+ /** @type {BootstrapManifest} */
50
+ manifest: {
51
+ [addOperators.name]: {
52
+ consume: {
53
+ fastUsdcKit: true,
54
+
55
+ // widely shared: name services
56
+ agoricNames: true,
57
+ namesByAddress: true,
58
+ },
59
+ },
60
+ },
61
+ options,
62
+ };
63
+ };
package/src/cli/cli.js CHANGED
@@ -13,7 +13,7 @@ import { addConfigCommands } from './config-commands.js';
13
13
  import { addOperatorCommands } from './operator-commands.js';
14
14
  import * as configLib from './config.js';
15
15
  import transferLib from './transfer.js';
16
- import { makeFile } from '../util/file.js';
16
+ import { makeFile } from './util/file.js';
17
17
  import { addLPCommands } from './lp-commands.js';
18
18
 
19
19
  const packageJson = JSON.parse(
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @import {Command} from 'commander';
3
- * @import {File} from '../util/file.js';
3
+ * @import {File} from './util/file.js';
4
4
  * @import * as ConfigHelpers from './config.js';
5
5
  */
6
6
  /**
package/src/cli/config.js CHANGED
@@ -23,7 +23,7 @@ import { stdin as input, stdout as output } from 'node:process';
23
23
  }} ConfigOpts
24
24
  */
25
25
 
26
- /** @import { File } from '../util/file' */
26
+ /** @import { File } from './util/file' */
27
27
 
28
28
  export const init = async (
29
29
  /** @type {File} */ configFile,
@@ -1,6 +1,7 @@
1
1
  /* eslint-env node */
2
2
  /**
3
3
  * @import {Command} from 'commander';
4
+ * @import {Amount, Brand} from '@agoric/ertp';
4
5
  * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
5
6
  * @import {ExecuteOfferAction} from '@agoric/smart-wallet/src/smartWallet.js';
6
7
  * @import {USDCProposalShapes} from '../pool-share-math.js';
@@ -14,11 +15,13 @@ import { AmountMath } from '@agoric/ertp';
14
15
  import {
15
16
  assertParsableNumber,
16
17
  ceilDivideBy,
18
+ floorDivideBy,
17
19
  multiplyBy,
18
20
  parseRatio,
19
21
  } from '@agoric/zoe/src/contractSupport/ratio.js';
20
22
  import { InvalidArgumentError } from 'commander';
21
23
  import { outputActionAndHint } from './bridge-action.js';
24
+ import { Offers } from '../clientSupport.js';
22
25
 
23
26
  export const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
24
27
 
@@ -81,30 +84,27 @@ export const addLPCommands = (
81
84
  .action(async opts => {
82
85
  swkP ||= loadSwk();
83
86
  const swk = await swkP;
87
+
84
88
  /** @type {Brand<'nat'>} */
85
89
  // @ts-expect-error it doesnt recognize usdc as a Brand type
86
90
  const usdc = swk.agoricNames.brand.USDC;
87
91
  assert(usdc, 'USDC brand not in agoricNames');
88
92
 
93
+ /** @type {Brand<'nat'>} */
94
+ // @ts-expect-error it doesnt recognize FastLP as a Brand type
95
+ const poolShare = swk.agoricNames.brand.FastLP;
96
+ assert(poolShare, 'FastLP brand not in agoricNames');
97
+
89
98
  const usdcAmount = parseUSDCAmount(opts.amount, usdc);
90
99
 
91
- /** @type {USDCProposalShapes['deposit']} */
92
- const proposal = {
93
- give: {
94
- USDC: usdcAmount,
95
- },
96
- };
100
+ const metrics = await swk.readPublished('fastUsdc.poolMetrics');
101
+ const fastLPAmount = floorDivideBy(usdcAmount, metrics.shareWorth);
97
102
 
98
- /** @type {OfferSpec} */
99
- const offer = {
100
- id: opts.offerId,
101
- invitationSpec: {
102
- source: 'agoricContract',
103
- instancePath: ['fastUsdc'],
104
- callPipe: [['makeDepositInvitation', []]],
105
- },
106
- proposal,
107
- };
103
+ const offer = Offers.fastUsdc.Deposit(swk.agoricNames, {
104
+ offerId: opts.offerId,
105
+ fastLPAmount: fastLPAmount.value,
106
+ usdcAmount: usdcAmount.value,
107
+ });
108
108
 
109
109
  /** @type {ExecuteOfferAction} */
110
110
  const bridgeAction = {
@@ -125,7 +125,6 @@ export const addLPCommands = (
125
125
  .requiredOption('--amount <number>', 'USDC amount', parseDecimal)
126
126
  .option('--offerId <string>', 'Offer id', String, `lpWithdraw-${now()}`)
127
127
  .action(async opts => {
128
- swkP ||= loadSwk();
129
128
  swkP ||= loadSwk();
130
129
  const swk = await swkP;
131
130
 
@@ -141,31 +140,14 @@ export const addLPCommands = (
141
140
 
142
141
  const usdcAmount = parseUSDCAmount(opts.amount, usdc);
143
142
 
144
- /** @type {import('../types.js').PoolMetrics} */
145
- // @ts-expect-error it treats this as "unknown"
146
143
  const metrics = await swk.readPublished('fastUsdc.poolMetrics');
147
144
  const fastLPAmount = ceilDivideBy(usdcAmount, metrics.shareWorth);
148
145
 
149
- /** @type {USDCProposalShapes['withdraw']} */
150
- const proposal = {
151
- give: {
152
- PoolShare: fastLPAmount,
153
- },
154
- want: {
155
- USDC: usdcAmount,
156
- },
157
- };
158
-
159
- /** @type {OfferSpec} */
160
- const offer = {
161
- id: opts.offerId,
162
- invitationSpec: {
163
- source: 'agoricContract',
164
- instancePath: ['fastUsdc'],
165
- callPipe: [['makeWithdrawInvitation', []]],
166
- },
167
- proposal,
168
- };
146
+ const offer = Offers.fastUsdc.Withdraw(swk.agoricNames, {
147
+ offerId: opts.offerId,
148
+ fastLPAmount: fastLPAmount.value,
149
+ usdcAmount: usdcAmount.value,
150
+ });
169
151
 
170
152
  outputActionAndHint(
171
153
  { method: 'executeOffer', offer },
@@ -96,6 +96,7 @@ export const addOperatorCommands = (
96
96
  .requiredOption('--recipientAddress <string>', 'bech32 address', String)
97
97
  .requiredOption('--blockHash <0xhex>', 'hex hash', parseHex)
98
98
  .requiredOption('--blockNumber <number>', 'number', parseNat)
99
+ .requiredOption('--blockTimestamp <number>', 'number', parseNat)
99
100
  .requiredOption('--chainId <string>', 'chain id', Number)
100
101
  .requiredOption('--amount <number>', 'number', parseNat)
101
102
  .requiredOption('--forwardingAddress <string>', 'bech32 address', String)
@@ -7,16 +7,16 @@ import {
7
7
  pickEndpoint,
8
8
  } from '@agoric/client-utils';
9
9
  import { encodeAddressHook } from '@agoric/cosmic-proto/address-hooks.js';
10
- import { queryFastUSDCLocalChainAccount } from '../util/agoric.js';
11
- import { depositForBurn, makeProvider } from '../util/cctp.js';
10
+ import { queryFastUSDCLocalChainAccount } from './util/agoric.js';
11
+ import { depositForBurn, makeProvider } from './util/cctp.js';
12
12
  import {
13
13
  makeSigner,
14
14
  queryForwardingAccount,
15
15
  registerFwdAccount,
16
- } from '../util/noble.js';
17
- import { queryUSDCBalance } from '../util/bank.js';
16
+ } from './util/noble.js';
17
+ import { queryUSDCBalance } from './util/bank.js';
18
18
 
19
- /** @import { File } from '../util/file' */
19
+ /** @import { File } from './util/file' */
20
20
  /** @import { VStorage } from '@agoric/client-utils' */
21
21
  /** @import { SigningStargateClient } from '@cosmjs/stargate' */
22
22
  /** @import { JsonRpcProvider as ethProvider } from 'ethers' */
@@ -0,0 +1,98 @@
1
+ // @ts-check
2
+ import { assertAllDefined } from '@agoric/internal';
3
+
4
+ /**
5
+ * @import {USDCProposalShapes} from './pool-share-math.js';
6
+ */
7
+
8
+ /**
9
+ * @param {Pick<
10
+ * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
11
+ * 'brand'
12
+ * >} agoricNames
13
+ * @param {object} opts
14
+ * @param {string} opts.offerId
15
+ * @param {bigint} opts.fastLPAmount
16
+ * @param {bigint} opts.usdcAmount
17
+ * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec & {proposal: USDCProposalShapes['deposit']}}
18
+ */
19
+ const makeDepositOffer = ({ brand }, { offerId, fastLPAmount, usdcAmount }) => {
20
+ assertAllDefined({ offerId, fastLPAmount, usdcAmount });
21
+
22
+ return {
23
+ id: offerId,
24
+ invitationSpec: {
25
+ source: 'agoricContract',
26
+ instancePath: ['fastUsdc'],
27
+ callPipe: [['makeDepositInvitation']],
28
+ },
29
+ /** @type {USDCProposalShapes['deposit']} */
30
+ // @ts-expect-error https://github.com/Agoric/agoric-sdk/issues/10491
31
+ proposal: {
32
+ give: {
33
+ USDC: {
34
+ brand: brand.USDC,
35
+ value: usdcAmount,
36
+ },
37
+ },
38
+ want: {
39
+ PoolShare: {
40
+ brand: brand.FastLP,
41
+ value: fastLPAmount,
42
+ },
43
+ },
44
+ },
45
+ };
46
+ };
47
+
48
+ /**
49
+ * @param {Pick<
50
+ * import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
51
+ * 'brand'
52
+ * >} agoricNames
53
+ * @param {object} opts
54
+ * @param {string} opts.offerId
55
+ * @param {bigint} opts.fastLPAmount
56
+ * @param {bigint} opts.usdcAmount
57
+ * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
58
+ */
59
+ const makeWithdrawOffer = (
60
+ { brand },
61
+ { offerId, fastLPAmount, usdcAmount },
62
+ ) => ({
63
+ id: offerId,
64
+ invitationSpec: {
65
+ source: 'agoricContract',
66
+ instancePath: ['fastUsdc'],
67
+ callPipe: [['makeWithdrawInvitation']],
68
+ },
69
+ proposal: {
70
+ give: {
71
+ PoolShare: {
72
+ // @ts-expect-error https://github.com/Agoric/agoric-sdk/issues/10491
73
+ brand: brand.FastLP,
74
+ value: fastLPAmount,
75
+ },
76
+ },
77
+ want: {
78
+ USDC: {
79
+ // @ts-expect-error https://github.com/Agoric/agoric-sdk/issues/10491
80
+ brand: brand.USDC,
81
+ value: usdcAmount,
82
+ },
83
+ },
84
+ },
85
+ });
86
+
87
+ /**
88
+ * @satisfies {Record<
89
+ * string,
90
+ * Record<string, import('@agoric/smart-wallet/src/types.js').OfferMaker>
91
+ * >}
92
+ */
93
+ export const Offers = {
94
+ fastUsdc: {
95
+ Deposit: makeDepositOffer,
96
+ Withdraw: makeWithdrawOffer,
97
+ },
98
+ };
@@ -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
+ };