From aa79cd5e8eb808a6efa503f19783e64397fbbc03 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 2 May 2024 19:10:01 -0500 Subject: [PATCH] refactor: refine StakingAccountHolder facets - implement delegate() etc. directly on holder; - avoids unguarded helper methods - since these methods don't have multiple callers, it makes little sense to put them on the helper facet anyway - call zcf.makeInvitation() directly from invitationMaker facet methods; prune makeXInvitation methods on holder --- .../src/exos/stakingAccountKit.js | 136 +++++++----------- .../test/test-withdraw-reward.js | 6 +- 2 files changed, 56 insertions(+), 86 deletions(-) diff --git a/packages/orchestration/src/exos/stakingAccountKit.js b/packages/orchestration/src/exos/stakingAccountKit.js index 02416c0c48d..0083a6bf717 100644 --- a/packages/orchestration/src/exos/stakingAccountKit.js +++ b/packages/orchestration/src/exos/stakingAccountKit.js @@ -42,11 +42,8 @@ const { Fail } = assert; const HolderI = M.interface('holder', { getPublicTopics: M.call().returns(TopicsRecordShape), - makeDelegateInvitation: M.call(M.string(), AmountShape).returns(M.promise()), - makeWithdrawRewardInvitation: M.call(M.string()).returns(M.promise()), - makeCloseAccountInvitation: M.call().returns(M.promise()), - makeTransferAccountInvitation: M.call().returns(M.promise()), delegate: M.callWhen(M.string(), AmountShape).returns(M.record()), + withdrawReward: M.callWhen(M.string()).returns(M.array()), }); /** @type {{ [name: string]: [description: string, valueShape: Pattern] }} */ @@ -94,12 +91,10 @@ export const prepareStakingAccountKit = (baggage, makeRecorderKit, zcf) => { helper: UnguardedHelperI, holder: HolderI, invitationMakers: M.interface('invitationMakers', { - Delegate: HolderI.payload.methodGuards.makeDelegateInvitation, - WithdrawReward: - HolderI.payload.methodGuards.makeWithdrawRewardInvitation, - CloseAccount: HolderI.payload.methodGuards.makeCloseAccountInvitation, - TransferAccount: - HolderI.payload.methodGuards.makeTransferAccountInvitation, + Delegate: M.call(M.string(), AmountShape).returns(M.promise()), + WithdrawReward: M.call(M.string()).returns(M.promise()), + CloseAccount: M.call().returns(M.promise()), + TransferAccount: M.call().returns(M.promise()), }), }, /** @@ -127,6 +122,52 @@ export const prepareStakingAccountKit = (baggage, makeRecorderKit, zcf) => { getUpdater() { return this.state.topicKit.recorder; }, + }, + invitationMakers: { + /** + * + * @param {string} validatorAddress + * @param {Amount<'nat'>} amount + */ + Delegate(validatorAddress, amount) { + trace('Delegate', validatorAddress, amount); + + return zcf.makeInvitation(async seat => { + seat.exit(); + return this.facets.holder.delegate(validatorAddress, amount); + }, 'Delegate'); + }, + /** @param {string} validatorAddress */ + WithdrawReward(validatorAddress) { + trace('WithdrawReward', validatorAddress); + + return zcf.makeInvitation(async seat => { + seat.exit(); + return this.facets.holder.withdrawReward(validatorAddress); + }, 'WithdrawReward'); + }, + CloseAccount() { + throw Error('not yet implemented'); + }, + /** + * Starting a transfer revokes the account holder. The associated updater + * will get a special notification that the account is being transferred. + */ + TransferAccount() { + throw Error('not yet implemented'); + }, + }, + holder: { + getPublicTopics() { + const { topicKit } = this.state; + return harden({ + account: { + description: PUBLIC_TOPICS.account[0], + subscriber: topicKit.subscriber, + storagePath: topicKit.recorder.getStoragePath(), + }, + }); + }, // TODO move this beneath the Orchestration abstraction, // to the OrchestrationAccount provided by makeAccount() /** @@ -135,6 +176,8 @@ export const prepareStakingAccountKit = (baggage, makeRecorderKit, zcf) => { * @param {Amount<'nat'>} ertpAmount */ async delegate(validatorAddress, ertpAmount) { + trace('delegate', validatorAddress, ertpAmount); + // FIXME get values from proposal or args // FIXME brand handling and amount scaling trace('TODO: handle brand', ertpAmount); @@ -180,79 +223,6 @@ export const prepareStakingAccountKit = (baggage, makeRecorderKit, zcf) => { return harden(coins.map(toChainAmount)); }, }, - invitationMakers: { - Delegate(validatorAddress, amount) { - return this.facets.holder.makeDelegateInvitation( - validatorAddress, - amount, - ); - }, - /** @param {string} validatorAddress */ - WithdrawReward(validatorAddress) { - return this.facets.holder.makeWithdrawRewardInvitation( - validatorAddress, - ); - }, - CloseAccount() { - return this.facets.holder.makeCloseAccountInvitation(); - }, - TransferAccount() { - return this.facets.holder.makeTransferAccountInvitation(); - }, - }, - holder: { - getPublicTopics() { - const { topicKit } = this.state; - return harden({ - account: { - description: PUBLIC_TOPICS.account[0], - subscriber: topicKit.subscriber, - storagePath: topicKit.recorder.getStoragePath(), - }, - }); - }, - /** - * - * @param {string} validatorAddress - * @param {Amount<'nat'>} ertpAmount - */ - async delegate(validatorAddress, ertpAmount) { - trace('delegate', validatorAddress, ertpAmount); - return this.facets.helper.delegate(validatorAddress, ertpAmount); - }, - /** - * - * @param {string} validatorAddress - * @param {Amount<'nat'>} ertpAmount - */ - makeDelegateInvitation(validatorAddress, ertpAmount) { - trace('makeDelegateInvitation', validatorAddress, ertpAmount); - - return zcf.makeInvitation(async seat => { - seat.exit(); - return this.facets.helper.delegate(validatorAddress, ertpAmount); - }, 'Delegate'); - }, - /** @param {string} validatorAddress */ - makeWithdrawRewardInvitation(validatorAddress) { - trace('makeWithdrawRewardInvitation', validatorAddress); - - return zcf.makeInvitation(async seat => { - seat.exit(); - return this.facets.helper.withdrawReward(validatorAddress); - }, 'WithdrawReward'); - }, - makeCloseAccountInvitation() { - throw Error('not yet implemented'); - }, - /** - * Starting a transfer revokes the account holder. The associated updater - * will get a special notification that the account is being transferred. - */ - makeTransferAccountInvitation() { - throw Error('not yet implemented'); - }, - }, }, ); return makeStakingAccountKit; diff --git a/packages/orchestration/test/test-withdraw-reward.js b/packages/orchestration/test/test-withdraw-reward.js index 2cfb69e9953..5c77a686829 100644 --- a/packages/orchestration/test/test-withdraw-reward.js +++ b/packages/orchestration/test/test-withdraw-reward.js @@ -157,11 +157,10 @@ test('withdraw rewards from staking account holder', async t => { const { baggage, makeRecorderKit, storageNode, zcf } = s; const make = prepareStakingAccountKit(baggage, makeRecorderKit, zcf); - // `helper` is a somewhat internal API; // Higher fidelity tests below use invitationMakers. - const { helper } = make(account, storageNode, account.getAddress()); + const { holder } = make(account, storageNode, account.getAddress()); const { validator } = scenario1; - const actual = await E(helper).withdrawReward(validator.address); + const actual = await E(holder).withdrawReward(validator.address); t.deepEqual(actual, [{ denom: 'uatom', value: 2n }]); const msg = { typeUrl: '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward', @@ -181,6 +180,7 @@ test(`delegate; withdraw rewards`, async t => { const { validator, delegations } = scenario1; { const value = BigInt(Object.values(delegations)[0].amount); + /** @type {Amount<'nat'>} */ const anAmount = { brand: Far('Token'), value }; const toDelegate = await E(invitationMakers).Delegate( validator.address,