@agoric/fast-usdc 0.2.0-u19.2 → 0.2.0-u21.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/README.md CHANGED
@@ -1,101 +1,184 @@
1
1
  # Fast USDC
2
2
 
3
- Development package for the Fast USDC product.
4
- Here in agoric-sdk as a convenience for integration testing and iterating on the SDK affordances required for the product.
3
+ Development package for the Fast USDC product. Here in agoric-sdk as a
4
+ convenience for integration testing and iterating on the SDK affordances
5
+ required for the product.
5
6
 
6
7
  # Factoring
7
8
 
8
- This package is meant to contain all the code for the Fast USDC product. However there are some constraints:
9
+ This package is meant to contain all the code for the Fast USDC product.
10
+ However, there are some constraints:
9
11
 
10
- - a3p integration tests are in the `a3p-integration` top-level package, separate from this workspace
11
- - the proposal builders are in `@agoric/builders` to work with the a3p-integration `build:submissions` script
12
- - the RunUtils tests are in `@agoric/boot` to test running them atop a fresh bootstrapped environment
12
+ - a3p integration tests are in the `a3p-integration` top-level package, separate
13
+ from this workspace
14
+ - the proposal builders are in `@agoric/builders` to work with the
15
+ a3p-integration `build:submissions` script
16
+ - the RunUtils tests are in `@aglocal/boot` to test running them atop a fresh
17
+ bootstrapped environment
13
18
 
14
19
  Over time we can update our tooling to decouple this more from the `packages` directory.
15
20
 
16
- 1. Make a3p-integration `build:submissions` script work with arbitrary builder paths, allowing this to be above `@agoric/builders` in the package graph
17
- 2. Export bootstrap testing utilities from `@agoric/boot`, allowing this to be above `@agoric/boot` in the package graph
18
- 3. Update CI to support packages that aren't under `packages/`, eg. a top-level `dapps` directory
21
+ 1. Make a3p-integration `build:submissions` script work with arbitrary builder
22
+ paths, allowing this to be above `@agoric/builders` in the package graph
23
+ 2. Export bootstrap testing utilities from `@aglocal/boot`, allowing this to be
24
+ above `@aglocal/boot` in the package graph
25
+ 3. Update CI to support packages that aren't under `packages/`, eg. a top-level
26
+ `dapps` directory. `multichain-testing` does this now but not organized per contract.
19
27
  4. Move this package out of agoric-sdk
20
28
 
21
- # Transaction feed
22
-
23
- ## Oracles interface
24
-
25
- Oracles run off-chain and interact with the contract via an Agoric smart wallet bridge.
26
- ```mermaid
27
- sequenceDiagram
28
- title Becoming an oracle operator
29
- participant OW as Operator N<br/>Smart Wallet
30
- participant FUC as Fast USDC<br/>Contract Exo
31
- participant CE as Core Eval
32
-
33
- CE->>FUC: makeOperatorInvitation()
34
- FUC-->>CE: operatorInvitation
35
- CE->>+OW: deposit(operatorInvitation)
36
-
37
- Note left of FUC: Off-chain wallet accepts the operator invitation
38
-
39
- OW->>+FUC: offer(operatorInvitation)
40
- FUC-->>OW: operator invitationMakers: {SubmitEvidence}
41
-
42
- Note left of FUC: Off-chain watcher detects evidence
43
- OW->>+FUC: offer(SubmitEvidence, evidence)
44
- ```
29
+ # Funds flow
45
30
 
46
31
  ```mermaid
47
32
  sequenceDiagram
48
- title Receiving evidence
49
- participant W as Operator N<br/>Smart Wallet
50
- participant A as Operator N<br/>Admin Oexo
51
- participant TF as Transaction<br/>Feed
52
-
53
- W->>A: offer(SubmitEvidence, evidence)
54
-
55
- Note left of A: Once 3 operators push the same…
56
-
57
- A->>TF: notify(evidence)
33
+ actor User as User
34
+ participant NEA as User Wallet<br>[Browser]
35
+ participant ETH as CCTP Contract<br>[Ethereum]
36
+ participant NFA as Noble Forwarding Account<br/>[Noble]
37
+ participant NC as Noble Chain<br/>[Noble]
38
+ participant NAR as Noble-Agoric<br/>[IBC Relayer]
39
+ participant SA as Settlement Account<br/>[Agoric]
40
+ participant CFA as Contract Fee Account<br/>[Agoric]
41
+ participant DAR as Destination-Agoric<br/>[IBC Relayer]
42
+ participant EUD as End User Destination<br/>[Dest Chain]
43
+
44
+ autonumber
45
+ rect rgb(240, 248, 255)
46
+ User ->> NEA: Sign transaction<br/>(MintAmount, to NFA)
47
+ NEA ->> ETH: Submit USDC Burn Txn via CCTP
48
+ end
49
+ rect rgb(200, 255, 230)
50
+ FUC ->> P: Initiate PFM transfer(AdvanceAmount, EUD) from pool<br/>of Noble-Agoric tokens to EUD Chain
51
+ P ->> NC: PFM transfer(AdvanceAmount of Agoric USDC denom) to EUD
52
+ NC ->> EUD: deliver AdvanceAmount as final USDC denom
53
+ end
54
+ Note over User, EUD: User got their AdvanceAmountof IBC USDC<br/>UX COMPLETE
55
+ rect rgb(255, 200, 200)
56
+ Note over ETH, SA: Minting Process
57
+ Note over ETH: ~12 minutes for Ethereum finality
58
+ Note over NC: 1-6 minutes for CCTP<br/>to Mint on Noble
59
+ NC ->> NFA: Noble CCTP contract mints USDC<br/> into Noble Forwarding Address
60
+ NFA ->> NAR: Broadcast Forward MintAmount (as Agoric USDC Denom) to FU Account
61
+ NAR ->> SA: Relay
62
+ end
63
+ rect rgb(255, 245, 230)
64
+ Note over FUC, CFA: Settlement Process
65
+ alt Advance was started:
66
+ FUC ->> SA: Initiate transfers out of settlement
67
+ SA ->> P: Deposit the AdvanceAmount + PoolFee (= MintAmount - ContractFee)
68
+ SA ->> CFA: Deposit ContractFee
69
+ else Advance for matched transaction that has not yet started:
70
+ P ->> NC: PFM transfer(MintAmount of Agoric USDC denom) to EUD
71
+ NC ->> EUD: deliver MintAmount as final USDC denom
72
+ else Settlement for unknown transaction:
73
+ Note over SA: Leave funds in SettlementAccount.
74
+ Note over SA: Wait for observation from watcher
75
+ end
76
+ end
58
77
  ```
59
78
 
60
- # Status Manager
79
+ Not pictured:
80
+ - Circle Attestation Service
81
+ - CCTP Relayer
61
82
 
62
- ### Pending Advance State Diagram
83
+ "Noble Forwarding Account" is also owned by the CCTP Relayer as they actually register it
84
+ CCTP Relayer can be many parties, but only one when caller is specified
63
85
 
64
- *Transactions are qualified by the OCW and EventFeed before arriving to the Advancer.*
65
86
 
66
- ```mermaid
67
- stateDiagram-v2
68
- [*] --> Observed: observe()
69
- [*] --> Advancing: advancing()
70
-
71
- Advancing --> Advanced: advanceOutcome(...true)
72
- Advancing --> AdvanceFailed: advanceOutcome(...false)
73
-
74
- Observed --> [*]: dequeueStatus()
75
- Advanced --> [*]: dequeueStatus()
76
- AdvanceFailed --> [*]: dequeueStatus()
77
-
78
- note right of [*]
79
- After dequeueStatus():
80
- Transaction is removed
81
- from pendingTxs store.
82
- Settler will .disburse()
83
- or .forward()
84
- end note
85
- ```
86
-
87
- ### Complete state diagram (starting from Transaction Feed into Advancer)
87
+ # Transaction flow
88
88
 
89
89
  ```mermaid
90
- stateDiagram-v2
91
- Observed --> AdvanceSkipped : Risks identified
92
- Observed --> Advancing : No risks, can advance
93
- Observed --> Forwarding : No risks, Mint deposited before advance
94
- Forwarding --> Forwarded
95
- Advancing --> Advanced
96
- Advanced --> Disbursed
97
- AdvanceSkipped --> Forwarding : Mint deposited
98
- AdvanceFailed --> Forwarding : Mint deposited
99
- Advancing --> AdvanceFailed
100
- Forwarding --> ForwardFailed
90
+ %%{init: {
91
+ 'theme': 'base',
92
+ 'themeVariables': {
93
+ 'primaryColor': '#f0f8ff',
94
+ 'primaryTextColor': '#2c3e50',
95
+ 'primaryBorderColor': '#7fb2e6',
96
+ 'lineColor': '#7fb2e6',
97
+ 'secondaryColor': '#f6f8fa',
98
+ 'tertiaryColor': '#fff5e6'
99
+ }
100
+ }}%%
101
+ sequenceDiagram
102
+ title Fast USDC Transaction Process
103
+ autonumber
104
+ actor User
105
+ %% [Where it runs]
106
+ participant NEA as Noble Express app<br/>[Browser]
107
+ participant ETH as CCTP Contract<br/>[Ethereum]
108
+ participant NFA as Noble Forwarding Account<br/>[Noble]
109
+ participant NC as Noble Chain<br/>[Noble]
110
+ participant NAR as Noble-Agoric<br/>[Relayer]
111
+ participant OCW as Eth Watcher<br/>[Off-chain]
112
+ participant FUC as Fast USDC Contract<br/>[Agoric]
113
+ participant P as Pool<br/>[Agoric]
114
+ participant SA as Settlement Account<br/>[Agoric]
115
+ participant CFA as Contract Fee Account<br/>[Agoric]
116
+ participant DAR as Destination-Agoric<br/>[Relayer]
117
+ participant EUD as End User Destination<br/>[User]
118
+
119
+ %% Notation: --> for async, ->> for sync
120
+ rect rgb(240, 248, 255)
121
+ Note over User,OCW: User request
122
+ Note over NEA: App looks up fees and SettlementAccount address
123
+ User->>NEA: Input desired MintAmount and EUD
124
+ NEA->>User: Display fees and AdvanceAmount
125
+ Note over NEA: Calculate VirtualRecipient from (SettlementAccount, EUD)
126
+ Note over NEA: Calculate NFA address from (VirtualRecipient) using Signerless forwarding
127
+ %% Getting from here to the burn is mostly up to Noble
128
+ User->>NEA: Initiate transfer
129
+ NEA-->>NC: Register NFA
130
+ NEA->>User: Request signature
131
+ User->>NEA: Sign transaction<br/>(MintAmount, to NFA)
132
+ NEA->>ETH: Submit USDC Burn Txn via CCTP
133
+ Note over ETH: Burn succeeds,<br/>implying mint to NFA will happen
134
+ OCW->>ETH: Query CCTP transactions to Noble
135
+ ETH-->>OCW: 1 block confirmed
136
+ OCW->>NC: Look up recipient of NFA<br/>by account query
137
+ NC->>OCW: RPC replies with account including `recipient` (LCA+EUD)
138
+ end
139
+
140
+ Note over OCW: Continue if recipient is over the Noble-Agoric channel
141
+ rect rgb(200, 255, 230)
142
+ Note over NC,EUD: Advancement Process
143
+ Note over OCW: Log proof of each confirmation
144
+ Note over OCW,FUC: Provide info needed by policy to make a decision
145
+ OCW->>FUC: Notify of each confirmation<br/>(dest=agoric1 recipient, amount,<br/>metadata=transaction-nonce,chain,block,timestamp)
146
+ Note over FUC: MM's policy decides whether to advance (e.g. 2 confirmations from Ethereum, 5 from Polygon)
147
+ Note over FUC: Syslog with sufficient detail to debug
148
+ Note over FUC: calculate AdvanceAmount = (MintAmount – PoolFee - ContractFee)<br/>based on fee rates at this moment, and record for future lookup
149
+ FUC->>P: Initiate PFM transfer(AdvanceAmount, EUD) from pool<br/>of Noble-Agoric tokens to EUD Chain
150
+ P->>NC: PFM transfer(AdvanceAmount of Agoric USDC denom) to EUD
151
+ NC->>EUD: deliver AdvanceAmount as final USDC denom
152
+ %% TODO do need epsilon tolerance on MintAmount for if Noble takes a small cut of the minted amount
153
+ %% TODO map out the event handling for these states: START: only-observed,advance-started,received-minted-unobserved, END: done
154
+ Note over SA: Wake up the settlement process to handle observed (key=EUD,MintAmount)
155
+
156
+ end
157
+ Note over User,EUD: User got their AdvanceAmountof IBC USDC<br/>UX COMPLETE
158
+
159
+ rect rgb(255, 200, 200)
160
+ Note over ETH,SA: Minting Process
161
+ Note over ETH: ~12 minutes for Ethereum finality
162
+ Note over NC: 1-6 minutes for CCTP<br/>to Mint on Noble
163
+ NC->>NFA: Noble CCTP contract mints USDC<br/> into Noble Forwarding Address
164
+ NFA->>SA: Forward MintAmount (as Agoric USDC Denom) to FU Account
165
+ end
166
+
167
+ rect rgb(255, 245, 230)
168
+ Note over FUC,CFA: Settlement Process
169
+ Note over FUC,SA: Tap on account reads MintAmount,<br/>parses EUD from virtual address recipient<br/>and looks up AdvanceAmount,PoolFee,ContractFee.<br/>Matches against an unsettled transaction (by EUD and approx amount).
170
+ %% Treat starting the advance as an atomic action. Assume it will complete once started.
171
+ alt Advance was started:
172
+ FUC->>SA: Initiate transfers out of settlement
173
+ SA->>P: Deposit the AdvanceAmount + PoolFee (= MintAmount - ContractFee)
174
+ SA->>CFA: Deposit ContractFee
175
+ else Advance for matched transaction that has not yet started:
176
+ P->>NC: PFM transfer(MintAmount of Agoric USDC denom) to EUD
177
+ NC->>EUD: deliver MintAmount as final USDC denom
178
+ else Settlement for unknown transaction:
179
+ %% Have not received notification of this Amount,EUD from the watcher
180
+ Note over SA: Leave funds in SettlementAccount.
181
+ Note over SA: Wait for observation from watcher
182
+ end
183
+ end
101
184
  ```
package/package.json CHANGED
@@ -1,61 +1,52 @@
1
1
  {
2
2
  "name": "@agoric/fast-usdc",
3
- "version": "0.2.0-u19.2",
3
+ "version": "0.2.0-u21.0",
4
4
  "description": "CLI and library for Fast USDC product",
5
5
  "type": "module",
6
6
  "files": [
7
- "contract",
8
7
  "src",
9
8
  "tools"
10
9
  ],
11
10
  "main": "src/main.js",
12
- "bin": {
13
- "fast-usdc": "./src/cli/bin.js"
14
- },
11
+ "bin": "./src/cli/bin.js",
15
12
  "scripts": {
16
13
  "build": "exit 0",
17
14
  "test": "ava",
18
15
  "test:c8": "c8 --all $C8_OPTIONS ava",
19
16
  "test:xs": "exit 0",
20
17
  "lint-fix": "yarn lint:eslint --fix",
21
- "lint": "run-s --continue-on-error lint:*",
22
- "lint:types": "tsc",
23
- "lint:eslint": "eslint ."
18
+ "lint": "yarn run -T run-s --continue-on-error 'lint:*'",
19
+ "lint:eslint": "yarn run -T eslint .",
20
+ "lint:types": "yarn run -T tsc"
24
21
  },
25
22
  "devDependencies": {
26
- "@agoric/swingset-liveslots": "^0.10.3-u19.2",
27
- "@agoric/vats": "^0.16.0-u19.2",
28
- "@agoric/zone": "^0.3.0-u19.2",
29
23
  "@fast-check/ava": "^2.0.1",
30
24
  "ava": "^5.3.0",
31
- "c8": "^10.1.2",
32
- "execa": "9.1.0",
33
- "ts-blank-space": "^0.4.4"
25
+ "c8": "^10.1.3",
26
+ "nano-spawn": "^1.0.2",
27
+ "ts-blank-space": "^0.6.1"
34
28
  },
35
29
  "dependencies": {
36
- "@agoric/client-utils": "^0.2.0-u19.2",
37
- "@agoric/cosmic-proto": "^0.5.0-u19.2",
38
- "@agoric/ertp": "^0.16.3-u19.2",
39
- "@agoric/internal": "^0.4.0-u19.2",
40
- "@agoric/notifier": "^0.7.0-u19.2",
41
- "@agoric/orchestration": "^0.2.0-u19.2",
42
- "@agoric/store": "^0.9.3-u19.0",
43
- "@agoric/vat-data": "^0.5.3-u19.2",
44
- "@agoric/vow": "^0.2.0-u19.2",
45
- "@agoric/zoe": "^0.27.0-u19.2",
46
- "@cosmjs/proto-signing": "^0.32.4",
47
- "@cosmjs/stargate": "^0.32.4",
30
+ "@agoric/client-utils": "workspace:*",
31
+ "@agoric/cosmic-proto": "workspace:*",
32
+ "@agoric/ertp": "workspace:*",
33
+ "@agoric/internal": "workspace:*",
34
+ "@agoric/notifier": "workspace:*",
35
+ "@agoric/orchestration": "workspace:*",
36
+ "@agoric/zoe": "workspace:*",
37
+ "@cosmjs/proto-signing": "^0.33.0",
38
+ "@cosmjs/stargate": "^0.33.0",
48
39
  "@endo/base64": "^1.0.9",
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",
40
+ "@endo/common": "^1.2.10",
41
+ "@endo/errors": "^1.2.10",
42
+ "@endo/eventual-send": "^1.3.1",
43
+ "@endo/far": "^1.1.11",
44
+ "@endo/init": "^1.1.9",
45
+ "@endo/marshal": "^1.6.4",
46
+ "@endo/nat": "^5.1.0",
47
+ "@endo/pass-style": "^1.5.0",
48
+ "@endo/patterns": "^1.5.0",
49
+ "@endo/promise-kit": "^1.1.10",
59
50
  "@nick134-bit/noblejs": "0.0.2",
60
51
  "bech32": "^2.0.0",
61
52
  "commander": "^12.1.0",
@@ -82,5 +73,5 @@
82
73
  "publishConfig": {
83
74
  "access": "public"
84
75
  },
85
- "gitHead": "f0ae74b84cb6de3724bfdcd18b4bea7e8199dee1"
76
+ "gitHead": "e4dd46857133403d584bcf822a81817b355532f9"
86
77
  }
package/src/cli/cli.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  import { addConfigCommands } from './config-commands.js';
13
13
  import { addOperatorCommands } from './operator-commands.js';
14
14
  import * as configLib from './config.js';
15
- import transferLib from './transfer.js';
15
+ import * as transferLib from './transfer.js';
16
16
  import { makeFile } from './util/file.js';
17
17
  import { addLPCommands } from './lp-commands.js';
18
18
 
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.js' */
27
27
 
28
28
  export const init = async (
29
29
  /** @type {File} */ configFile,
@@ -18,7 +18,7 @@ import {
18
18
  floorDivideBy,
19
19
  multiplyBy,
20
20
  parseRatio,
21
- } from '@agoric/zoe/src/contractSupport/ratio.js';
21
+ } from '@agoric/ertp/src/ratio.js';
22
22
  import { InvalidArgumentError } from 'commander';
23
23
  import { outputActionAndHint } from './bridge-action.js';
24
24
  import { Offers } from '../clientSupport.js';
@@ -38,7 +38,7 @@ const parseDecimal = arg => {
38
38
 
39
39
  /**
40
40
  * @param {string} amountString
41
- * @param {Brand} usdc
41
+ * @param {Brand<'nat'>} usdc
42
42
  */
43
43
  const parseUSDCAmount = (amountString, usdc) => {
44
44
  const USDC_DECIMALS = 6;
@@ -3,7 +3,6 @@
3
3
  * @import {Command} from 'commander';
4
4
  * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
5
5
  * @import {ExecuteOfferAction} from '@agoric/smart-wallet/src/smartWallet.js';
6
- * @import {OperatorKit} from '../exos/operator-kit.js';
7
6
  */
8
7
 
9
8
  import {
@@ -13,7 +12,7 @@ import {
13
12
  import { mustMatch } from '@agoric/internal';
14
13
  import { Nat } from '@endo/nat';
15
14
  import { InvalidArgumentError } from 'commander';
16
- import { INVITATION_MAKERS_DESC } from '../exos/transaction-feed.js';
15
+ import { INVITATION_MAKERS_DESC } from '../operator-kit-interface.js';
17
16
  import { CctpTxEvidenceShape } from '../type-guards.js';
18
17
  import { outputActionAndHint } from './bridge-action.js';
19
18
 
@@ -128,9 +127,7 @@ export const addOperatorCommands = (
128
127
  invitationSpec: {
129
128
  source: 'continuing',
130
129
  previousOffer: previousOfferId,
131
- /** @type {string & keyof OperatorKit['invitationMakers'] } */
132
130
  invitationMakerName: 'SubmitEvidence',
133
- /** @type {Parameters<OperatorKit['invitationMakers']['SubmitEvidence']> } */
134
131
  invitationArgs: [evidence],
135
132
  },
136
133
  proposal: {},
@@ -16,12 +16,12 @@ import {
16
16
  } from './util/noble.js';
17
17
  import { queryUSDCBalance } from './util/bank.js';
18
18
 
19
- /** @import { File } from './util/file' */
19
+ /** @import { File } from './util/file.js' */
20
20
  /** @import { VStorage } from '@agoric/client-utils' */
21
21
  /** @import { SigningStargateClient } from '@cosmjs/stargate' */
22
22
  /** @import { JsonRpcProvider as ethProvider } from 'ethers' */
23
23
 
24
- const transfer = async (
24
+ export const transfer = async (
25
25
  /** @type {File} */ configFile,
26
26
  /** @type {string} */ amount,
27
27
  /** @type {string} */ EUD,
@@ -34,7 +34,7 @@ const transfer = async (
34
34
  setTimeout = globalThis.setTimeout,
35
35
  ) => {
36
36
  const execute = async (
37
- /** @type {import('./config').ConfigOpts} */ config,
37
+ /** @type {import('./config.js').ConfigOpts} */ config,
38
38
  ) => {
39
39
  const netConfig = await fetchEnvNetworkConfig({ env, fetch });
40
40
  vstorage ||= makeVStorage(
@@ -137,5 +137,3 @@ const transfer = async (
137
137
  }
138
138
  await execute(config);
139
139
  };
140
-
141
- export default { transfer };
@@ -4,9 +4,8 @@ export const queryFastUSDCLocalChainAccount = async (
4
4
  /** @type {VStorage} */ vstorage,
5
5
  out = console,
6
6
  ) => {
7
- const agoricAddr = await vstorage.readLatest(
8
- 'published.fastUsdc.settlementAccount',
9
- );
10
- out.log(`Got Fast USDC Local Chain Account ${agoricAddr}`);
11
- return agoricAddr;
7
+ const { value } = await vstorage.readLatest('published.fastUsdc');
8
+ const { settlementAccount } = JSON.parse(JSON.parse(value).values[0]);
9
+ out.log(`settlementAccount: ${settlementAccount}`);
10
+ return settlementAccount;
12
11
  };
package/src/constants.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Status values for FastUSDC.
2
+ * Status values for FastUSDC. Includes states for advancing and settling.
3
3
  *
4
4
  * @enum {(typeof TxStatus)[keyof typeof TxStatus]}
5
5
  */
@@ -16,6 +16,8 @@ export const TxStatus = /** @type {const} */ ({
16
16
  AdvanceSkipped: 'ADVANCE_SKIPPED',
17
17
  /** settlement for matching advance received and funds disbursed */
18
18
  Disbursed: 'DISBURSED',
19
+ /** No route, forward not attempted */
20
+ ForwardedSkipped: 'FORWARD_SKIPPED',
19
21
  /** fallback: do not collect fees */
20
22
  Forwarded: 'FORWARDED',
21
23
  /** failed to forward to EUD */
@@ -31,13 +33,11 @@ export const TerminalTxStatus = {
31
33
  };
32
34
 
33
35
  /**
34
- * Status values for the StatusManager.
36
+ * Status values for the StatusManager while an advance is being processed.
35
37
  *
36
38
  * @enum {(typeof PendingTxStatus)[keyof typeof PendingTxStatus]}
37
39
  */
38
40
  export const PendingTxStatus = /** @type {const} */ ({
39
- /** tx was observed but not advanced */
40
- Observed: 'OBSERVED',
41
41
  /** IBC transfer is initiated */
42
42
  Advancing: 'ADVANCING',
43
43
  /** IBC transfer failed (timed out) */
@@ -0,0 +1,29 @@
1
+ import { M } from '@endo/patterns';
2
+ import { CctpTxEvidenceShape, RiskAssessmentShape } from './type-guards.js';
3
+
4
+ /**
5
+ * @import {Zone} from '@agoric/zone';
6
+ * @import {CctpTxEvidence, RiskAssessment} from '@agoric/fast-usdc/src/types.js';
7
+ */
8
+
9
+ /** Name in the invitation purse (keyed also by this contract instance) */
10
+ export const INVITATION_MAKERS_DESC = 'oracle operator invitation';
11
+
12
+ export const OperatorKitI = {
13
+ admin: M.interface('Admin', {
14
+ disable: M.call().returns(),
15
+ }),
16
+
17
+ invitationMakers: M.interface('InvitationMakers', {
18
+ SubmitEvidence: M.call(CctpTxEvidenceShape)
19
+ .optional(RiskAssessmentShape)
20
+ .returns(M.promise()),
21
+ }),
22
+
23
+ operator: M.interface('Operator', {
24
+ submitEvidence: M.call(CctpTxEvidenceShape)
25
+ .optional(RiskAssessmentShape)
26
+ .returns(),
27
+ getStatus: M.call().returns(M.record()),
28
+ }),
29
+ };
@@ -4,16 +4,17 @@ import {
4
4
  makeRatio,
5
5
  makeRatioFromAmounts,
6
6
  multiplyBy,
7
- } from '@agoric/zoe/src/contractSupport/ratio.js';
7
+ } from '@agoric/ertp/src/ratio.js';
8
8
  import { Fail, q } from '@endo/errors';
9
9
 
10
10
  const { keys } = Object;
11
11
  const { add, isEmpty, isEqual, isGTE, make, makeEmpty, subtract } = AmountMath;
12
12
 
13
13
  /**
14
- * @import {Amount, Brand, DepositFacet, NatValue, Payment} from '@agoric/ertp';
15
- * @import {PoolStats} from './types';
16
- * @import {RepayAmountKWR} from './exos/liquidity-pool';
14
+ * @import {Amount, Brand, DepositFacet, NatValue, Payment, Ratio} from '@agoric/ertp';
15
+ * @import {Allocation} from '@agoric/zoe';
16
+ * @import {PoolStats} from './types.js';
17
+ * @import {RepayAmountKWR} from './utils/fees.js';
17
18
  */
18
19
 
19
20
  /**
@@ -201,35 +202,26 @@ export const borrowCalc = (
201
202
 
202
203
  /**
203
204
  * @param {ShareWorth} shareWorth
204
- * @param {Allocation} fromSeatAllocation
205
- * @param {RepayAmountKWR} amounts
205
+ * @param {RepayAmountKWR} split
206
206
  * @param {Amount<'nat'>} encumberedBalance aka 'outstanding borrows'
207
207
  * @param {PoolStats} poolStats
208
- * @throws {Error} if allocations do not match amounts or Principal exceeds encumberedBalance
208
+ * @throws {Error} if Principal exceeds encumberedBalance
209
209
  */
210
- export const repayCalc = (
211
- shareWorth,
212
- fromSeatAllocation,
213
- amounts,
214
- encumberedBalance,
215
- poolStats,
216
- ) => {
217
- (isEqual(fromSeatAllocation.Principal, amounts.Principal) &&
218
- isEqual(fromSeatAllocation.PoolFee, amounts.PoolFee) &&
219
- isEqual(fromSeatAllocation.ContractFee, amounts.ContractFee)) ||
220
- Fail`Cannot repay. From seat allocation ${q(fromSeatAllocation)} does not equal amounts ${q(amounts)}.`;
221
-
222
- isGTE(encumberedBalance, amounts.Principal) ||
223
- Fail`Cannot repay. Principal ${q(amounts.Principal)} exceeds encumberedBalance ${q(encumberedBalance)}.`;
210
+ export const repayCalc = (shareWorth, split, encumberedBalance, poolStats) => {
211
+ isGTE(encumberedBalance, split.Principal) ||
212
+ Fail`Cannot repay. Principal ${q(split.Principal)} exceeds encumberedBalance ${q(encumberedBalance)}.`;
224
213
 
225
214
  return harden({
226
- shareWorth: withFees(shareWorth, amounts.PoolFee),
227
- encumberedBalance: subtract(encumberedBalance, amounts.Principal),
215
+ shareWorth: withFees(shareWorth, split.PoolFee),
216
+ encumberedBalance: subtract(encumberedBalance, split.Principal),
228
217
  poolStats: {
229
218
  ...poolStats,
230
- totalRepays: add(poolStats.totalRepays, amounts.Principal),
231
- totalPoolFees: add(poolStats.totalPoolFees, amounts.PoolFee),
232
- totalContractFees: add(poolStats.totalContractFees, amounts.ContractFee),
219
+ totalRepays: add(poolStats.totalRepays, split.Principal),
220
+ totalPoolFees: add(poolStats.totalPoolFees, split.PoolFee),
221
+ totalContractFees: add(
222
+ add(poolStats.totalContractFees, split.ContractFee),
223
+ split.RelayFee,
224
+ ),
233
225
  },
234
226
  });
235
227
  };