Skip to content

Commit

Permalink
Sns disburse maturity function (#395)
Browse files Browse the repository at this point in the history
# Motivation

Add `disburseMaturity` to sns functions

# Changes

- `disburseMaturity` function
- related types
- increased size limit for sns: 14Kb -> 16Kb

# Tests

- disburseMaturity params spec

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
mstrasinskis and github-actions[bot] authored Aug 9, 2023
1 parent 3568c32 commit 223d9da
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 68 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
{
"name": "@dfinity/sns",
"path": "./packages/sns/dist/index.js",
"limit": "14 kB",
"limit": "16 kB",
"ignore": [
"@dfinity/agent",
"@dfinity/candid",
Expand Down
160 changes: 93 additions & 67 deletions packages/sns/README.md

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions packages/sns/src/converters/governance.converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import type {
SnsIncreaseDissolveDelayParams,
SnsListProposalsParams,
SnsNeuronAutoStakeMaturityParams,
SnsNeuronDisburseMaturityParams,
SnsNeuronPermissionsParams,
SnsNeuronStakeMaturityParams,
SnsRegisterVoteParams,
Expand Down Expand Up @@ -178,6 +179,23 @@ export const toStakeMaturityRequest = ({
},
});

export const toDisburseMaturityRequest = ({
neuronId,
percentageToDisburse,
toAccount,
}: SnsNeuronDisburseMaturityParams): ManageNeuron =>
toManageNeuronCommand({
neuronId,
command: {
DisburseMaturity: {
// currently there is a main account only support
to_account:
toAccount === undefined ? [] : toNullable(toCandidAccount(toAccount)),
percentage_to_disburse: percentageToDisburse,
},
},
});

export const toAutoStakeMaturityNeuronRequest = ({
neuronId,
autoStake: requested_setting_for_auto_stake_maturity,
Expand Down
76 changes: 76 additions & 0 deletions packages/sns/src/governance.canister.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
import { rootCanisterIdMock } from "./mocks/sns.mock";
import {
SnsDisburseNeuronParams,
SnsNeuronDisburseMaturityParams,
SnsRegisterVoteParams,
SnsSplitNeuronParams,
} from "./types/governance.params";
Expand Down Expand Up @@ -1136,6 +1137,81 @@ describe("Governance canister", () => {
});
});

describe("disburseMaturity", () => {
const toAccount = {
owner: Principal.fromText("aaaaa-aa"),
subaccount: arrayOfNumberToUint8Array([0, 0, 1]),
};
const params: SnsNeuronDisburseMaturityParams = {
neuronId: {
id: arrayOfNumberToUint8Array([1, 2, 3]),
},
percentageToDisburse: 50,
toAccount,
};

it("should disburse maturity of the neuron", async () => {
const request: ManageNeuron = {
subaccount: params.neuronId.id,
command: [
{
DisburseMaturity: {
to_account: [toCandidAccount(toAccount)],
percentage_to_disburse: params.percentageToDisburse,
},
},
],
};

const service = mock<ActorSubclass<SnsGovernanceService>>();
service.manage_neuron.mockResolvedValue({
command: [{ DisburseMaturity: { amount_disbursed_e8s: BigInt(0) } }],
});

const canister = SnsGovernanceCanister.create({
canisterId: rootCanisterIdMock,
certifiedServiceOverride: service,
});

await canister.disburseMaturity(params);

expect(service.manage_neuron).toBeCalled();
expect(service.manage_neuron).toBeCalledWith(request);
});

it("throws error if percentage not valid", () => {
const service = mock<ActorSubclass<SnsGovernanceService>>();

const canister = SnsGovernanceCanister.create({
canisterId: rootCanisterIdMock,
certifiedServiceOverride: service,
});

const call = () =>
canister.disburseMaturity({
...params,
percentageToDisburse: 500,
});

expect(call).rejects.toThrow(InvalidPercentageError);
expect(service.manage_neuron).not.toBeCalled();
});

it("should raise an error", async () => {
const service = mock<ActorSubclass<SnsGovernanceService>>();
service.manage_neuron.mockResolvedValue(mockErrorCommand);

const canister = SnsGovernanceCanister.create({
canisterId: rootCanisterIdMock,
certifiedServiceOverride: service,
});
const call = () => canister.disburseMaturity(params);

expect(call).rejects.toThrowError(SnsGovernanceError);
expect(service.manage_neuron).toBeCalled();
});
});

describe("autoStakeMaturity", () => {
const testAutoStakeMaturitySuccess = async (
requested_setting_for_auto_stake_maturity: boolean,
Expand Down
19 changes: 19 additions & 0 deletions packages/sns/src/governance.canister.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
toAddPermissionsRequest,
toAutoStakeMaturityNeuronRequest,
toClaimOrRefreshRequest,
toDisburseMaturityRequest,
toDisburseNeuronRequest,
toFollowRequest,
toIncreaseDissolveDelayRequest,
Expand All @@ -49,6 +50,7 @@ import type {
SnsListNeuronsParams,
SnsListProposalsParams,
SnsNeuronAutoStakeMaturityParams,
SnsNeuronDisburseMaturityParams,
SnsNeuronPermissionsParams,
SnsNeuronStakeMaturityParams,
SnsRegisterVoteParams,
Expand Down Expand Up @@ -289,6 +291,23 @@ export class SnsGovernanceCanister extends Canister<SnsGovernanceService> {
await this.manageNeuron(request);
};

/**
* Disburse the maturity of a neuron.
*
* @param {neuronId: NeuronId; toAccount?: IcrcAccount; percentageToDisburse: number; } params
* @param {IcrcAccount} toAccount. Account to disburse maturity.
* @param {NeuronId} neuronId The id of the neuron for which to disburse the maturity
* @param {number} percentageToDisburse What percentage of the available maturity to disburse.
*/
disburseMaturity = async (
params: SnsNeuronDisburseMaturityParams,
): Promise<void> => {
assertPercentageNumber(params.percentageToDisburse);

const request: ManageNeuron = toDisburseMaturityRequest(params);
await this.manageNeuron(request);
};

/**
* Changes auto-stake maturity for a Neuron.
*
Expand Down
21 changes: 21 additions & 0 deletions packages/sns/src/sns.wrapper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,27 @@ describe("SnsWrapper", () => {
});
});

it("should call disburseMaturity", async () => {
const neuronId = {
id: arrayOfNumberToUint8Array([1, 2, 3]),
};
const toAccount = {
owner: Principal.fromText("aaaaa-aa"),
subaccount: arrayOfNumberToUint8Array([0, 0, 1]),
};
const percentageToDisburse = 50;
await snsWrapper.disburseMaturity({
neuronId,
percentageToDisburse,
toAccount,
});
expect(mockGovernanceCanister.disburseMaturity).toHaveBeenCalledWith({
neuronId,
percentageToDisburse,
toAccount,
});
});

it("should call autoStakeMaturity", async () => {
const neuronId = {
id: arrayOfNumberToUint8Array([1, 2, 3]),
Expand Down
5 changes: 5 additions & 0 deletions packages/sns/src/sns.wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import type {
SnsListNeuronsParams,
SnsListProposalsParams,
SnsNeuronAutoStakeMaturityParams,
SnsNeuronDisburseMaturityParams,
SnsNeuronPermissionsParams,
SnsNeuronStakeMaturityParams,
SnsRegisterVoteParams,
Expand Down Expand Up @@ -437,6 +438,10 @@ export class SnsWrapper {
stakeMaturity = (params: SnsNeuronStakeMaturityParams): Promise<void> =>
this.governance.stakeMaturity(params);

// Always certified
disburseMaturity = (params: SnsNeuronDisburseMaturityParams): Promise<void> =>
this.governance.disburseMaturity(params);

// Always certified
autoStakeMaturity = (
params: SnsNeuronAutoStakeMaturityParams,
Expand Down
9 changes: 9 additions & 0 deletions packages/sns/src/types/governance.params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ export interface SnsNeuronStakeMaturityParams
percentageToStake?: number;
}

/**
* The parameters to disburse maturity of a neuron
*/
export interface SnsNeuronDisburseMaturityParams
extends SnsNeuronManagementParams {
toAccount?: IcrcAccount;
percentageToDisburse: number;
}

/**
* The parameters to toggle auto stake maturity of a neuron
*/
Expand Down

0 comments on commit 223d9da

Please sign in to comment.