From b0ec75a8809392acd20129c547bd542ca3c83265 Mon Sep 17 00:00:00 2001 From: 0xPatrick Date: Wed, 13 Nov 2024 15:44:32 -0500 Subject: [PATCH] feat: integrate advancer in StartFn --- packages/fast-usdc/src/exos/advancer.js | 26 ++++----- packages/fast-usdc/src/fast-usdc.contract.js | 51 ++++++++++++------ packages/fast-usdc/src/fast-usdc.flows.js | 15 ++++++ .../snapshots/fast-usdc.contract.test.ts.md | 49 ++++++++++++++--- .../snapshots/fast-usdc.contract.test.ts.snap | Bin 1630 -> 2104 bytes 5 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 packages/fast-usdc/src/fast-usdc.flows.js diff --git a/packages/fast-usdc/src/exos/advancer.js b/packages/fast-usdc/src/exos/advancer.js index 409a71cb37a9..0180392ef99f 100644 --- a/packages/fast-usdc/src/exos/advancer.js +++ b/packages/fast-usdc/src/exos/advancer.js @@ -16,20 +16,11 @@ const { isGTE } = AmountMath; * @import {HostInterface} from '@agoric/async-flow'; * @import {NatAmount} from '@agoric/ertp'; * @import {ChainAddress, ChainHub, Denom, DenomAmount, OrchestrationAccount} from '@agoric/orchestration'; - * @import {VowTools} from '@agoric/vow'; + * @import {Vow, VowTools} from '@agoric/vow'; * @import {Zone} from '@agoric/zone'; * @import {CctpTxEvidence, FeeConfig, LogFn} from '../types.js'; * @import {StatusManager} from './status-manager.js'; - */ - -/** - * Expected interface from LiquidityPool - * - * @typedef {{ - * lookupBalance(): NatAmount; - * borrow(amount: Amount<"nat">): Promise>; - * repay(payments: PaymentKeywordRecord): Promise - * }} AssetManagerFacet + * @import {AssetManagerFacet} from './liquidity-pool.js'; */ /** @@ -96,7 +87,7 @@ export const prepareAdvancerKit = ( /** * @param {{ * assetManagerFacet: AssetManagerFacet; - * poolAccount: ERef>>; + * poolAccount: Vow>> | HostInterface>; * }} config */ config => harden(config), @@ -115,8 +106,9 @@ export const prepareAdvancerKit = ( async handleTransactionEvent(evidence) { await null; try { - // TODO poolAccount might be a vow we need to unwrap - const { assetManagerFacet, poolAccount } = this.state; + const { assetManagerFacet } = this.state; + // TODO is there a better way than this? + const poolAccount = await when(this.state.poolAccount); const { recipientAddress } = evidence.aux; const { EUD } = addressTools.getQueryParams( recipientAddress, @@ -177,7 +169,11 @@ export const prepareAdvancerKit = ( * @param {{ destination: ChainAddress; payment: Payment<'nat'> }} ctx */ onFulfilled(amount, { destination }) { - const { poolAccount } = this.state; + // TODO do we need to ensure this isn't Vow for an LOA? + const poolAccount = + /** @type {HostInterface>} */ ( + this.state.poolAccount + ); const transferV = E(poolAccount).transfer( destination, /** @type {DenomAmount} */ ({ diff --git a/packages/fast-usdc/src/fast-usdc.contract.js b/packages/fast-usdc/src/fast-usdc.contract.js index d04cf523585a..0a8d44f8cd80 100644 --- a/packages/fast-usdc/src/fast-usdc.contract.js +++ b/packages/fast-usdc/src/fast-usdc.contract.js @@ -12,12 +12,16 @@ import { prepareStatusManager } from './exos/status-manager.js'; import { prepareTransactionFeedKit } from './exos/transaction-feed.js'; import { defineInertInvitation } from './utils/zoe.js'; import { FeeConfigShape } from './typeGuards.js'; +import * as flows from './fast-usdc.flows.js'; const trace = makeTracer('FastUsdc'); /** * @import {Denom} from '@agoric/orchestration'; + * @import {HostInterface} from '@agoric/async-flow'; + * @import {OrchestrationAccount} from '@agoric/orchestration'; * @import {OrchestrationPowers, OrchestrationTools} from '@agoric/orchestration/src/utils/start-helper.js'; + * @import {Vow} from '@agoric/vow'; * @import {Zone} from '@agoric/zone'; * @import {OperatorKit} from './exos/operator-kit.js'; * @import {CctpTxEvidence, FeeConfig} from './types.js'; @@ -59,7 +63,7 @@ export const contract = async (zcf, privateArgs, zone, tools) => { const statusManager = prepareStatusManager(zone); const makeSettler = prepareSettler(zone, { statusManager }); - const { chainHub, vowTools } = tools; + const { chainHub, orchestrateAll, vowTools } = tools; const makeAdvancer = prepareAdvancer(zone, { chainHub, feeConfig: privateArgs.feeConfig, @@ -73,21 +77,6 @@ export const contract = async (zcf, privateArgs, zone, tools) => { }); const makeFeedKit = prepareTransactionFeedKit(zone, zcf); assertAllDefined({ makeFeedKit, makeAdvancer, makeSettler, statusManager }); - const feedKit = makeFeedKit(); - const advancer = makeAdvancer( - // @ts-expect-error FIXME - {}, - ); - // Connect evidence stream to advancer - void observeIteration(subscribeEach(feedKit.public.getEvidenceSubscriber()), { - updateState(evidence) { - try { - void advancer.handleTransactionEvent(evidence); - } catch (err) { - trace('🚨 Error handling transaction event', err); - } - }, - }); const makeLiquidityPoolKit = prepareLiquidityPoolKit(zone, { zcf, usdc: { @@ -105,6 +94,7 @@ export const contract = async (zcf, privateArgs, zone, tools) => { const creatorFacet = zone.exo('Fast USDC Creator', undefined, { /** @type {(operatorId: string) => Promise>} */ async makeOperatorInvitation(operatorId) { + // eslint-disable-next-line no-use-before-define return feedKit.creator.makeOperatorInvitation(operatorId); }, simulateFeesFromAdvance(/* amount, payment */) { @@ -113,6 +103,7 @@ export const contract = async (zcf, privateArgs, zone, tools) => { // return poolKit.feeSink.receive(amount, payment); }, }); + const { makeLocalAccount } = orchestrateAll(flows, {}); const publicFacet = zone.exo('Fast USDC Public', undefined, { // XXX to be removed before production @@ -126,6 +117,7 @@ export const contract = async (zcf, privateArgs, zone, tools) => { * @param {CctpTxEvidence} evidence */ makeTestPushInvitation(evidence) { + // eslint-disable-next-line no-use-before-define void advancer.handleTransactionEvent(evidence); return makeTestInvitation(); }, @@ -169,6 +161,33 @@ export const contract = async (zcf, privateArgs, zone, tools) => { makeLiquidityPoolKit(shareMint, privateArgs.storageNode), ); + const poolAccount = + // cast to HostInterface + /** @type { Vow>>} */ ( + /** @type {unknown}*/ ( + zone.makeOnce('Pool Local Orch Account', () => makeLocalAccount()) + ) + ); + + const advancer = zone.makeOnce('Advancer', () => + makeAdvancer({ + assetManagerFacet: poolKit.assetManager, + poolAccount, + }), + ); + + const feedKit = zone.makeOnce('Feed Kit', () => makeFeedKit()); + // Connect evidence stream to advancer + void observeIteration(subscribeEach(feedKit.public.getEvidenceSubscriber()), { + updateState(evidence) { + try { + void advancer.handleTransactionEvent(evidence); + } catch (err) { + trace('🚨 Error handling transaction event', err); + } + }, + }); + return harden({ creatorFacet, publicFacet }); }; harden(contract); diff --git a/packages/fast-usdc/src/fast-usdc.flows.js b/packages/fast-usdc/src/fast-usdc.flows.js new file mode 100644 index 000000000000..d9ce603f739a --- /dev/null +++ b/packages/fast-usdc/src/fast-usdc.flows.js @@ -0,0 +1,15 @@ +/** + * @import {HostInterface} from '@agoric/async-flow'; + * @import {Orchestrator, OrchestrationFlow, OrchestrationAccount} from '@agoric/orchestration'; + */ + +/** + * @satisfies {OrchestrationFlow}w + * @param {Orchestrator} orch + * @returns {Promise>} + */ +export const makeLocalAccount = async orch => { + const agoricChain = await orch.getChain('agoric'); + return agoricChain.makeAccount(); +}; +harden(makeLocalAccount); diff --git a/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.md b/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.md index 481595307e12..c715ab0b1d30 100644 --- a/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.md +++ b/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.md @@ -22,17 +22,34 @@ Generated by [AVA](https://avajs.dev). }, LogStore_kindHandle: 'Alleged: kind', StateUnwrapper_kindHandle: 'Alleged: kind', - asyncFuncEagerWakers: [], + asyncFuncEagerWakers: [ + Object @Alleged: asyncFlow flow {}, + ], asyncFuncFailures: {}, - flowForOutcomeVow: {}, + flowForOutcomeVow: { + 'Alleged: VowInternalsKit vowV0': 'Alleged: asyncFlow flow', + }, unwrapMap: 'Alleged: weakMapStore', }, chainHub: { ChainHub_kindHandle: 'Alleged: kind', ChainHub_singleton: 'Alleged: ChainHub', - bech32PrefixToChainName: {}, + bech32PrefixToChainName: { + agoric: 'agoric', + }, brandDenom: {}, - chainInfos: {}, + chainInfos: { + agoric: { + bech32Prefix: 'agoric', + chainId: 'agoric-3', + icqEnabled: false, + stakingTokens: [ + { + denom: 'ubld', + }, + ], + }, + }, connectionInfos: {}, denom: {}, lookupChainInfo_kindHandle: 'Alleged: kind', @@ -40,6 +57,7 @@ Generated by [AVA](https://avajs.dev). lookupConnectionInfo_kindHandle: 'Alleged: kind', }, contract: { + Advancer: 'Alleged: Fast USDC Advancer advancer', 'Fast USDC Advancer_kindHandle': 'Alleged: kind', 'Fast USDC Creator_kindHandle': 'Alleged: kind', 'Fast USDC Creator_singleton': 'Alleged: Fast USDC Creator', @@ -49,6 +67,11 @@ Generated by [AVA](https://avajs.dev). 'Fast USDC Settler_kindHandle': 'Alleged: kind', 'Fast USDC Status Manager_kindHandle': 'Alleged: kind', 'Fast USDC Status Manager_singleton': 'Alleged: Fast USDC Status Manager', + 'Feed Kit': { + creator: Object @Alleged: Fast USDC Feed creator {}, + operatorPowers: Object @Alleged: Fast USDC Feed operatorPowers {}, + public: Object @Alleged: Fast USDC Feed public {}, + }, Kinds: { 'Transaction Feed_kindHandle': 'Alleged: kind', }, @@ -62,12 +85,17 @@ Generated by [AVA](https://avajs.dev). 'Liquidity Pool_kindHandle': 'Alleged: kind', 'Operator Kit_kindHandle': 'Alleged: kind', PendingTxs: {}, + 'Pool Local Orch Account': 'Vow', SeenTxs: [], mint: { PoolShare: 'Alleged: zcfMint', }, operators: {}, - orchestration: {}, + orchestration: { + makeLocalAccount: { + asyncFlow_kindHandle: 'Alleged: kind', + }, + }, pending: {}, vstorage: { 'Durable Publish Kit_kindHandle': 'Alleged: kind', @@ -80,7 +108,16 @@ Generated by [AVA](https://avajs.dev). LocalChainFacade_kindHandle: 'Alleged: kind', Orchestrator_kindHandle: 'Alleged: kind', RemoteChainFacade_kindHandle: 'Alleged: kind', - chainName: {}, + chainName: { + agoric: { + pending: true, + vow: Object @Vow { + payload: { + vowV0: Object @Alleged: VowInternalsKit vowV0 {}, + }, + }, + }, + }, ibcTools: { IBCTransferSenderKit_kindHandle: 'Alleged: kind', ibcResultWatcher_kindHandle: 'Alleged: kind', diff --git a/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.snap b/packages/fast-usdc/test/snapshots/fast-usdc.contract.test.ts.snap index 4e23a1fae211721c76076420ffbcab517cbd22d7..16e9b392c898427db6d119fbe006985a4795a164 100644 GIT binary patch literal 2104 zcmV-82*>w9RzV#x$Iiu0+PdBB76MsTTZxqr5=zsCmNso@ z+AI}9Wqi)WIrYgI_nhOnK~%d%T9DX>U4-CaA1bJLSh3n7B!m`m5fZ#0frM5dgoFeS zh>KuB%L_tKU_Hk^o-@bs#^Hgy#PR?A-~9i~{I|)Mw`wNW8qVGO%r#t-)oZj~r*&pH z7HvA)+;#5W*LCXB>vQcWlIZ-96iKZDxCr1y06zloTLAwCFiU`^2v8)60!du1-DH|e zi2pI4&x2$^k{}Z(l1Pa}LE;5+^i0d9HIr4>TQ$>gwyPHm_eR68^mEkGP1b{Dmraw^ znf|_NN2YKTuP}|?ME~6TnXsKqaYA zrBtff8%cmAfv+ZkHPN`K&_m zs7jH1ISV{^3;t#nSk3{@=78_#fPdx`)uqr49anBwd0F2vtmWQ48TE3`D(a45)lKGd zs|T3zwS!27r*zurSZQ!;R14-;Tb59~X0>hFY#u010t|CuhL9T-pCAMlad2{?9|!r1 zyuRUbo2@aIc5;jw&^`I6hL$&6>atP%%n@=)vaICggO;V8rFCXMO&iR11j><61s}Ca z4YOr45Arz~vSsr2Dz`7UT#fIr&Cq#{wS<*xwAuS+$~UdeXk(2w#TJM=nN~MwrJI{Z z-JnTdF?4_hUvEWDe6LAP&D5B-ed@_|n{64luX2IAM0c0~{#pX2Yc{p?GtA;ULiSLW ziM)E=+Tz}>E#&*M35{Epcgy>L(-I)Adz=BMDkkTRR&%AtJL;w^NczsQrLXu#jLLMZ z%M|e903=zE8HFmftnX4wW43Q)KftKtRQ`?&DzUKlBG;%{y=-gS)n!fN zEz9l6qnq7cGgIi(B{vwe1Xrh0N`lyqVR@T&N&0q-ca8TH%)-zP^z-sUP0wy2__`!W z?K&>EY2B+gDaEPBSGcpo9pR8q-t(+_j++N-z5|?#{XGg(9%2fZ6MQ0xuTqWbBR3B- zeN#qHa`RW%4tLpT%jXFBm3*vPprA%4rQGB?3mKwrAVYb3EY`fri`dMphWIX0$=ID;>)&8_eiYwX<}lc6N3SY zM2Obn^s|oKNf+%7J+ODSSkS@ECDx4irUOjQ;!UkcF*i+@XSc$*%I(+b%A3; z7pR7ud#wa~PbE1%l;jbWB>I~Y@VgSQIHeFRgx1rh07Hd67CNH4Q^04YfFDl**=Ys- zt`O_>Y2bzmd-qT;9uJMomtGQ7UHWI#CSwNGKAcl7SB`z)Q z5gx|WNB1LF(cJwt=H`42zg2pk)hMM`xwl z#cq4sEhHbC9bkN?OOd{xXdCXfZqv3;Il#NIPNTK4O>N(oyzk2=w5>JKIQd8MxJhcaFPG>%cO7WKW6v6HNj!?{OJ{O!duMVV3yA8!*oqXO}oOJmgye07>5Xk z%tI=6;K7#H`yI`}JW`U#kT~w9ruae`SS$nA%D|m6aIdVSsqvv{s#qY$224R>%IQY( zAhl9~Jhq=&FwO^QPsv$K(e?sqkk+jHa-d9Aa##=2Ez9;Qy1}3yq+KbH>VDe2lrTtd zPWDsL+uzUm0y(*#mXc0-_3681;0Nl#p9s~_hh-pI0ghJ`=*dvAiYZrlTz)VM#dH9g z^q$3ZKWloZrBiDCGqhW0txjU{ppm>t8t<)0Goa(rMrSzX4Q4q5W2{6+c+Vb?9D8%5 zXTpRq;iHlX(cNx4{7eOSt`h8Xvue-uLIwDOy1Vc2W@WLpet~~bkqUf{ke^rN*_Q5^ zoa%z|UlkxSr%>iXEy}_iu&Bb``L<1n_YCO|>8+Y6C-CJt>3u`A7opp___iHMKA&eM itugcVeDB{))$YIOs&va`cGYpI?fw_x!@C*B8vp=($rsH4 literal 1630 zcmV-k2BG;uRzV-P1VOd8T;l`^eVXoVRzr!{*`Nc;LtU8j;>9@+9E zjK&{{kjN~6IRI|~_!_{^0R9GWkN{5-AWuSB5?Uy~$TUev>)%W!1Cj&@gQSrsz5?-s z1heGuOx>bolNA^1Wz(?Niq9DGg>{4L=P1`r)}$q;Op{fZex}&K6pj26(}blnYXHL( zA@c-i!cl5(b8XfXn-27W2a0HG)ZpjpWe2(2fe0=ws!0cV-q%Kw!qV25EiEby!5#R9 z2M%nAO}mlB0DKz&{s;gEg23sZl38D8W+NnC z3j!NK;Nu{0HwY9$z+)j`E(BCVz-uAk%Mg$XD^g)qYNQkfE{B2l!oUw<;Nb|c9sxdz z0QVxmnJDmT6!PE4RvV}{Ius_l z6}rM0ZwYjfo!Wmr)vo=_oT!wfu-H74v@uuICT`-xIyzR8RI*{>OcC;l$FqVv1L|CR znpT)~iLNutc39tdSlJe9mKtW=VlL%3FJ;vfo3p}Ns7p;$*~PB=jMg15=V`6^WTfTV zCZp@~wC1G1smYj{py}OtG;D%$EyJ!0%(m>Ny~8e&ZU;45X4=}x#}_TOYHTeFhj)Qi znL|9`A;!uU<@yZcqUvBXUd)-L=lQB|vsU(CX-#nMR(YH7iiZ%?UCoZ5#!VsC>$T~o z?yyNY?yo- zN8@)X^lN;TtafLcFw2@h*X`V8(g`<8t@TZHY-~4u3ljcoZa+b-OrE zd1L4dD|Bp6p|0?b_6V=j#_72Cy&d>kC=W^%!Ms zSqRg;@JBsJyhgQkCU?OkNJt&q&Jwr8q_y4nl-bY5IN3v@tCJ@>x5f^(+K7vms2VoA zM5VSieC3Q^6r1O{WEQ8Uy^l&6an4#r#Vp`yOzxFFMv29akgvf0_es=YYRd zCnov|9a4n?r}Ds=Ja8=!e34hg4tHHhq5$Ly3hhYWGmmzCmlCC~Vim@jJII|!0raFz zEL)V@)Y(P{UAvMXL8ld;Ewo!PL2a8!@0#$22Tkd$CTv5x!Y+QtgGbnwJ3<`9Khj1* zwcY(HMaXH-^Yo@6*K~_+wj_H*7j3K-r8R1`V#%~(xvH(sJMZ%(i0^;?sVRvD(D|)! z{_M1KH>=DlF|IRfKd)h