Skip to content

Commit

Permalink
Remove stakeNeuronIcrc1
Browse files Browse the repository at this point in the history
  • Loading branch information
dskloetd committed Oct 30, 2024
1 parent a4b36e4 commit bc4a0cc
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 197 deletions.
127 changes: 0 additions & 127 deletions packages/nns/src/governance.canister.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,133 +290,6 @@ describe("GovernanceCanister", () => {
});
});

describe("GovernanceCanister.stakeNeuronIcrc1", () => {
it("creates new neuron successfully", async () => {
const neuronId = BigInt(10);
const serviceResponse: ManageNeuronResponse = {
command: [
{ ClaimOrRefresh: { refreshed_neuron_id: [{ id: neuronId }] } },
],
};
const service = mock<ActorSubclass<GovernanceService>>();
service.manage_neuron.mockResolvedValue(serviceResponse);

const mockLedger = mock<LedgerCanister>();
mockLedger.icrc1Transfer.mockImplementation(
jest.fn().mockResolvedValue(BigInt(1)),
);

const governance = GovernanceCanister.create({
certifiedServiceOverride: service,
});
const response = await governance.stakeNeuronIcrc1({
stake: BigInt(100_000_000),
principal: new AnonymousIdentity().getPrincipal(),
ledgerCanister: mockLedger,
});

expect(mockLedger.icrc1Transfer).toBeCalled();
expect(service.manage_neuron).toBeCalled();
expect(response).toEqual(neuronId);
});

it("stakeNeuron passes fee to the ledger transfer", async () => {
const neuronId = BigInt(10);
const serviceResponse: ManageNeuronResponse = {
command: [
{ ClaimOrRefresh: { refreshed_neuron_id: [{ id: neuronId }] } },
],
};
const service = mock<ActorSubclass<GovernanceService>>();
service.manage_neuron.mockResolvedValue(serviceResponse);

const mockLedger = mock<LedgerCanister>();
mockLedger.icrc1Transfer.mockImplementation(
jest.fn().mockResolvedValue(BigInt(1)),
);
const fee = BigInt(10_000);

const governance = GovernanceCanister.create({
certifiedServiceOverride: service,
});
const response = await governance.stakeNeuronIcrc1({
stake: BigInt(100_000_000),
principal: new AnonymousIdentity().getPrincipal(),
ledgerCanister: mockLedger,
fee,
});

expect(mockLedger.icrc1Transfer).toBeCalledWith(
expect.objectContaining({ fee }),
);
});

it("creates new neuron from subaccount successfully", async () => {
const neuronId = BigInt(10);
const serviceResponse: ManageNeuronResponse = {
command: [
{ ClaimOrRefresh: { refreshed_neuron_id: [{ id: neuronId }] } },
],
};
const service = mock<ActorSubclass<GovernanceService>>();
service.manage_neuron.mockResolvedValue(serviceResponse);

const mockLedger = mock<LedgerCanister>();
mockLedger.icrc1Transfer.mockImplementation(
jest.fn().mockResolvedValue(BigInt(1)),
);

const governance = GovernanceCanister.create({
certifiedServiceOverride: service,
});
const response = await governance.stakeNeuronIcrc1({
stake: BigInt(100_000_000),
principal: new AnonymousIdentity().getPrincipal(),
ledgerCanister: mockLedger,
fromSubAccount: new Uint8Array([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1,
]),
});

expect(mockLedger.icrc1Transfer).toBeCalled();
expect(service.manage_neuron).toBeCalled();
expect(response).toEqual(neuronId);
});

it("returns insufficient amount errors", async () => {
const neuronId = BigInt(1);
const clainNeuronResponse: ClaimOrRefreshNeuronFromAccountResponse = {
result: [{ NeuronId: { id: neuronId } }],
};
const service = mock<ActorSubclass<GovernanceService>>();
service.claim_or_refresh_neuron_from_account.mockResolvedValue(
clainNeuronResponse,
);

const mockLedger = mock<LedgerCanister>();
mockLedger.icrc1Transfer.mockImplementation(jest.fn());

const governance = GovernanceCanister.create({
certifiedServiceOverride: service,
});

const call = async () =>
await governance.stakeNeuronIcrc1({
stake: BigInt(10_000_000),
principal: new AnonymousIdentity().getPrincipal(),
ledgerCanister: mockLedger,
});

expect(mockLedger.icrc1Transfer).not.toBeCalled();
expect(service.claim_or_refresh_neuron_from_account).not.toBeCalled();

await expect(call).rejects.toThrow(
new InsufficientAmountError(BigInt(10_000_000)),
);
});
});

describe("GovernanceCanister.listNeurons", () => {
it("list user neurons", async () => {
const service = mock<ActorSubclass<GovernanceService>>();
Expand Down
70 changes: 0 additions & 70 deletions packages/nns/src/governance.canister.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,76 +298,6 @@ export class GovernanceCanister {
return neuronId;
};

// TODO: Rename to and replace `stakeNeuron` once `stakeNeuronIcrc1` is tested
// in NNS dapp.
// Note: Ledger HW does currently (2023-09-20) not support ICRC-1 transfers to
// the governance canister.
/**
* @throws {@link InsufficientAmountError}
* @throws {@link StakeNeuronTransferError}
* @throws {@link CouldNotClaimNeuronError}
* @throws {@link TransferError}
*/
public stakeNeuronIcrc1 = async ({
stake,
principal,
fromSubAccount,
ledgerCanister,
createdAt,
fee,
}: {
stake: bigint;
principal: Principal;
fromSubAccount?: Uint8Array;
ledgerCanister: LedgerCanister;
// Used for the TransferRequest parameters.
// Check the TransferRequest type for more information.
createdAt?: bigint;
fee?: E8s;
}): Promise<NeuronId> => {
if (stake < E8S_PER_TOKEN) {
throw new InsufficientAmountError(stake);
}

const nonceBytes = new Uint8Array(randomBytes(8));
const nonce = uint8ArrayToBigInt(nonceBytes);
const toSubAccount = this.getNeuronStakeSubAccountBytes(
nonceBytes,
principal,
);

// Send amount to the ledger.
await ledgerCanister.icrc1Transfer({
// WARNING: This does not set the same memo field as the stakeNeuron
// function above and would need to be handled separately from that field.
icrc1Memo: nonceBytes,
amount: stake,
fromSubAccount,
to: {
owner: this.canisterId,
subaccount: [toSubAccount],
},
createdAt,
fee,
});

// Notify the governance of the transaction so that the neuron is created.
const neuronId: NeuronId | undefined =
await this.claimOrRefreshNeuronFromAccount({
controller: principal,
memo: nonce,
});

// Typescript was complaining with `neuronId || new NeuronNotFound()`:
// "Type 'undefined' is not assignable to type 'bigint | StakeNeuronError | TransferError'"
// hence the explicit check.
if (isNullish(neuronId)) {
throw new CouldNotClaimNeuronError();
}

return neuronId;
};

/**
* Increases dissolve delay of a neuron
*
Expand Down

0 comments on commit bc4a0cc

Please sign in to comment.