Skip to content

Commit

Permalink
feat: restake example contract
Browse files Browse the repository at this point in the history
- A contract that allows calls to make an OrchestrationAccount, and
 subsequently schedule a restake (claim and stake rewards) on an interval.
- Leverages existing invitation makers like Delegate and combines them with
 Restake and CancelRestake.
  • Loading branch information
0xpatrickdev committed Aug 1, 2024
1 parent e54e0a1 commit d6f9b7a
Show file tree
Hide file tree
Showing 4 changed files with 577 additions and 0 deletions.
94 changes: 94 additions & 0 deletions packages/orchestration/src/examples/restake.contract.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
import { M } from '@endo/patterns';
import { withOrchestration } from '../utils/start-helper.js';
import * as flows from './restake.flows.js';
import {
prepareRestakeHolderKit,
prepareRestakeWaker,
restakeInvitaitonGuardShape,
} from './restake.kit.js';
import { prepareCombineInvitationMakers } from '../exos/combine-invitation-makers.js';

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

/**
* XXX consider moving to privateArgs / creatorFacet, as terms are immutable
*
* @typedef {{
* minimumDelay: bigint;
* minimumInterval: bigint;
* }} RestakeContractTerms
*/

/**
* A contract that allows calls to make an OrchestrationAccount, and
* subsequently schedule a restake (claim and stake rewards) on an interval.
*
* Leverages existing invitation makers like Delegate and combines them with
* Restake and CancelRestake.
*
* @param {ZCF<RestakeContractTerms>} zcf
* @param {OrchestrationPowers & {
* marshaller: Marshaller;
* }} privateArgs
* @param {Zone} zone
* @param {OrchestrationTools} tools
*/
const contract = async (
zcf,
{ timerService },
zone,
{ orchestrateAll, vowTools },
) => {
const makeRestakeWaker = prepareRestakeWaker(
zone.subZone('restakeWaker'),
vowTools,
);
const makeCombineInvitationMakers = prepareCombineInvitationMakers(
zone,
restakeInvitaitonGuardShape,
);

const { minimumDelay, minimumInterval } = zcf.getTerms();

const makeRestakeHolderKit = prepareRestakeHolderKit(
zone.subZone('restakeHolder'),
{
vowTools,
zcf,
timer: timerService,
makeRestakeWaker,
params: harden({ minimumDelay, minimumInterval }),
},
);

const orchFns = orchestrateAll(flows, {
makeRestakeHolderKit,
makeCombineInvitationMakers,
});

const publicFacet = zone.exo(
'Restake Public Facet',
M.interface('Restake PF', {
makeRestakeAccountInvitation: M.callWhen().returns(InvitationShape),
}),
{
makeRestakeAccountInvitation() {
return zcf.makeInvitation(
orchFns.makeRestakeAccount,
'Make a Restake Account',
);
},
},
);

return { publicFacet };
};

export const start = withOrchestration(contract);

/** @typedef {typeof start} RestakeSF */
53 changes: 53 additions & 0 deletions packages/orchestration/src/examples/restake.flows.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* @file Example contract that allows users to do different things with rewards
*/
import { M, mustMatch } from '@endo/patterns';

/**
* @import {OrchestrationAccount, OrchestrationFlow, Orchestrator, StakingAccountActions} from '@agoric/orchestration';
* @import {MakeRestakeHolderKit} from './restake.kit.js';
* @import {MakeCombineInvitationMakers} from '../exos/combine-invitation-makers.js';
*/

/**
* Create an OrchestrationAccount for a specific chain and return a continuing
* offer with invitations makers for Delegate, WithdrawRewards, Transfer, etc.
*
* @satisfies {OrchestrationFlow}
* @param {Orchestrator} orch
* @param {{
* makeRestakeHolderKit: MakeRestakeHolderKit;
* makeCombineInvitationMakers: MakeCombineInvitationMakers;
* }} ctx
* @param {ZCFSeat} seat
* @param {{ chainName: string }} offerArgs
*/
export const makeRestakeAccount = async (
orch,
{ makeRestakeHolderKit, makeCombineInvitationMakers },
seat,
{ chainName },
) => {
seat.exit(); // no funds exchanged
mustMatch(chainName, M.string());
const remoteChain = await orch.getChain(chainName);
const orchAccount =
/** @type {OrchestrationAccount<any> & StakingAccountActions} */ (
await remoteChain.makeAccount()
);
const restakeHolderKit = makeRestakeHolderKit(orchAccount);
const { invitationMakers: orchInvitationMakers, publicSubscribers } =
await orchAccount.asContinuingOffer();

const combinedInvitationMakers = makeCombineInvitationMakers(
// `orchInvitationMakers` currently lying about its type
orchInvitationMakers,
// @ts-expect-error update `makeCombineInvitationMakers` to accept Guarded...
restakeHolderKit.invitationMakers,
);

return harden({
invitationMakers: combinedInvitationMakers,
publicSubscribers,
});
};
Loading

0 comments on commit d6f9b7a

Please sign in to comment.