@agoric/fast-usdc 0.1.1-other-dev-3eb1a1d.0 → 0.1.1-upgrade-19-dev-c605745.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 +43 -0
- package/package.json +29 -25
- package/src/add-operators.core.js +63 -0
- package/src/cli/bridge-action.js +40 -0
- package/src/cli/cli.js +46 -153
- package/src/cli/config-commands.js +108 -0
- package/src/cli/config.js +15 -9
- package/src/cli/lp-commands.js +160 -0
- package/src/cli/operator-commands.js +146 -0
- package/src/cli/transfer.js +63 -13
- package/src/{util → cli/util}/agoric.js +1 -1
- package/src/cli/util/bank.js +12 -0
- package/src/{util → cli/util}/cctp.js +1 -1
- package/src/{util → cli/util}/file.js +1 -1
- package/src/clientSupport.js +98 -0
- package/src/constants.js +25 -2
- package/src/distribute-fees.core.js +93 -0
- package/src/exos/advancer.js +220 -106
- package/src/exos/liquidity-pool.js +130 -81
- package/src/exos/operator-kit.js +16 -12
- package/src/exos/settler.js +360 -64
- package/src/exos/status-manager.js +316 -65
- package/src/exos/transaction-feed.js +121 -42
- package/src/fast-usdc-policy.core.js +65 -0
- package/src/fast-usdc.contract.js +165 -84
- package/src/fast-usdc.flows.js +10 -0
- package/src/main.js +1 -0
- package/src/pool-share-math.js +55 -9
- package/src/{fast-usdc.start.js → start-fast-usdc.core.js} +48 -86
- package/src/type-guards.js +75 -24
- package/src/types.ts +89 -14
- package/src/utils/chain-policies.js +140 -0
- package/src/utils/core-eval.js +73 -0
- package/src/utils/deploy-config.js +127 -0
- package/src/utils/fees.js +3 -4
- package/tools/cli-tools.ts +9 -0
- package/tools/mock-io.ts +14 -0
- package/src/exos/README.md +0 -26
- package/src/utils/address.js +0 -71
- /package/src/{util → cli/util}/noble.js +0 -0
|
@@ -1,28 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { makeError, q } from '@endo/errors';
|
|
3
|
-
|
|
1
|
+
import { makeTracer } from '@agoric/internal';
|
|
4
2
|
import { appendToStoredArray } from '@agoric/store/src/stores/store-utils.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { AmountKeywordRecordShape } from '@agoric/zoe/src/typeGuards.js';
|
|
4
|
+
import { Fail, makeError, q } from '@endo/errors';
|
|
5
|
+
import { E } from '@endo/eventual-send';
|
|
6
|
+
import { M } from '@endo/patterns';
|
|
7
|
+
import { PendingTxStatus, TerminalTxStatus, TxStatus } from '../constants.js';
|
|
8
|
+
import {
|
|
9
|
+
CctpTxEvidenceShape,
|
|
10
|
+
EvmHashShape,
|
|
11
|
+
PendingTxShape,
|
|
12
|
+
} from '../type-guards.js';
|
|
7
13
|
|
|
8
14
|
/**
|
|
9
15
|
* @import {MapStore, SetStore} from '@agoric/store';
|
|
10
16
|
* @import {Zone} from '@agoric/zone';
|
|
11
|
-
* @import {CctpTxEvidence, NobleAddress,
|
|
17
|
+
* @import {CctpTxEvidence, NobleAddress, PendingTx, EvmHash, LogFn, TransactionRecord, EvidenceWithRisk, RiskAssessment} from '../types.js';
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {`pendingTx:${bigint}:${NobleAddress}`} PendingTxKey
|
|
22
|
+
* The string template is for developer visibility but not meant to ever be parsed.
|
|
12
23
|
*/
|
|
13
24
|
|
|
14
25
|
/**
|
|
15
26
|
* Create the key for the pendingTxs MapStore.
|
|
16
27
|
*
|
|
17
|
-
* The key is a composite
|
|
18
|
-
* parsable.
|
|
28
|
+
* The key is a composite but not meant to be parsable.
|
|
19
29
|
*
|
|
20
|
-
* @param {NobleAddress}
|
|
30
|
+
* @param {NobleAddress} nfa Noble Forwarding Account (implies EUD)
|
|
21
31
|
* @param {bigint} amount
|
|
22
32
|
* @returns {PendingTxKey}
|
|
23
33
|
*/
|
|
24
|
-
const makePendingTxKey = (
|
|
25
|
-
|
|
34
|
+
const makePendingTxKey = (nfa, amount) =>
|
|
35
|
+
// amount can't contain colon
|
|
36
|
+
`pendingTx:${amount}:${nfa}`;
|
|
26
37
|
|
|
27
38
|
/**
|
|
28
39
|
* Get the key for the pendingTxs MapStore.
|
|
@@ -36,18 +47,17 @@ const pendingTxKeyOf = evidence => {
|
|
|
36
47
|
};
|
|
37
48
|
|
|
38
49
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* @param {CctpTxEvidence} evidence
|
|
45
|
-
* @returns {SeenTxKey}
|
|
50
|
+
* @typedef {{
|
|
51
|
+
* log?: LogFn;
|
|
52
|
+
* marshaller: ERef<Marshaller>;
|
|
53
|
+
* }} StatusManagerPowers
|
|
46
54
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
|
|
56
|
+
export const stateShape = harden({
|
|
57
|
+
pendingSettleTxs: M.remotable(),
|
|
58
|
+
seenTxs: M.remotable(),
|
|
59
|
+
storedCompletedTxs: M.remotable(),
|
|
60
|
+
});
|
|
51
61
|
|
|
52
62
|
/**
|
|
53
63
|
* The `StatusManager` keeps track of Pending and Seen Transactions
|
|
@@ -57,19 +67,89 @@ const seenTxKeyOf = evidence => {
|
|
|
57
67
|
* XXX consider separate facets for `Advancing` and `Settling` capabilities.
|
|
58
68
|
*
|
|
59
69
|
* @param {Zone} zone
|
|
70
|
+
* @param {ERef<StorageNode>} txnsNode
|
|
71
|
+
* @param {StatusManagerPowers} caps
|
|
60
72
|
*/
|
|
61
|
-
export const prepareStatusManager =
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
export const prepareStatusManager = (
|
|
74
|
+
zone,
|
|
75
|
+
txnsNode,
|
|
76
|
+
{
|
|
77
|
+
marshaller,
|
|
78
|
+
// eslint-disable-next-line no-unused-vars
|
|
79
|
+
log = makeTracer('StatusManager', true),
|
|
80
|
+
} = /** @type {StatusManagerPowers} */ ({}),
|
|
81
|
+
) => {
|
|
82
|
+
/**
|
|
83
|
+
* Keyed by a tuple of the Noble Forwarding Account and amount.
|
|
84
|
+
* @type {MapStore<PendingTxKey, PendingTx[]>}
|
|
85
|
+
*/
|
|
86
|
+
const pendingSettleTxs = zone.mapStore('PendingSettleTxs', {
|
|
64
87
|
keyShape: M.string(),
|
|
65
88
|
valueShape: M.arrayOf(PendingTxShape),
|
|
66
89
|
});
|
|
67
90
|
|
|
68
|
-
/**
|
|
69
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Transactions seen *ever* by the contract.
|
|
93
|
+
*
|
|
94
|
+
* Note that like all durable stores, this MapStore is kept in IAVL. It stores
|
|
95
|
+
* the `blockTimestamp` so that later we can prune old transactions.
|
|
96
|
+
*
|
|
97
|
+
* Note that `blockTimestamp` can drift between chains. Fortunately all CCTP
|
|
98
|
+
* chains use the same Unix epoch and won't drift more than minutes apart,
|
|
99
|
+
* which is more than enough precision for pruning old transaction.
|
|
100
|
+
*
|
|
101
|
+
* @type {MapStore<EvmHash, NatValue>}
|
|
102
|
+
*/
|
|
103
|
+
const seenTxs = zone.mapStore('SeenTxs', {
|
|
104
|
+
keyShape: M.string(),
|
|
105
|
+
valueShape: M.nat(),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Transactions that have completed, but are still in vstorage.
|
|
110
|
+
*
|
|
111
|
+
* @type {SetStore<EvmHash>}
|
|
112
|
+
*/
|
|
113
|
+
const storedCompletedTxs = zone.setStore('StoredCompletedTxs', {
|
|
70
114
|
keyShape: M.string(),
|
|
71
115
|
});
|
|
72
116
|
|
|
117
|
+
/**
|
|
118
|
+
* @param {EvmHash} txId
|
|
119
|
+
* @param {TransactionRecord} record
|
|
120
|
+
* @returns {Promise<void>}
|
|
121
|
+
*/
|
|
122
|
+
const publishTxnRecord = async (txId, record) => {
|
|
123
|
+
const txNode = E(txnsNode).makeChildNode(txId, {
|
|
124
|
+
sequence: true, // avoid overwriting other output in the block
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// XXX awkward for publish* to update a store, but it's temporary
|
|
128
|
+
if (record.status && TerminalTxStatus[record.status]) {
|
|
129
|
+
// UNTIL https://github.com/Agoric/agoric-sdk/issues/7405
|
|
130
|
+
// Queue it for deletion later because if we deleted it now the earlier
|
|
131
|
+
// writes in this block would be wiped. For now we keep track of what to
|
|
132
|
+
// delete when we know it'll be another block.
|
|
133
|
+
storedCompletedTxs.add(txId);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const capData = await E(marshaller).toCapData(record);
|
|
137
|
+
|
|
138
|
+
await E(txNode).setValue(JSON.stringify(capData));
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @param {CctpTxEvidence['txHash']} hash
|
|
143
|
+
* @param {CctpTxEvidence} evidence
|
|
144
|
+
*/
|
|
145
|
+
const publishEvidence = (hash, evidence) => {
|
|
146
|
+
// Don't await, just writing to vstorage.
|
|
147
|
+
void publishTxnRecord(
|
|
148
|
+
hash,
|
|
149
|
+
harden({ evidence, status: TxStatus.Observed }),
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
73
153
|
/**
|
|
74
154
|
* Ensures that `txHash+chainId` has not been processed
|
|
75
155
|
* and adds entry to `seenTxs` set.
|
|
@@ -78,39 +158,160 @@ export const prepareStatusManager = zone => {
|
|
|
78
158
|
*
|
|
79
159
|
* @param {CctpTxEvidence} evidence
|
|
80
160
|
* @param {PendingTxStatus} status
|
|
161
|
+
* @param {string[]} [risksIdentified]
|
|
81
162
|
*/
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
if (seenTxs.has(
|
|
85
|
-
throw makeError(`Transaction already seen: ${q(
|
|
163
|
+
const initPendingTx = (evidence, status, risksIdentified) => {
|
|
164
|
+
const { txHash } = evidence;
|
|
165
|
+
if (seenTxs.has(txHash)) {
|
|
166
|
+
throw makeError(`Transaction already seen: ${q(txHash)}`);
|
|
86
167
|
}
|
|
87
|
-
seenTxs.
|
|
168
|
+
seenTxs.init(txHash, evidence.blockTimestamp);
|
|
88
169
|
|
|
89
170
|
appendToStoredArray(
|
|
90
|
-
|
|
171
|
+
pendingSettleTxs,
|
|
91
172
|
pendingTxKeyOf(evidence),
|
|
92
173
|
harden({ ...evidence, status }),
|
|
93
174
|
);
|
|
175
|
+
publishEvidence(txHash, evidence);
|
|
176
|
+
if (status === PendingTxStatus.AdvanceSkipped) {
|
|
177
|
+
void publishTxnRecord(txHash, harden({ status, risksIdentified }));
|
|
178
|
+
} else if (status !== PendingTxStatus.Observed) {
|
|
179
|
+
// publishEvidence publishes Observed
|
|
180
|
+
void publishTxnRecord(txHash, harden({ status }));
|
|
181
|
+
}
|
|
94
182
|
};
|
|
95
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Update the pending transaction status.
|
|
186
|
+
*
|
|
187
|
+
* @param {{nfa: NobleAddress, amount: bigint}} keyParts
|
|
188
|
+
* @param {PendingTxStatus} status
|
|
189
|
+
*/
|
|
190
|
+
function setPendingTxStatus({ nfa, amount }, status) {
|
|
191
|
+
const key = makePendingTxKey(nfa, amount);
|
|
192
|
+
pendingSettleTxs.has(key) || Fail`no advancing tx with ${{ nfa, amount }}`;
|
|
193
|
+
const pending = pendingSettleTxs.get(key);
|
|
194
|
+
const ix = pending.findIndex(tx => tx.status === PendingTxStatus.Advancing);
|
|
195
|
+
ix >= 0 || Fail`no advancing tx with ${{ nfa, amount }}`;
|
|
196
|
+
const [prefix, tx, suffix] = [
|
|
197
|
+
pending.slice(0, ix),
|
|
198
|
+
pending[ix],
|
|
199
|
+
pending.slice(ix + 1),
|
|
200
|
+
];
|
|
201
|
+
const txpost = { ...tx, status };
|
|
202
|
+
pendingSettleTxs.set(key, harden([...prefix, txpost, ...suffix]));
|
|
203
|
+
void publishTxnRecord(tx.txHash, harden({ status }));
|
|
204
|
+
}
|
|
205
|
+
|
|
96
206
|
return zone.exo(
|
|
97
207
|
'Fast USDC Status Manager',
|
|
98
208
|
M.interface('StatusManagerI', {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
209
|
+
// TODO: naming scheme for transition events
|
|
210
|
+
advance: M.call(CctpTxEvidenceShape).returns(),
|
|
211
|
+
advanceOutcome: M.call(M.string(), M.nat(), M.boolean()).returns(),
|
|
212
|
+
skipAdvance: M.call(CctpTxEvidenceShape, M.arrayOf(M.string())).returns(),
|
|
213
|
+
advanceOutcomeForMintedEarly: M.call(EvmHashShape, M.boolean()).returns(),
|
|
214
|
+
advanceOutcomeForUnknownMint: M.call(CctpTxEvidenceShape).returns(),
|
|
215
|
+
observe: M.call(CctpTxEvidenceShape).returns(),
|
|
216
|
+
hasBeenObserved: M.call(CctpTxEvidenceShape).returns(M.boolean()),
|
|
217
|
+
deleteCompletedTxs: M.call().returns(M.undefined()),
|
|
218
|
+
dequeueStatus: M.call(M.string(), M.bigint()).returns(
|
|
219
|
+
M.or(
|
|
220
|
+
{
|
|
221
|
+
txHash: EvmHashShape,
|
|
222
|
+
status: M.or(...Object.values(PendingTxStatus)),
|
|
223
|
+
},
|
|
224
|
+
M.undefined(),
|
|
225
|
+
),
|
|
226
|
+
),
|
|
227
|
+
disbursed: M.call(EvmHashShape, AmountKeywordRecordShape).returns(
|
|
228
|
+
M.undefined(),
|
|
229
|
+
),
|
|
230
|
+
forwarded: M.call(EvmHashShape, M.boolean()).returns(),
|
|
103
231
|
lookupPending: M.call(M.string(), M.bigint()).returns(
|
|
104
232
|
M.arrayOf(PendingTxShape),
|
|
105
233
|
),
|
|
106
234
|
}),
|
|
107
235
|
{
|
|
108
236
|
/**
|
|
109
|
-
* Add a new transaction with
|
|
237
|
+
* Add a new transaction with ADVANCING status
|
|
238
|
+
*
|
|
239
|
+
* NB: this acts like observe() but subsequently records an ADVANCING
|
|
240
|
+
* state
|
|
241
|
+
*
|
|
110
242
|
* @param {CctpTxEvidence} evidence
|
|
111
243
|
*/
|
|
112
244
|
advance(evidence) {
|
|
113
|
-
|
|
245
|
+
initPendingTx(evidence, PendingTxStatus.Advancing);
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Add a new transaction with ADVANCE_SKIPPED status
|
|
250
|
+
*
|
|
251
|
+
* NB: this acts like observe() but subsequently records an
|
|
252
|
+
* ADVANCE_SKIPPED state along with risks identified
|
|
253
|
+
*
|
|
254
|
+
* @param {CctpTxEvidence} evidence
|
|
255
|
+
* @param {string[]} risksIdentified
|
|
256
|
+
*/
|
|
257
|
+
skipAdvance(evidence, risksIdentified) {
|
|
258
|
+
initPendingTx(
|
|
259
|
+
evidence,
|
|
260
|
+
PendingTxStatus.AdvanceSkipped,
|
|
261
|
+
risksIdentified,
|
|
262
|
+
);
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Record result of an ADVANCING transaction
|
|
267
|
+
*
|
|
268
|
+
* @param {NobleAddress} nfa Noble Forwarding Account
|
|
269
|
+
* @param {import('@agoric/ertp').NatValue} amount
|
|
270
|
+
* @param {boolean} success - Advanced vs. AdvanceFailed
|
|
271
|
+
* @throws {Error} if nothing to advance
|
|
272
|
+
*/
|
|
273
|
+
advanceOutcome(nfa, amount, success) {
|
|
274
|
+
setPendingTxStatus(
|
|
275
|
+
{ nfa, amount },
|
|
276
|
+
success ? PendingTxStatus.Advanced : PendingTxStatus.AdvanceFailed,
|
|
277
|
+
);
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* If minted while advancing, publish a status update for the advance
|
|
282
|
+
* to vstorage.
|
|
283
|
+
*
|
|
284
|
+
* Does not add or amend `pendingSettleTxs` as this has
|
|
285
|
+
* already settled.
|
|
286
|
+
*
|
|
287
|
+
* @param {EvmHash} txHash
|
|
288
|
+
* @param {boolean} success whether the Transfer succeeded
|
|
289
|
+
*/
|
|
290
|
+
advanceOutcomeForMintedEarly(txHash, success) {
|
|
291
|
+
void publishTxnRecord(
|
|
292
|
+
txHash,
|
|
293
|
+
harden({
|
|
294
|
+
status: success
|
|
295
|
+
? PendingTxStatus.Advanced
|
|
296
|
+
: PendingTxStatus.AdvanceFailed,
|
|
297
|
+
}),
|
|
298
|
+
);
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* If minted before observed and the evidence is eventually
|
|
303
|
+
* reported, publish the evidence without adding to `pendingSettleTxs`
|
|
304
|
+
*
|
|
305
|
+
* @param {CctpTxEvidence} evidence
|
|
306
|
+
*/
|
|
307
|
+
advanceOutcomeForUnknownMint(evidence) {
|
|
308
|
+
const { txHash } = evidence;
|
|
309
|
+
// unexpected path, since `hasBeenObserved` will be called before this
|
|
310
|
+
if (seenTxs.has(txHash)) {
|
|
311
|
+
throw makeError(`Transaction already seen: ${q(txHash)}`);
|
|
312
|
+
}
|
|
313
|
+
seenTxs.init(txHash, evidence.blockTimestamp);
|
|
314
|
+
publishEvidence(txHash, evidence);
|
|
114
315
|
},
|
|
115
316
|
|
|
116
317
|
/**
|
|
@@ -118,57 +319,107 @@ export const prepareStatusManager = zone => {
|
|
|
118
319
|
* @param {CctpTxEvidence} evidence
|
|
119
320
|
*/
|
|
120
321
|
observe(evidence) {
|
|
121
|
-
|
|
322
|
+
initPendingTx(evidence, PendingTxStatus.Observed);
|
|
122
323
|
},
|
|
123
324
|
|
|
124
325
|
/**
|
|
125
|
-
*
|
|
326
|
+
* Note: ADVANCING state implies tx has been OBSERVED
|
|
126
327
|
*
|
|
127
|
-
* @param {
|
|
128
|
-
* @param {bigint} amount
|
|
129
|
-
* @returns {boolean}
|
|
328
|
+
* @param {CctpTxEvidence} evidence
|
|
130
329
|
*/
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
330
|
+
hasBeenObserved(evidence) {
|
|
331
|
+
return seenTxs.has(evidence.txHash);
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
// UNTIL https://github.com/Agoric/agoric-sdk/issues/7405
|
|
335
|
+
deleteCompletedTxs() {
|
|
336
|
+
for (const txHash of storedCompletedTxs.values()) {
|
|
337
|
+
// As of now, setValue('') on a non-sequence node will delete it
|
|
338
|
+
const txNode = E(txnsNode).makeChildNode(txHash, {
|
|
339
|
+
sequence: false,
|
|
340
|
+
});
|
|
341
|
+
void E(txNode)
|
|
342
|
+
.setValue('')
|
|
343
|
+
.then(() => storedCompletedTxs.delete(txHash));
|
|
344
|
+
}
|
|
135
345
|
},
|
|
136
346
|
|
|
137
347
|
/**
|
|
138
|
-
*
|
|
348
|
+
* Remove and return the oldest pending settlement transaction that matches the given
|
|
349
|
+
* forwarding account and amount. Since multiple pending transactions may exist with
|
|
350
|
+
* identical (account, amount) pairs, we process them in FIFO order.
|
|
139
351
|
*
|
|
140
|
-
* @param {NobleAddress}
|
|
352
|
+
* @param {NobleAddress} nfa
|
|
141
353
|
* @param {bigint} amount
|
|
354
|
+
* @returns {Pick<PendingTx, 'status' | 'txHash'> | undefined} undefined if no pending
|
|
355
|
+
* transactions exist for this address and amount combination.
|
|
142
356
|
*/
|
|
143
|
-
|
|
144
|
-
const key = makePendingTxKey(
|
|
145
|
-
|
|
357
|
+
dequeueStatus(nfa, amount) {
|
|
358
|
+
const key = makePendingTxKey(nfa, amount);
|
|
359
|
+
if (!pendingSettleTxs.has(key)) return undefined;
|
|
360
|
+
const pending = pendingSettleTxs.get(key);
|
|
361
|
+
|
|
362
|
+
if (pending.length === 0) {
|
|
363
|
+
return undefined;
|
|
364
|
+
}
|
|
365
|
+
// extract first item
|
|
366
|
+
const [{ status, txHash }, ...remaining] = pending;
|
|
146
367
|
|
|
147
|
-
if (
|
|
148
|
-
|
|
368
|
+
if (remaining.length) {
|
|
369
|
+
pendingSettleTxs.set(key, harden(remaining));
|
|
370
|
+
} else {
|
|
371
|
+
pendingSettleTxs.delete(key);
|
|
149
372
|
}
|
|
150
373
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
374
|
+
return harden({ status, txHash });
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Mark a transaction as `DISBURSED`
|
|
379
|
+
*
|
|
380
|
+
* @param {EvmHash} txHash
|
|
381
|
+
* @param {import('./liquidity-pool.js').RepayAmountKWR} split
|
|
382
|
+
*/
|
|
383
|
+
disbursed(txHash, split) {
|
|
384
|
+
void publishTxnRecord(
|
|
385
|
+
txHash,
|
|
386
|
+
harden({ split, status: TxStatus.Disbursed }),
|
|
387
|
+
);
|
|
388
|
+
},
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Mark a transaction as `FORWARDED` or `FORWARD_FAILED`
|
|
392
|
+
*
|
|
393
|
+
* @param {EvmHash} txHash
|
|
394
|
+
* @param {boolean} success
|
|
395
|
+
*/
|
|
396
|
+
forwarded(txHash, success) {
|
|
397
|
+
void publishTxnRecord(
|
|
398
|
+
txHash,
|
|
399
|
+
harden({
|
|
400
|
+
status: success ? TxStatus.Forwarded : TxStatus.ForwardFailed,
|
|
401
|
+
}),
|
|
402
|
+
);
|
|
155
403
|
},
|
|
156
404
|
|
|
157
405
|
/**
|
|
158
406
|
* Lookup all pending entries for a given address and amount
|
|
159
407
|
*
|
|
160
|
-
*
|
|
408
|
+
* XXX only used in tests. should we remove?
|
|
409
|
+
*
|
|
410
|
+
* @param {NobleAddress} nfa
|
|
161
411
|
* @param {bigint} amount
|
|
162
412
|
* @returns {PendingTx[]}
|
|
163
413
|
*/
|
|
164
|
-
lookupPending(
|
|
165
|
-
const key = makePendingTxKey(
|
|
166
|
-
if (!
|
|
167
|
-
|
|
414
|
+
lookupPending(nfa, amount) {
|
|
415
|
+
const key = makePendingTxKey(nfa, amount);
|
|
416
|
+
if (!pendingSettleTxs.has(key)) {
|
|
417
|
+
return harden([]);
|
|
168
418
|
}
|
|
169
|
-
return
|
|
419
|
+
return pendingSettleTxs.get(key);
|
|
170
420
|
},
|
|
171
421
|
},
|
|
422
|
+
{ stateShape },
|
|
172
423
|
);
|
|
173
424
|
};
|
|
174
425
|
harden(prepareStatusManager);
|