Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(localOrchAccount): Deposit, Withdraw invitationMakers #10117

Merged
merged 2 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions packages/orchestration/src/examples/send-anywhere.contract.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { makeSharedStateRecord } from '@agoric/async-flow';
import { AmountShape } from '@agoric/ertp';
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
import { M } from '@endo/patterns';
import { withOrchestration } from '../utils/start-helper.js';
import * as flows from './send-anywhere.flows.js';
import { prepareChainHubAdmin } from '../exos/chain-hub-admin.js';
import { AnyNatAmountShape } from '../typeGuards.js';

/**
* @import {Zone} from '@agoric/zone';
* @import {OrchestrationPowers, OrchestrationTools} from '../utils/start-helper.js';
*/

export const SingleAmountRecord = M.and(
M.recordOf(M.string(), AmountShape, {
export const SingleNatAmountRecord = M.and(
M.recordOf(M.string(), AnyNatAmountShape, {
numPropertiesLimit: 1,
}),
M.not(harden({})),
);
harden(SingleAmountRecord);
harden(SingleNatAmountRecord);

/**
* Orchestration contract to be wrapped by withOrchestration for Zoe
Expand Down Expand Up @@ -61,7 +61,7 @@ const contract = async (
orchFns.sendIt,
'send',
undefined,
M.splitRecord({ give: SingleAmountRecord }),
M.splitRecord({ give: SingleNatAmountRecord }),
);
},
},
Expand Down
3 changes: 3 additions & 0 deletions packages/orchestration/src/examples/stakeBld.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { M } from '@endo/patterns';
import { makeChainHub } from '../exos/chain-hub.js';
import { prepareLocalOrchestrationAccountKit } from '../exos/local-orchestration-account.js';
import fetchedChainInfo from '../fetched-chain-info.js';
import { makeZoeTools } from '../utils/zoe-tools.js';

/**
* @import {NameHub} from '@agoric/vats';
Expand Down Expand Up @@ -43,6 +44,7 @@ export const start = async (zcf, privateArgs, baggage) => {
const vowTools = prepareVowTools(zone.subZone('vows'));

const chainHub = makeChainHub(privateArgs.agoricNames, vowTools);
const zoeTools = makeZoeTools(zcf, vowTools);

const { localchain, timerService } = privateArgs;
const makeLocalOrchestrationAccountKit = prepareLocalOrchestrationAccountKit(
Expand All @@ -54,6 +56,7 @@ export const start = async (zcf, privateArgs, baggage) => {
vowTools,
chainHub,
localchain,
zoeTools,
},
);

Expand Down
85 changes: 82 additions & 3 deletions packages/orchestration/src/exos/local-orchestration-account.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Fail, q } from '@endo/errors';

import {
AmountArgShape,
AnyNatAmountsRecord,
ChainAddressShape,
DenomAmountShape,
DenomShape,
Expand Down Expand Up @@ -39,6 +40,7 @@ import { coerceCoin, coerceDenomAmount } from '../utils/amounts.js';
* @import {Matcher} from '@endo/patterns';
* @import {ChainHub} from './chain-hub.js';
* @import {PacketTools} from './packet-tools.js';
* @import {ZoeTools} from '../utils/zoe-tools.js';
*/

const trace = makeTracer('LOA');
Expand Down Expand Up @@ -91,10 +93,19 @@ const PUBLIC_TOPICS = {
* @param {VowTools} powers.vowTools
* @param {ChainHub} powers.chainHub
* @param {Remote<LocalChain>} powers.localchain
* @param {ZoeTools} powers.zoeTools
*/
export const prepareLocalOrchestrationAccountKit = (
zone,
{ makeRecorderKit, zcf, timerService, vowTools, chainHub, localchain },
{
makeRecorderKit,
zcf,
timerService,
vowTools,
chainHub,
localchain,
zoeTools,
},
) => {
const { watch, allVows, asVow, when } = vowTools;
const { makeIBCTransferSender } = prepareIBCTools(
Expand Down Expand Up @@ -139,6 +150,12 @@ export const prepareLocalOrchestrationAccountKit = (
returnVoidWatcher: M.interface('returnVoidWatcher', {
onFulfilled: M.call(M.any()).optional(M.any()).returns(M.undefined()),
}),
seatExiterHandler: M.interface('seatExiterHandler', {
onFulfilled: M.call(M.undefined(), M.remotable()).returns(
M.undefined(),
),
onRejected: M.call(M.error(), M.remotable()).returns(M.undefined()),
}),
getBalanceWatcher: M.interface('getBalanceWatcher', {
onFulfilled: M.call(AmountShape, DenomShape).returns(DenomAmountShape),
}),
Expand All @@ -151,12 +168,14 @@ export const prepareLocalOrchestrationAccountKit = (
),
}),
invitationMakers: M.interface('invitationMakers', {
Delegate: M.call(M.string(), AmountShape).returns(M.promise()),
Undelegate: M.call(M.string(), AmountShape).returns(M.promise()),
CloseAccount: M.call().returns(M.promise()),
Delegate: M.call(M.string(), AmountShape).returns(M.promise()),
Deposit: M.call().returns(M.promise()),
Send: M.call().returns(M.promise()),
SendAll: M.call().returns(M.promise()),
Transfer: M.call().returns(M.promise()),
Undelegate: M.call(M.string(), AmountShape).returns(M.promise()),
Withdraw: M.call().returns(M.promise()),
}),
},
/**
Expand Down Expand Up @@ -200,6 +219,27 @@ export const prepareLocalOrchestrationAccountKit = (
);
}, 'Delegate');
},
Deposit() {
trace('Deposit');
return zcf.makeInvitation(
seat => {
const { give } = seat.getProposal();
return watch(
zoeTools.localTransfer(
seat,
// @ts-expect-error LocalAccount vs LocalAccountMethods
this.state.account,
give,
),
this.facets.seatExiterHandler,
seat,
);
},
'Deposit',
undefined,
M.splitRecord({ give: AnyNatAmountsRecord, want: {} }),
);
Comment on lines +227 to +241
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given zoeTools.localTransfer is expected to resolve promptly, we technically do not need to use watch here and instead could use asVow.

This approach seems harmless, and appeases the linter. It also allows a developer to call Deposit() inside an async-flow if they wished.

},
/**
* @param {string} validatorAddress
* @param {Amount<'nat'>} ertpAmount
Expand Down Expand Up @@ -262,6 +302,27 @@ export const prepareLocalOrchestrationAccountKit = (
};
return zcf.makeInvitation(offerHandler, 'Transfer');
},
Withdraw() {
trace('Withdraw');
return zcf.makeInvitation(
seat => {
const { want } = seat.getProposal();
return watch(
zoeTools.withdrawToSeat(
// @ts-expect-error LocalAccount vs LocalAccountMethods
this.state.account,
seat,
want,
),
this.facets.seatExiterHandler,
seat,
);
},
'Withdraw',
undefined,
M.splitRecord({ give: {}, want: AnyNatAmountsRecord }),
);
},
},
undelegateWatcher: {
/**
Expand Down Expand Up @@ -362,6 +423,24 @@ export const prepareLocalOrchestrationAccountKit = (
return harden({ denom, value: natAmount.value });
},
},
/** exits or fails a seat depending the outcome */
seatExiterHandler: {
/**
* @param {undefined} _
* @param {ZCFSeat} seat
*/
onFulfilled(_, seat) {
seat.exit();
},
/**
* @param {Error} reason
* @param {ZCFSeat} seat
*/
onRejected(reason, seat) {
seat.exit(reason);
throw reason;
},
},
/**
* handles a QueryBalanceRequest from localchain.query and returns the
* balance as a DenomAmount
Expand Down
10 changes: 10 additions & 0 deletions packages/orchestration/src/typeGuards.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,13 @@ export const TxBodyOptsShape = M.splitRecord(
nonCriticalExtensionOptions: M.arrayOf(M.any()),
},
);

/**
* Ensures at least one {@link AmountKeywordRecord} entry is present and only
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clever

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h/t SingleNatAmountRecord fka SingleAmountRecord from send-anywhere

* permits Nat (fungible) amounts.
*/
export const AnyNatAmountsRecord = M.and(
M.recordOf(M.string(), AnyNatAmountShape),
M.not(harden({})),
);
harden(AnyNatAmountsRecord);
10 changes: 9 additions & 1 deletion packages/orchestration/src/utils/start-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,15 @@ export const provideOrchestration = (
const { makeRecorderKit } = prepareRecorderKitMakers(baggage, marshaller);
const makeLocalOrchestrationAccountKit = prepareLocalOrchestrationAccountKit(
zones.orchestration,
{ makeRecorderKit, zcf, timerService, vowTools, chainHub, localchain },
{
makeRecorderKit,
zcf,
timerService,
vowTools,
chainHub,
localchain,
zoeTools,
},
);

const asyncFlowTools = prepareAsyncFlowTools(zones.asyncFlow, {
Expand Down
Loading
Loading