Skip to content

Commit

Permalink
WIP: tests are green
Browse files Browse the repository at this point in the history
  • Loading branch information
dckc committed May 1, 2024
1 parent bee3ded commit eba0907
Showing 1 changed file with 119 additions and 32 deletions.
151 changes: 119 additions & 32 deletions packages/orchestration/test/test-withdraw-reward.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
// @ts-check
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';

import { encodeBase64 } from '@endo/base64';
import { decodeBase64, encodeBase64 } from '@endo/base64';
import { E, Far } from '@endo/far';
import * as pbjs from 'protobufjs';

Check failure on line 6 in packages/orchestration/test/test-withdraw-reward.js

View workflow job for this annotation

GitHub Actions / lint-rest

'protobufjs' should be listed in the project's dependencies. Run 'npm i -S protobufjs' to add it
import {
MsgWithdrawDelegatorReward,
MsgWithdrawDelegatorRewardResponse,
} from '@agoric/cosmic-proto/cosmos/distribution/v1beta1/tx.js';
import { makeScalarBigMapStore } from '@agoric/vat-data';
import { MsgDelegateResponse } from '@agoric/cosmic-proto/cosmos/staking/v1beta1/tx';
import { Any } from '@agoric/cosmic-proto/google/protobuf/any';
import { prepareStakingAccountKit } from '../src/exos/stakingAccountKit.js';

/** @import {ChainAccount} from '../src/types.js'; */
Expand All @@ -21,6 +23,32 @@ const { Fail } = assert;
/** @type {typeof import('protobufjs').Writer} */
const Writer = pbjs.default.Writer;

Check failure on line 24 in packages/orchestration/test/test-withdraw-reward.js

View workflow job for this annotation

GitHub Actions / lint-rest

'Writer' is assigned a value but never used. Allowed unused vars must match /^_/u

const scenario1 = {
acct1: {
address: 'agoric1spy36ltduehs5dmszfrp792f0k2emcntrql3nx',
},
validator: { address: 'agoric1valoper234', addressEncoding: 'bech32' },
delegations: {
agoric1valoper234: { denom: 'ustake', amount: '200' },
},
};

test('DelegateResponse decoding', t => {
// executeEncodedTx() returns "acknowledge string"
const ackStr =
'Ei0KKy9jb3Ntb3Muc3Rha2luZy52MWJldGExLk1zZ0RlbGVnYXRlUmVzcG9uc2U=';
// That's base64 protobuf of an Any
const any = Any.decode(decodeBase64(ackStr));

// use toJSON to get a ProtoMsg
// we happen to know that it's a MsgDelegateResponseProtoMsg
/** @import {MsgDelegateResponseProtoMsg} from '@agoric/cosmic-proto/cosmos/staking/v1beta1/tx.js'; */
const msgA = /** @type {MsgDelegateResponseProtoMsg} */ (Any.toJSON(any));
// now use fromProtoMsg to get a MsgDelegateResponse
const msgD = MsgDelegateResponse.fromProtoMsg(msgA);
t.deepEqual(msgD, {});
});

test('MsgWithdrawDelegatorReward: protobuf encoding reminder', t => {
const actual = MsgWithdrawDelegatorReward.toProtoMsg({
delegatorAddress: 'abc',
Expand Down Expand Up @@ -49,23 +77,33 @@ test('MsgWithdrawDelegatorReward: protobuf encoding reminder', t => {
const mockAccount = (addr = 'agoric1234', delegations = {}) => {
const calls = [];

const typeUrl = '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward';
const simulate = {
'/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward': _m => {
const response = { amount: Object.values(delegations) };
const bytes =
MsgWithdrawDelegatorRewardResponse.encode(response).finish();
const ackStr = encodeBase64(bytes);
return ackStr;
},

'/cosmos.staking.v1beta1.MsgDelegate': _m => {
return 'Ei0KKy9jb3Ntb3Muc3Rha2luZy52MWJldGExLk1zZ0RlbGVnYXRlUmVzcG9uc2U=';
// const m2 = Any.fromJSON(MsgDelegateResponse.toProtoMsg({}));
// return encodeBase64(Any.encode(m2).finish());
},
};

/** @type {ChainAccount} */
const account = Far('MockAccount', {
getAccountAddress: () => addr,
executeEncodedTx: async msgs => {
assert.equal(msgs.length, 1);
assert.equal(msgs[0].typeUrl, typeUrl);
const { typeUrl } = msgs[0];
const doMessage = simulate[typeUrl];
assert(doMessage, `unknown ${typeUrl}`);
await null;
calls.push({ msgs });
const wr = new Writer();
for (const v of Object.values(delegations)) {
// @ts-expect-error BinaryWriter is not exported
MsgWithdrawDelegatorRewardResponse.encode({ amount: [v] }, wr);
}
const bs = wr.finish();
return encodeBase64(bs);
return doMessage(msgs[0]);
},
executeTx: () => Fail`mock`,
close: () => Fail`mock`,
Expand All @@ -76,52 +114,101 @@ const mockAccount = (addr = 'agoric1234', delegations = {}) => {
return { account, calls };
};

/** @returns {ZCF} */
const mockZCF = () =>
harden({
const mockZCF = () => {
const toHandler = new Map();
/** @type {ZCF} */
const zcf = harden({
// @ts-expect-error mock
makeInvitation: async (handler, desc, c = undefined, patt = undefined) => {

Check failure on line 122 in packages/orchestration/test/test-withdraw-reward.js

View workflow job for this annotation

GitHub Actions / lint-rest

'c' is assigned a value but never used. Allowed unused vars must match /^_/u

Check failure on line 122 in packages/orchestration/test/test-withdraw-reward.js

View workflow job for this annotation

GitHub Actions / lint-rest

'patt' is assigned a value but never used. Allowed unused vars must match /^_/u
// const userSeat = harden({
// getOfferResult: () => {
// const zcfSeat = {};
// const r = handler(zcfSeat);
// return r;
// },
// });
/** @type {Invitation} */
// @ts-expect-error mock
const invitation = harden({});
toHandler.set(invitation, handler);
return invitation;
},
});
const zoe = harden({
offer(invitation) {
const handler = toHandler.get(invitation);
const zcfSeat = harden({
exit() {},
});
const result = Promise.resolve(null).then(() => handler(zcfSeat));
const userSeat = harden({
getOfferResult: () => result,
});
return userSeat;
},
});
return { zcf, zoe };
};

const makeRecorderKit = () => {
/** @type {any} */
const kit = harden({});
return kit;
};

test('withdraw rewards from staking account holder', async t => {
const makeRecorderKit = () => {
/** @type {any} */
const kit = harden({});
return kit;
};
const baggage = makeScalarBigMapStore('b1');
const zcf = mockZCF();
const { zcf } = mockZCF();
const make = prepareStakingAccountKit(baggage, makeRecorderKit, zcf);

const validator = { address: 'agoric1valoper234', addressEncoding: 'bech32' };
const delegations = {
[validator.address]: { denom: 'ustake', amount: '200' },
};
const { validator, delegations } = scenario1;

const { account } = mockAccount(undefined, delegations);
// const { rootNode } = makeFakeStorageKit('mockChainStorageRoot');
/** @type {StorageNode} */
// @ts-expect-error mock
const storageNode = Far('StorageNode', {});
const addr = 'agoric123';

// TODO: invitationMakers
const { helper } = make(account, storageNode, addr);
const { helper } = make(account, storageNode, account.getAccountAddress());
const actual = await E(helper).withdrawReward(validator);
t.deepEqual(actual, [{ denom: 'ustake', value: 200n }]);
});

test(`delegate; undelegate`, async t => {
const baggage = makeScalarBigMapStore('b1');
const { zcf, zoe } = mockZCF();
const make = prepareStakingAccountKit(baggage, makeRecorderKit, zcf);

const { validator, delegations } = scenario1;

const { account } = mockAccount(undefined, delegations);
/** @type {StorageNode} */
// @ts-expect-error mock
const storageNode = Far('StorageNode', {});

// TODO: invitationMakers
const { invitationMakers } = make(
account,
storageNode,
account.getAccountAddress(),
);

const toDelegate = await E(invitationMakers).Delegate(validator.address, {
brand: Far('Token'),
value: 2n,
});
{
const seat = E(zoe).offer(toDelegate);
const result = await E(seat).getOfferResult();

t.deepEqual(result, {});
}

const toWithdraw = await E(invitationMakers).WithdrawReward(
validator.address,
);
{
const seat = E(zoe).offer(toWithdraw);
const result = await E(seat).getOfferResult();

t.deepEqual(result, [{ denom: 'ustake', value: 200n }]);
}
});

test.todo(`delegate; undelegate; collect rewards`);
test.todo('undelegate uses a timer: begin; how long? wait; resolve');
test.todo('undelegate is cancellable - cosmos cancelUnbonding');

0 comments on commit eba0907

Please sign in to comment.