1
- import { AmountMath , AmountShape , PaymentShape } from '@agoric/ertp' ;
2
- import { assertAllDefined } from '@agoric/internal' ;
1
+ import { AmountMath , AmountShape } from '@agoric/ertp' ;
2
+ import { assertAllDefined , makeTracer } from '@agoric/internal' ;
3
3
import { ChainAddressShape } from '@agoric/orchestration' ;
4
4
import { pickFacet } from '@agoric/vat-data' ;
5
5
import { VowShape } from '@agoric/vow' ;
@@ -15,31 +15,25 @@ const { isGTE } = AmountMath;
15
15
/**
16
16
* @import {HostInterface} from '@agoric/async-flow';
17
17
* @import {NatAmount} from '@agoric/ertp';
18
- * @import {ChainAddress, ChainHub, Denom, DenomAmount, OrchestrationAccount} from '@agoric/orchestration';
18
+ * @import {ChainAddress, ChainHub, Denom, OrchestrationAccount} from '@agoric/orchestration';
19
+ * @import {ZoeTools} from '@agoric/orchestration/src/utils/zoe-tools.js';
19
20
* @import {VowTools} from '@agoric/vow';
20
21
* @import {Zone} from '@agoric/zone';
21
22
* @import {CctpTxEvidence, FeeConfig, LogFn} from '../types.js';
22
23
* @import {StatusManager} from './status-manager.js';
23
- */
24
-
25
- /**
26
- * Expected interface from LiquidityPool
27
- *
28
- * @typedef {{
29
- * lookupBalance(): NatAmount;
30
- * borrow(amount: Amount<"nat">): Promise<Payment<"nat">>;
31
- * repay(payments: PaymentKeywordRecord): Promise<void>
32
- * }} AssetManagerFacet
24
+ * @import {LiquidityPoolKit} from './liquidity-pool.js';
33
25
*/
34
26
35
27
/**
36
28
* @typedef {{
37
29
* chainHub: ChainHub;
38
30
* feeConfig: FeeConfig;
39
- * log: LogFn;
31
+ * localTransfer: ZoeTools['localTransfer'];
32
+ * log?: LogFn;
40
33
* statusManager: StatusManager;
41
34
* usdc: { brand: Brand<'nat'>; denom: Denom; };
42
35
* vowTools: VowTools;
36
+ * zcf: ZCF;
43
37
* }} AdvancerKitPowers
44
38
*/
45
39
@@ -49,13 +43,15 @@ const AdvancerKitI = harden({
49
43
handleTransactionEvent : M . callWhen ( CctpTxEvidenceShape ) . returns ( ) ,
50
44
} ) ,
51
45
depositHandler : M . interface ( 'DepositHandlerI' , {
52
- onFulfilled : M . call ( AmountShape , {
46
+ onFulfilled : M . call ( M . undefined ( ) , {
47
+ amount : AmountShape ,
53
48
destination : ChainAddressShape ,
54
- payment : PaymentShape ,
49
+ tmpSeat : M . remotable ( ) ,
55
50
} ) . returns ( VowShape ) ,
56
51
onRejected : M . call ( M . error ( ) , {
52
+ amount : AmountShape ,
57
53
destination : ChainAddressShape ,
58
- payment : PaymentShape ,
54
+ tmpSeat : M . remotable ( ) ,
59
55
} ) . returns ( ) ,
60
56
} ) ,
61
57
transferHandler : M . interface ( 'TransferHandlerI' , {
@@ -77,7 +73,16 @@ const AdvancerKitI = harden({
77
73
*/
78
74
export const prepareAdvancerKit = (
79
75
zone ,
80
- { chainHub, feeConfig, log, statusManager, usdc, vowTools : { watch, when } } ,
76
+ {
77
+ chainHub,
78
+ feeConfig,
79
+ localTransfer,
80
+ log = makeTracer ( 'Advancer' , true ) ,
81
+ statusManager,
82
+ usdc,
83
+ vowTools : { watch, when } ,
84
+ zcf,
85
+ } = /** @type {AdvancerKitPowers } */ ( { } ) ,
81
86
) => {
82
87
assertAllDefined ( {
83
88
chainHub,
@@ -95,8 +100,8 @@ export const prepareAdvancerKit = (
95
100
AdvancerKitI ,
96
101
/**
97
102
* @param {{
98
- * assetManagerFacet: AssetManagerFacet ;
99
- * poolAccount: ERef< HostInterface<OrchestrationAccount<{chainId: 'agoric'}> >>;
103
+ * borrowerFacet: LiquidityPoolKit['borrower'] ;
104
+ * poolAccount: HostInterface<OrchestrationAccount<{chainId: 'agoric'}>>;
100
105
* }} config
101
106
*/
102
107
config => harden ( config ) ,
@@ -115,8 +120,7 @@ export const prepareAdvancerKit = (
115
120
async handleTransactionEvent ( evidence ) {
116
121
await null ;
117
122
try {
118
- // TODO poolAccount might be a vow we need to unwrap
119
- const { assetManagerFacet, poolAccount } = this . state ;
123
+ const { borrowerFacet, poolAccount } = this . state ;
120
124
const { recipientAddress } = evidence . aux ;
121
125
const { EUD } = addressTools . getQueryParams (
122
126
recipientAddress ,
@@ -129,14 +133,12 @@ export const prepareAdvancerKit = (
129
133
const advanceAmount = feeTools . calculateAdvance ( requestedAmount ) ;
130
134
131
135
// TODO: consider skipping and using `borrow()`s internal balance check
132
- const poolBalance = assetManagerFacet . lookupBalance ( ) ;
136
+ const poolBalance = borrowerFacet . getBalance ( ) ;
133
137
if ( ! isGTE ( poolBalance , requestedAmount ) ) {
134
138
log (
135
139
`Insufficient pool funds` ,
136
140
`Requested ${ q ( advanceAmount ) } but only have ${ q ( poolBalance ) } ` ,
137
141
) ;
138
- // report `requestedAmount`, not `advancedAmount`... do we need to
139
- // communicate net to `StatusManger` in case fees change in between?
140
142
statusManager . observe ( evidence ) ;
141
143
return ;
142
144
}
@@ -152,19 +154,29 @@ export const prepareAdvancerKit = (
152
154
return ;
153
155
}
154
156
157
+ const { zcfSeat : tmpSeat } = zcf . makeEmptySeatKit ( ) ;
158
+ const amountKWR = harden ( { USDC : advanceAmount } ) ;
155
159
try {
156
- const payment = await assetManagerFacet . borrow ( advanceAmount ) ;
157
- const depositV = E ( poolAccount ) . deposit ( payment ) ;
158
- void watch ( depositV , this . facets . depositHandler , {
159
- destination,
160
- payment,
161
- } ) ;
160
+ borrowerFacet . borrow ( tmpSeat , amountKWR ) ;
162
161
} catch ( e ) {
163
- // `.borrow()` might fail if the balance changes since we
164
- // requested it. TODO - how to handle this? change ADVANCED -> OBSERVED?
165
- // Note: `depositHandler` handles the `.deposit()` failure
162
+ // We do not expect this to fail since there are no turn boundaries
163
+ // between .getBalance() and .borrow().
164
+ // We catch to report outside of the normal error flow since this is
165
+ // not expected.
166
166
log ( '🚨 advance borrow failed' , q ( e ) . toString ( ) ) ;
167
167
}
168
+
169
+ const depositV = localTransfer (
170
+ tmpSeat ,
171
+ // @ts -expect-error LocalAccountMethods vs OrchestrationAccount
172
+ poolAccount ,
173
+ amountKWR ,
174
+ ) ;
175
+ void watch ( depositV , this . facets . depositHandler , {
176
+ amount : advanceAmount ,
177
+ destination,
178
+ tmpSeat,
179
+ } ) ;
168
180
} catch ( e ) {
169
181
log ( 'Advancer error:' , q ( e ) . toString ( ) ) ;
170
182
statusManager . observe ( evidence ) ;
@@ -173,31 +185,33 @@ export const prepareAdvancerKit = (
173
185
} ,
174
186
depositHandler : {
175
187
/**
176
- * @param {NatAmount } amount amount returned from deposit
177
- * @param {{ destination: ChainAddress; payment: Payment<'nat'> } } ctx
188
+ * @param {undefined } result
189
+ * @param {{ amount: Amount<'nat'>; destination: ChainAddress; tmpSeat: ZCFSeat } } ctx
178
190
*/
179
- onFulfilled ( amount , { destination } ) {
191
+ onFulfilled ( result , { amount , destination } ) {
180
192
const { poolAccount } = this . state ;
181
- const transferV = E ( poolAccount ) . transfer (
182
- destination ,
183
- /** @type {DenomAmount } */ ( {
184
- denom : usdc . denom ,
185
- value : amount . value ,
186
- } ) ,
187
- ) ;
193
+ const transferV = E ( poolAccount ) . transfer ( destination , {
194
+ denom : usdc . denom ,
195
+ value : amount . value ,
196
+ } ) ;
188
197
return watch ( transferV , this . facets . transferHandler , {
189
198
destination,
190
199
amount,
191
200
} ) ;
192
201
} ,
193
202
/**
194
203
* @param {Error } error
195
- * @param {{ destination: ChainAddress; payment: Payment<'nat'> } } ctx
204
+ * @param {{ amount: Amount<'nat'>; destination: ChainAddress; tmpSeat: ZCFSeat } } ctx
196
205
*/
197
- onRejected ( error , { payment } ) {
198
- // TODO return live payment from ctx to LP
206
+ onRejected ( error , { tmpSeat } ) {
207
+ // TODO return seat allocation from ctx to LP?
199
208
log ( '🚨 advance deposit failed' , q ( error ) . toString ( ) ) ;
200
- log ( 'TODO live payment to return to LP' , q ( payment ) . toString ( ) ) ;
209
+ // TODO #10510 (comprehensive error testing) determine
210
+ // course of action here
211
+ log (
212
+ 'TODO live payment on seat to return to LP' ,
213
+ q ( tmpSeat ) . toString ( ) ,
214
+ ) ;
201
215
} ,
202
216
} ,
203
217
transferHandler : {
@@ -206,23 +220,24 @@ export const prepareAdvancerKit = (
206
220
* @param {{ destination: ChainAddress; amount: NatAmount; } } ctx
207
221
*/
208
222
onFulfilled ( result , { destination, amount } ) {
209
- // TODO vstorage update?
223
+ // TODO vstorage update? We don't currently have a status for
224
+ // Advanced + transferV settled
210
225
log (
211
226
'Advance transfer fulfilled' ,
212
227
q ( { amount, destination, result } ) . toString ( ) ,
213
228
) ;
214
229
} ,
215
230
onRejected ( error ) {
216
- // XXX retry logic?
217
- // What do we do if we fail, should we keep a Status?
231
+ // TODO #10510 (comprehensive error testing) determine
232
+ // course of action here. This might fail due to timeout.
218
233
log ( 'Advance transfer rejected' , q ( error ) . toString ( ) ) ;
219
234
} ,
220
235
} ,
221
236
} ,
222
237
{
223
238
stateShape : harden ( {
224
- assetManagerFacet : M . remotable ( ) ,
225
- poolAccount : M . or ( VowShape , M . remotable ( ) ) ,
239
+ borrowerFacet : M . remotable ( ) ,
240
+ poolAccount : M . remotable ( ) ,
226
241
} ) ,
227
242
} ,
228
243
) ;
0 commit comments