@agoric/fast-usdc 0.1.1-dev-1f25ee2.0 → 0.1.1-dev-9cb1472.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
@@ -88,12 +88,14 @@ stateDiagram-v2
88
88
 
89
89
  ```mermaid
90
90
  stateDiagram-v2
91
- Observed --> Advancing
92
- Observed --> Forwarding:Minted
91
+ Observed --> AdvanceSkipped : Risks identified
92
+ Observed --> Advancing : No risks, can advance
93
+ Observed --> Forwarding : No risks, Mint deposited before advance
93
94
  Forwarding --> Forwarded
94
95
  Advancing --> Advanced
95
96
  Advanced --> Disbursed
96
- AdvanceFailed --> Forwarding
97
+ AdvanceSkipped --> Forwarding : Mint deposited
98
+ AdvanceFailed --> Forwarding : Mint deposited
97
99
  Advancing --> AdvanceFailed
98
100
  Forwarding --> ForwardFailed
99
101
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/fast-usdc",
3
- "version": "0.1.1-dev-1f25ee2.0+1f25ee2",
3
+ "version": "0.1.1-dev-9cb1472.0+9cb1472",
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-1f25ee2.0+1f25ee2",
26
- "@agoric/vats": "0.15.2-dev-1f25ee2.0+1f25ee2",
27
- "@agoric/zone": "0.2.3-dev-1f25ee2.0+1f25ee2",
25
+ "@agoric/swingset-liveslots": "0.10.3-dev-9cb1472.0+9cb1472",
26
+ "@agoric/vats": "0.15.2-dev-9cb1472.0+9cb1472",
27
+ "@agoric/zone": "0.2.3-dev-9cb1472.0+9cb1472",
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-1f25ee2.0+1f25ee2",
36
- "@agoric/cosmic-proto": "0.4.1-dev-1f25ee2.0+1f25ee2",
37
- "@agoric/ertp": "0.16.3-dev-1f25ee2.0+1f25ee2",
38
- "@agoric/internal": "0.3.3-dev-1f25ee2.0+1f25ee2",
39
- "@agoric/notifier": "0.6.3-dev-1f25ee2.0+1f25ee2",
40
- "@agoric/orchestration": "0.1.1-dev-1f25ee2.0+1f25ee2",
41
- "@agoric/store": "0.9.3-dev-1f25ee2.0+1f25ee2",
42
- "@agoric/vat-data": "0.5.3-dev-1f25ee2.0+1f25ee2",
43
- "@agoric/vow": "0.1.1-dev-1f25ee2.0+1f25ee2",
44
- "@agoric/zoe": "0.26.3-dev-1f25ee2.0+1f25ee2",
35
+ "@agoric/client-utils": "0.1.1-dev-9cb1472.0+9cb1472",
36
+ "@agoric/cosmic-proto": "0.4.1-dev-9cb1472.0+9cb1472",
37
+ "@agoric/ertp": "0.16.3-dev-9cb1472.0+9cb1472",
38
+ "@agoric/internal": "0.3.3-dev-9cb1472.0+9cb1472",
39
+ "@agoric/notifier": "0.6.3-dev-9cb1472.0+9cb1472",
40
+ "@agoric/orchestration": "0.1.1-dev-9cb1472.0+9cb1472",
41
+ "@agoric/store": "0.9.3-dev-9cb1472.0+9cb1472",
42
+ "@agoric/vat-data": "0.5.3-dev-9cb1472.0+9cb1472",
43
+ "@agoric/vow": "0.1.1-dev-9cb1472.0+9cb1472",
44
+ "@agoric/zoe": "0.26.3-dev-9cb1472.0+9cb1472",
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": "1f25ee2ec66788523594e25f020ccf3b6103d259"
84
+ "gitHead": "9cb147227644fb4e8ca5dc7e5a2f6eae0a9f8251"
85
85
  }
package/src/constants.js CHANGED
@@ -12,6 +12,8 @@ export const TxStatus = /** @type {const} */ ({
12
12
  Advanced: 'ADVANCED',
13
13
  /** IBC transfer failed (timed out) */
14
14
  AdvanceFailed: 'ADVANCE_FAILED',
15
+ /** Advance skipped and waiting for forward */
16
+ AdvanceSkipped: 'ADVANCE_SKIPPED',
15
17
  /** settlement for matching advance received and funds disbursed */
16
18
  Disbursed: 'DISBURSED',
17
19
  /** fallback: do not collect fees */
@@ -42,5 +44,7 @@ export const PendingTxStatus = /** @type {const} */ ({
42
44
  AdvanceFailed: 'ADVANCE_FAILED',
43
45
  /** IBC transfer is complete */
44
46
  Advanced: 'ADVANCED',
47
+ /** Advance skipped and waiting for forward */
48
+ AdvanceSkipped: 'ADVANCE_SKIPPED',
45
49
  });
46
50
  harden(PendingTxStatus);
@@ -8,9 +8,9 @@ import { E } from '@endo/far';
8
8
  import { M, mustMatch } from '@endo/patterns';
9
9
  import { Fail, q } from '@endo/errors';
10
10
  import {
11
- CctpTxEvidenceShape,
12
11
  AddressHookShape,
13
12
  EvmHashShape,
13
+ EvidenceWithRiskShape,
14
14
  } from '../type-guards.js';
15
15
  import { makeFeeTools } from '../utils/fees.js';
16
16
 
@@ -22,7 +22,7 @@ import { makeFeeTools } from '../utils/fees.js';
22
22
  * @import {ZoeTools} from '@agoric/orchestration/src/utils/zoe-tools.js';
23
23
  * @import {VowTools} from '@agoric/vow';
24
24
  * @import {Zone} from '@agoric/zone';
25
- * @import {CctpTxEvidence, AddressHook, EvmHash, FeeConfig, LogFn, NobleAddress} from '../types.js';
25
+ * @import {CctpTxEvidence, AddressHook, EvmHash, FeeConfig, LogFn, NobleAddress, EvidenceWithRisk} from '../types.js';
26
26
  * @import {StatusManager} from './status-manager.js';
27
27
  * @import {LiquidityPoolKit} from './liquidity-pool.js';
28
28
  */
@@ -55,7 +55,7 @@ const AdvancerVowCtxShape = M.splitRecord(
55
55
  /** type guards internal to the AdvancerKit */
56
56
  const AdvancerKitI = harden({
57
57
  advancer: M.interface('AdvancerI', {
58
- handleTransactionEvent: M.callWhen(CctpTxEvidenceShape).returns(),
58
+ handleTransactionEvent: M.callWhen(EvidenceWithRiskShape).returns(),
59
59
  setIntermediateRecipient: M.call(ChainAddressShape).returns(),
60
60
  }),
61
61
  depositHandler: M.interface('DepositHandlerI', {
@@ -137,9 +137,9 @@ export const prepareAdvancerKit = (
137
137
  * `StatusManager` - so we don't need to concern ourselves with
138
138
  * preserving the vow chain for callers.
139
139
  *
140
- * @param {CctpTxEvidence} evidence
140
+ * @param {EvidenceWithRisk} evidenceWithRisk
141
141
  */
142
- async handleTransactionEvent(evidence) {
142
+ async handleTransactionEvent({ evidence, risk }) {
143
143
  await null;
144
144
  try {
145
145
  if (statusManager.hasBeenObserved(evidence)) {
@@ -147,6 +147,12 @@ export const prepareAdvancerKit = (
147
147
  return;
148
148
  }
149
149
 
150
+ if (risk.risksIdentified?.length) {
151
+ log('risks identified, skipping advance');
152
+ statusManager.skipAdvance(evidence, risk.risksIdentified);
153
+ return;
154
+ }
155
+
150
156
  const { borrowerFacet, poolAccount, settlementAddress } =
151
157
  this.state;
152
158
  const { recipientAddress } = evidence.aux;
@@ -1,18 +1,18 @@
1
1
  import { makeTracer } from '@agoric/internal';
2
2
  import { Fail } from '@endo/errors';
3
3
  import { M } from '@endo/patterns';
4
- import { CctpTxEvidenceShape } from '../type-guards.js';
4
+ import { CctpTxEvidenceShape, RiskAssessmentShape } from '../type-guards.js';
5
5
 
6
6
  const trace = makeTracer('TxOperator');
7
7
 
8
8
  /**
9
9
  * @import {Zone} from '@agoric/zone';
10
- * @import {CctpTxEvidence} from '../types.js';
10
+ * @import {CctpTxEvidence, RiskAssessment} from '../types.js';
11
11
  */
12
12
 
13
13
  /**
14
14
  * @typedef {object} OperatorPowers
15
- * @property {(evidence: CctpTxEvidence, operatorId: string) => void} attest
15
+ * @property {(evidence: CctpTxEvidence, riskAssessment: RiskAssessment, operatorId: string) => void} attest
16
16
  */
17
17
 
18
18
  /**
@@ -31,11 +31,15 @@ const OperatorKitI = {
31
31
  }),
32
32
 
33
33
  invitationMakers: M.interface('InvitationMakers', {
34
- SubmitEvidence: M.call(CctpTxEvidenceShape).returns(M.promise()),
34
+ SubmitEvidence: M.call(CctpTxEvidenceShape)
35
+ .optional(RiskAssessmentShape)
36
+ .returns(M.promise()),
35
37
  }),
36
38
 
37
39
  operator: M.interface('Operator', {
38
- submitEvidence: M.call(CctpTxEvidenceShape).returns(),
40
+ submitEvidence: M.call(CctpTxEvidenceShape)
41
+ .optional(RiskAssessmentShape)
42
+ .returns(),
39
43
  getStatus: M.call().returns(M.record()),
40
44
  }),
41
45
  };
@@ -81,13 +85,14 @@ export const prepareOperatorKit = (zone, staticPowers) =>
81
85
  * fluxAggregator contract used for price oracles.
82
86
  *
83
87
  * @param {CctpTxEvidence} evidence
88
+ * @param {RiskAssessment} [riskAssessment]
84
89
  * @returns {Promise<Invitation>}
85
90
  */
86
- async SubmitEvidence(evidence) {
91
+ async SubmitEvidence(evidence, riskAssessment) {
87
92
  const { operator } = this.facets;
88
93
  // TODO(bootstrap integration): cause this call to throw and confirm that it
89
94
  // shows up in the the smart-wallet UpdateRecord `error` property
90
- operator.submitEvidence(evidence);
95
+ operator.submitEvidence(evidence, riskAssessment);
91
96
  return staticPowers.makeInertInvitation(
92
97
  'evidence was pushed in the invitation maker call',
93
98
  );
@@ -98,12 +103,13 @@ export const prepareOperatorKit = (zone, staticPowers) =>
98
103
  * submit evidence from this operator
99
104
  *
100
105
  * @param {CctpTxEvidence} evidence
106
+ * @param {RiskAssessment} [riskAssessment]
101
107
  * @returns {void}
102
108
  */
103
- submitEvidence(evidence) {
109
+ submitEvidence(evidence, riskAssessment = {}) {
104
110
  const { state } = this;
105
111
  !state.disabled || Fail`submitEvidence for disabled operator`;
106
- state.powers.attest(evidence, state.operatorId);
112
+ state.powers.attest(evidence, riskAssessment, state.operatorId);
107
113
  },
108
114
  /** @returns {OperatorStatus} */
109
115
  getStatus() {
@@ -181,6 +181,7 @@ export const prepareSettler = (
181
181
  return;
182
182
 
183
183
  case PendingTxStatus.Observed:
184
+ case PendingTxStatus.AdvanceSkipped:
184
185
  case PendingTxStatus.AdvanceFailed:
185
186
  return self.forward(found.txHash, nfa, amount, EUD);
186
187
 
@@ -14,7 +14,7 @@ import {
14
14
  /**
15
15
  * @import {MapStore, SetStore} from '@agoric/store';
16
16
  * @import {Zone} from '@agoric/zone';
17
- * @import {CctpTxEvidence, NobleAddress, PendingTx, EvmHash, LogFn, TransactionRecord} from '../types.js';
17
+ * @import {CctpTxEvidence, NobleAddress, PendingTx, EvmHash, LogFn, TransactionRecord, EvidenceWithRisk, RiskAssessment} from '../types.js';
18
18
  */
19
19
 
20
20
  /**
@@ -146,8 +146,9 @@ export const prepareStatusManager = (
146
146
  *
147
147
  * @param {CctpTxEvidence} evidence
148
148
  * @param {PendingTxStatus} status
149
+ * @param {string[]} [risksIdentified]
149
150
  */
150
- const initPendingTx = (evidence, status) => {
151
+ const initPendingTx = (evidence, status, risksIdentified) => {
151
152
  const { txHash } = evidence;
152
153
  if (seenTxs.has(txHash)) {
153
154
  throw makeError(`Transaction already seen: ${q(txHash)}`);
@@ -160,7 +161,9 @@ export const prepareStatusManager = (
160
161
  harden({ ...evidence, status }),
161
162
  );
162
163
  publishEvidence(txHash, evidence);
163
- if (status !== PendingTxStatus.Observed) {
164
+ if (status === PendingTxStatus.AdvanceSkipped) {
165
+ void publishTxnRecord(txHash, harden({ status, risksIdentified }));
166
+ } else if (status !== PendingTxStatus.Observed) {
164
167
  // publishEvidence publishes Observed
165
168
  void publishTxnRecord(txHash, harden({ status }));
166
169
  }
@@ -194,6 +197,9 @@ export const prepareStatusManager = (
194
197
  // TODO: naming scheme for transition events
195
198
  advance: M.call(CctpTxEvidenceShape).returns(M.undefined()),
196
199
  advanceOutcome: M.call(M.string(), M.nat(), M.boolean()).returns(),
200
+ skipAdvance: M.call(CctpTxEvidenceShape, M.arrayOf(M.string())).returns(
201
+ M.undefined(),
202
+ ),
197
203
  observe: M.call(CctpTxEvidenceShape).returns(M.undefined()),
198
204
  hasBeenObserved: M.call(CctpTxEvidenceShape).returns(M.boolean()),
199
205
  deleteCompletedTxs: M.call().returns(M.undefined()),
@@ -203,6 +209,7 @@ export const prepareStatusManager = (
203
209
  txHash: EvmHashShape,
204
210
  status: M.or(
205
211
  PendingTxStatus.Advanced,
212
+ PendingTxStatus.AdvanceSkipped,
206
213
  PendingTxStatus.AdvanceFailed,
207
214
  PendingTxStatus.Observed,
208
215
  ),
@@ -224,7 +231,8 @@ export const prepareStatusManager = (
224
231
  /**
225
232
  * Add a new transaction with ADVANCING status
226
233
  *
227
- * NB: this acts like observe() but skips recording the OBSERVED state
234
+ * NB: this acts like observe() but subsequently records an ADVANCING
235
+ * state
228
236
  *
229
237
  * @param {CctpTxEvidence} evidence
230
238
  */
@@ -232,6 +240,23 @@ export const prepareStatusManager = (
232
240
  initPendingTx(evidence, PendingTxStatus.Advancing);
233
241
  },
234
242
 
243
+ /**
244
+ * Add a new transaction with ADVANCE_SKIPPED status
245
+ *
246
+ * NB: this acts like observe() but subsequently records an
247
+ * ADVANCE_SKIPPED state along with risks identified
248
+ *
249
+ * @param {CctpTxEvidence} evidence
250
+ * @param {string[]} risksIdentified
251
+ */
252
+ skipAdvance(evidence, risksIdentified) {
253
+ initPendingTx(
254
+ evidence,
255
+ PendingTxStatus.AdvanceSkipped,
256
+ risksIdentified,
257
+ );
258
+ },
259
+
235
260
  /**
236
261
  * Record result of ADVANCING
237
262
  *
@@ -2,14 +2,15 @@ import { makeTracer } from '@agoric/internal';
2
2
  import { prepareDurablePublishKit } from '@agoric/notifier';
3
3
  import { keyEQ, M } from '@endo/patterns';
4
4
  import { Fail } from '@endo/errors';
5
- import { CctpTxEvidenceShape } from '../type-guards.js';
5
+ import { CctpTxEvidenceShape, RiskAssessmentShape } from '../type-guards.js';
6
6
  import { defineInertInvitation } from '../utils/zoe.js';
7
7
  import { prepareOperatorKit } from './operator-kit.js';
8
8
 
9
9
  /**
10
10
  * @import {Zone} from '@agoric/zone';
11
+ * @import {MapStore} from '@agoric/store';
11
12
  * @import {OperatorKit} from './operator-kit.js';
12
- * @import {CctpTxEvidence} from '../types.js';
13
+ * @import {CctpTxEvidence, EvidenceWithRisk, RiskAssessment} from '../types.js';
13
14
  */
14
15
 
15
16
  const trace = makeTracer('TxFeed', true);
@@ -19,7 +20,11 @@ export const INVITATION_MAKERS_DESC = 'oracle operator invitation';
19
20
 
20
21
  const TransactionFeedKitI = harden({
21
22
  operatorPowers: M.interface('Transaction Feed Admin', {
22
- attest: M.call(CctpTxEvidenceShape, M.string()).returns(),
23
+ attest: M.call(
24
+ CctpTxEvidenceShape,
25
+ RiskAssessmentShape,
26
+ M.string(),
27
+ ).returns(),
23
28
  }),
24
29
  creator: M.interface('Transaction Feed Creator', {
25
30
  // TODO narrow the return shape to OperatorKit
@@ -32,6 +37,22 @@ const TransactionFeedKitI = harden({
32
37
  }),
33
38
  });
34
39
 
40
+ /**
41
+ * @param {MapStore<string, RiskAssessment>[]} riskStores
42
+ * @param {string} txHash
43
+ */
44
+ const allRisksIdentified = (riskStores, txHash) => {
45
+ /** @type {Set<string>} */
46
+ const setOfRisks = new Set();
47
+ for (const store of riskStores) {
48
+ const next = store.get(txHash);
49
+ for (const risk of next.risksIdentified ?? []) {
50
+ setOfRisks.add(risk);
51
+ }
52
+ }
53
+ return [...setOfRisks.values()].sort();
54
+ };
55
+
35
56
  /**
36
57
  * @param {Zone} zone
37
58
  * @param {ZCF} zcf
@@ -42,7 +63,7 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
42
63
  kinds,
43
64
  'Transaction Feed',
44
65
  );
45
- /** @type {PublishKit<CctpTxEvidence>} */
66
+ /** @type {PublishKit<EvidenceWithRisk>} */
46
67
  const { publisher, subscriber } = makeDurablePublishKit();
47
68
 
48
69
  const makeInertInvitation = defineInertInvitation(zcf, 'submitting evidence');
@@ -56,14 +77,12 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
56
77
  TransactionFeedKitI,
57
78
  () => {
58
79
  /** @type {MapStore<string, OperatorKit>} */
59
- const operators = zone.mapStore('operators', {
60
- durable: true,
61
- });
80
+ const operators = zone.mapStore('operators');
62
81
  /** @type {MapStore<string, MapStore<string, CctpTxEvidence>>} */
63
- const pending = zone.mapStore('pending', {
64
- durable: true,
65
- });
66
- return { operators, pending };
82
+ const pending = zone.mapStore('pending');
83
+ /** @type {MapStore<string, MapStore<string, RiskAssessment>>} */
84
+ const risks = zone.mapStore('risks');
85
+ return { operators, pending, risks };
67
86
  },
68
87
  {
69
88
  creator: {
@@ -90,7 +109,7 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
90
109
  },
91
110
  /** @param {string} operatorId */
92
111
  initOperator(operatorId) {
93
- const { operators, pending } = this.state;
112
+ const { operators, pending, risks } = this.state;
94
113
  trace('initOperator', operatorId);
95
114
 
96
115
  const operatorKit = makeOperatorKit(
@@ -102,6 +121,7 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
102
121
  operatorId,
103
122
  zone.detached().mapStore('pending evidence'),
104
123
  );
124
+ risks.init(operatorId, zone.detached().mapStore('risk assessments'));
105
125
 
106
126
  return operatorKit;
107
127
  },
@@ -122,11 +142,12 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
122
142
  * NB: the operatorKit is responsible for
123
143
  *
124
144
  * @param {CctpTxEvidence} evidence
145
+ * @param {RiskAssessment} riskAssessment
125
146
  * @param {string} operatorId
126
147
  */
127
- attest(evidence, operatorId) {
128
- const { operators, pending } = this.state;
129
- trace('submitEvidence', operatorId, evidence);
148
+ attest(evidence, riskAssessment, operatorId) {
149
+ const { operators, pending, risks } = this.state;
150
+ trace('attest', operatorId, evidence);
130
151
 
131
152
  // TODO https://github.com/Agoric/agoric-sdk/pull/10720
132
153
  // TODO validate that it's a valid for Fast USDC before accepting
@@ -141,6 +162,9 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
141
162
  trace(`operator ${operatorId} already reported ${txHash}`);
142
163
  } else {
143
164
  pendingStore.init(txHash, evidence);
165
+ // accept the risk assessment as well
166
+ const riskStore = risks.get(operatorId);
167
+ riskStore.init(txHash, riskAssessment);
144
168
  }
145
169
  }
146
170
 
@@ -183,12 +207,24 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
183
207
  lastEvidence = next;
184
208
  }
185
209
 
186
- // sufficient agreement, so remove from pending and publish
210
+ const riskStores = [...risks.values()].filter(store =>
211
+ store.has(txHash),
212
+ );
213
+ // take the union of risks identified from all operators
214
+ const risksIdentified = allRisksIdentified(riskStores, txHash);
215
+
216
+ // sufficient agreement, so remove from pending risks, then publish
187
217
  for (const store of found) {
188
218
  store.delete(txHash);
189
219
  }
190
- trace('publishing evidence', evidence);
191
- publisher.publish(evidence);
220
+ for (const store of riskStores) {
221
+ store.delete(txHash);
222
+ }
223
+ trace('publishing evidence', evidence, risksIdentified);
224
+ publisher.publish({
225
+ evidence,
226
+ risk: { risksIdentified },
227
+ });
192
228
  },
193
229
  },
194
230
  public: {
@@ -38,7 +38,7 @@ const ADDRESSES_BAGGAGE_KEY = 'addresses';
38
38
  * @import {Marshaller, StorageNode} from '@agoric/internal/src/lib-chainStorage.js'
39
39
  * @import {Zone} from '@agoric/zone';
40
40
  * @import {OperatorKit} from './exos/operator-kit.js';
41
- * @import {CctpTxEvidence, FeeConfig} from './types.js';
41
+ * @import {CctpTxEvidence, FeeConfig, RiskAssessment} from './types.js';
42
42
  */
43
43
 
44
44
  /**
@@ -202,9 +202,10 @@ export const contract = async (zcf, privateArgs, zone, tools) => {
202
202
  * capability is available in the smart-wallet bridge during UI testing.
203
203
  *
204
204
  * @param {CctpTxEvidence} evidence
205
+ * @param {RiskAssessment} [risk]
205
206
  */
206
- makeTestPushInvitation(evidence) {
207
- void advancer.handleTransactionEvent(evidence);
207
+ makeTestPushInvitation(evidence, risk = {}) {
208
+ void advancer.handleTransactionEvent({ evidence, risk });
208
209
  return makeTestInvitation();
209
210
  },
210
211
  makeDepositInvitation() {
@@ -303,9 +304,9 @@ export const contract = async (zcf, privateArgs, zone, tools) => {
303
304
  );
304
305
  // Connect evidence stream to advancer
305
306
  void observeIteration(subscribeEach(feedKit.public.getEvidenceSubscriber()), {
306
- updateState(evidence) {
307
+ updateState(evidenceWithRisk) {
307
308
  try {
308
- void advancer.handleTransactionEvent(evidence);
309
+ void advancer.handleTransactionEvent(evidenceWithRisk);
309
310
  } catch (err) {
310
311
  trace('🚨 Error handling transaction event', err);
311
312
  }
@@ -6,7 +6,7 @@ import { PendingTxStatus } from './constants.js';
6
6
  * @import {TypedPattern} from '@agoric/internal';
7
7
  * @import {FastUsdcTerms} from './fast-usdc.contract.js';
8
8
  * @import {USDCProposalShapes} from './pool-share-math.js';
9
- * @import {CctpTxEvidence, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy, AddressHook, EvmAddress, EvmHash} from './types.js';
9
+ * @import {CctpTxEvidence, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy, AddressHook, EvmAddress, EvmHash, RiskAssessment, EvidenceWithRisk} from './types.js';
10
10
  */
11
11
 
12
12
  /**
@@ -49,6 +49,15 @@ export const EvmHashShape = M.string({
49
49
  });
50
50
  harden(EvmHashShape);
51
51
 
52
+ /** @type {TypedPattern<RiskAssessment>} */
53
+ export const RiskAssessmentShape = M.splitRecord(
54
+ {},
55
+ {
56
+ risksIdentified: M.arrayOf(M.string()),
57
+ },
58
+ );
59
+ harden(RiskAssessmentShape);
60
+
52
61
  /** @type {TypedPattern<CctpTxEvidence>} */
53
62
  export const CctpTxEvidenceShape = {
54
63
  aux: {
@@ -67,6 +76,13 @@ export const CctpTxEvidenceShape = {
67
76
  };
68
77
  harden(CctpTxEvidenceShape);
69
78
 
79
+ /** @type {TypedPattern<EvidenceWithRisk>} */
80
+ export const EvidenceWithRiskShape = {
81
+ evidence: CctpTxEvidenceShape,
82
+ risk: RiskAssessmentShape,
83
+ };
84
+ harden(EvidenceWithRiskShape);
85
+
70
86
  /** @type {TypedPattern<PendingTx>} */
71
87
  // @ts-expect-error TypedPattern not recognized as record
72
88
  export const PendingTxShape = {
package/src/types.ts CHANGED
@@ -17,6 +17,10 @@ export type NobleAddress = `noble1${string}`;
17
17
  export type EvmChainID = number;
18
18
  export type EvmChainName = string;
19
19
 
20
+ export interface RiskAssessment {
21
+ risksIdentified?: string[];
22
+ }
23
+
20
24
  export interface CctpTxEvidence {
21
25
  /** from Noble RPC */
22
26
  aux: {
@@ -35,6 +39,11 @@ export interface CctpTxEvidence {
35
39
  txHash: EvmHash;
36
40
  }
37
41
 
42
+ export interface EvidenceWithRisk {
43
+ evidence: CctpTxEvidence;
44
+ risk: RiskAssessment;
45
+ }
46
+
38
47
  /**
39
48
  * 'evidence' only available when it's first observed and not in subsequent
40
49
  * updates.
@@ -42,6 +51,7 @@ export interface CctpTxEvidence {
42
51
  export interface TransactionRecord extends CopyRecord {
43
52
  evidence?: CctpTxEvidence;
44
53
  split?: RepayAmountKWR;
54
+ risksIdentified?: string[];
45
55
  status: TxStatus;
46
56
  }
47
57