diff --git a/dfx.json b/dfx.json index 826c29c5..d3b1093b 100644 --- a/dfx.json +++ b/dfx.json @@ -134,6 +134,11 @@ "type": "custom", "candid": "src/airdrop/airdrop.did", "wasm": "src/airdrop/airdrop.wasm" + }, + "neuron_controller": { + "type": "custom", + "candid": "src/neuron_controller/neuron_controller.did", + "wasm": "src/neuron_controller/neuron_controller.wasm.gz" } }, "defaults": { diff --git a/scripts/sns/neuron_controller/dissolve_delay_params.sh b/scripts/sns/neuron_controller/dissolve_delay_params.sh new file mode 100755 index 00000000..1585b4c9 --- /dev/null +++ b/scripts/sns/neuron_controller/dissolve_delay_params.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail + +NEURON_ID=${1:-} +DELAY_SECONDS=${2:-} +MANAGE_CMD="(record {command = variant {Configure=record {operation = opt variant {IncreaseDissolveDelay = record { additional_dissolve_delay_seconds = $DELAY_SECONDS:nat32 }}}}; neuron_id = ${NEURON_ID}:nat64;})" + +echo "${MANAGE_CMD}" diff --git a/scripts/sns/neuron_controller/sns_init.yaml b/scripts/sns/neuron_controller/sns_init.yaml new file mode 100644 index 00000000..eed52f64 --- /dev/null +++ b/scripts/sns/neuron_controller/sns_init.yaml @@ -0,0 +1,472 @@ +# You should make a copy of this file, name it sns_init.yaml, and edit it to +# suit your needs. +# +# All principal IDs should almost certainly be changed. +# +# In this file, 1 year is nominally defined to be 365.25 days. +# +# This gets passed to `sns propose`. See propose_sns.sh. +# +# This follows the second configuration file format developed for the `sns` +# CLI. The first format will be supported for a time, but this format will +# eventually become the standard format. +# ------------------------------------------------------------------------------ +# UNITS +# +# This SNS configuration file version allows specifying the various +# fields with units that make configuration easier. For instance, +# in the previous version, all fields relating to token values +# had to be specified in e8s (fractions of 10E-8 of a governance token). +# In this version, similar fields can be specified in whole tokens, +# tokens with decimals, or e8s. Below is more information on the type +# of units that can be used. +# +# For fields that represent token values (such as `transaction_fee` +# or `rejection_fee`), devs can specify decimal strings ending in +# "tokens" (plural), decimal strings ending in "token" (singular), +# or integer strings (base 10) ending in "e8s". In the case of +# "tokens" strings, the maximum number of digits after the (optional) +# decimal point is 8. The "_" character may be sprinkled throughout. +# Whitespace around number is insignificant. E.g. " 42 tokens" is +# equivalent to "42tokens". +# +# For fields that represent duration values (such as `initial_voting_period` +# or `minimum_dissolve_delay`), devs can specify durations as a concatenation +# of time spans. Where each time span is an integer number and a suffix. +# Supported suffixes: +# - seconds, second, sec, s +# - minutes, minute, min, m +# - hours, hour, hr, h +# - days, day, d +# - weeks, week, w +# - months, month, M -- defined as 30.44 days +# - years, year, y -- defined as 365.25 days +# +# For example, "1w 2d 3h" gets parsed as +# +# 1 week + 2 days + 3 hours +# = +# (1 * (7 * 24 * 60 * 60) + 2 * 24 * 60 * 60 + 3 * (60 * 60)) seconds +# +# For fields that represent percentage values (such as `bonus`), devs specify +# the value as an integer with a trailing percent sign ('%'). For example, +# `10%`. +# +# For fields that represent time of day (such as `start_time`), devs specify +# the value as a string in form "hh::mm UTC". Where hh is hour, and mm is minute. +# Only the UTC timezone is currently supported. +# ------------------------------------------------------------------------------ + +# Name of the SNS project. This may differ from the name of the associated +# token. Must be a string of max length = 255. +name: TEST_SNS_NEURON_CONTROLLER + +# Description of the SNS project. +# Must be a string of max length = 2,000. +description: > + Have to test NeuronController canister + +# This is currently a placeholder field and must be left empty for now. +Principals: [] + +# Path to the SNS Project logo on the local filesystem. The path is relative +# to the configuration file's location, unless an absolute path is given. +# Must have less than 341,334 bytes. The only supported format is PNG. +# Consider that NNS dapp will render the image with a 1:1 aspect ratio and +# cropped to a circle. +logo: logo.png + +# URL to the dapp controlled by the SNS project. +# Must be a string from 10 to 512 bytes. +url: https://forum.dfinity.org/thread-where-this-sns-is-discussed + +# Metadata for the NNS proposal required to create the SNS. This data will be +# shown only in the NNS proposal. +NnsProposal: + # The title of the NNS proposal. Must be a string of 4 to 256 bytes. + title: "NNS Proposal to create an SNS named 'TEST_SNS_NEURON_CONTROLLER'" + + # The HTTPS address of additional content required to evaluate the NNS + # proposal. + url: "https://forum.dfinity.org" + + # The description of the proposal. Must be a string of 10 to 2,000 bytes. + summary: > + Proposal to create an SNS for the project XX. + The SNS will be initialized with the following neurons: + ... + +# If the SNS launch attempt fails, control over the dapp canister(s) is given to +# these principals. In most use cases, this is chosen to be the original set of +# controller(s) of the dapp. Must be a list of PrincipalIds. +fallback_controller_principals: + # For the actual SNS launch, you should replace this with one or more + # principals of your intended fallback controllers. + # + # For testing, propose_sns.sh will fill this in automatically. + - "bzv3l-66vp6-w42cr-zouaz-7od2k-zdwhg-stqbm-3i65x-f3cea-ai7na-4ae" + +# The list of dapp canister(s) that will be decentralized if the +# decentralization swap succeeds. These are defined in the form of canister IDs, +# for example, `bnz7o-iuaaa-aaaaa-qaaaa-cai`. For a successful SNS launch, +# these dapp canister(s) must be co-controlled by the NNS Root canister +# (`r7inp-6aaaa-aaaaa-aaabq-cai`) at latest at the time when the NNS proposal to +# create an SNS is adopted (usually this is required even earlier, e.g., to +# convince NNS neurons to vote in favor of your proposal). +dapp_canisters: + # For the actual SNS launch, you should replace this with one or more + # IDs of the canisters comprising your to-be-decentralized dapp. + # + # For testing, propose_sns.sh will fill this in automatically. + - bkyz2-fmaaa-aaaaa-qaaaq-cai + +# Configuration of SNS tokens in the SNS Ledger canister deployed as part +# of the SNS. +Token: + # The name of the token issued by the SNS ledger. + # Must be a string of 4 to 255 bytes without leading or trailing spaces. + name: NeuronController Token + + # The symbol of the token issued by the SNS Ledger. + # Must be a string of 3 to 10 bytes without leading or trailing spaces. + symbol: NRN + + # SNS ledger transaction fee. + transaction_fee: 10_000 e8s + + # Path to the SNS token logo on your local filesystem. The path is relative + # to the configuration file location, unless an absolute path is given. + # Must have less than 341,334 bytes. The only supported format is PNG. + logo: logo.png + +# Configures SNS proposal-related fields. These fields define the initial values +# for some of the nervous system parameters related to SNS proposals. This will +# not affect all SNS proposals submitted to the newly created SNS. +Proposals: + # The cost of making an SNS proposal that is rejected by the SNS neuron + # holders. This field is specified as a token. For example: "1 token". + rejection_fee: 1 token + + # The initial voting period of an SNS proposal. A proposal's voting period + # may be increased during its lifecycle due to the wait-for-quiet algorithm + # (see details below). This field is specified as a duration. For example + # "4 days". + initial_voting_period: 4 days + + # The wait-for-quiet algorithm extends the voting period of a proposal when + # there is a flip in the majority vote during the proposal's voting period. + # + # Without this, there could be an incentive to vote right at the end of a + # proposal's voting period, in order to reduce the chance that people will + # see and have time to react to that. + # + # If this value is set to 1 day, then a change in the majority vote at the + # end of a proposal's original voting period results in an extension of the + # voting period by an additional day. Another change at the end of the + # extended period will cause the voting period to be extended by another + # half-day, etc. + # + # The total extension to the voting period will never be more than twice + # this value. + # + # For more information, please refer to + # https://wiki.internetcomputer.org/wiki/Network_Nervous_System#Proposal_decision_and_wait-for-quiet + # + # This field is specified as a duration. For example: "1 day". + maximum_wait_for_quiet_deadline_extension: 1 day + +# Configuration of SNS voting. +Neurons: + # The minimum amount of SNS tokens to stake a neuron. This field is specified + # as a token. For instance, "1 token". + minimum_creation_stake: 1 tokens + +# Configuration of SNS voting. +Voting: + # The minimum dissolve delay a neuron must have to be able to cast votes on + # proposals. + # + # Dissolve delay incentivizes neurons to vote in the long-term interest of + # an SNS, as they are rewarded for longer-term commitment to that SNS. + # + # Users cannot access the SNS tokens used to stake neurons (until the neuron + # is dissolved). This field is specified as a duration. For example: "6 months". + minimum_dissolve_delay: 1 month + + # Configuration of voting power bonuses that are applied to neurons to + # incentivize alignment with the best interest of the DAO. Note, these + # bonuses multiply each other, so the increase in voting power due to + # the dissolve delay bonus is used in the equation to increase voting + # power for the age bonus. + MaximumVotingPowerBonuses: + # Users with a higher dissolve delay are incentivized to take the + # long-term interests of the SNS into consideration when voting. To + # reward this long-term commitment, this bonus can be set to a + # percentage greater than zero, which will result in neurons having + # their voting power increased in proportion to their dissolve delay. + # + # For example, if the user has a dissolve delay of 6 months, and + # the maximum dissolve delay duration (defined below as `duration`) + # for the dissolve delay bonus is 12 months, and the maximum bonus + # (defined as `bonus` below) is set to 10%, then that user’s voting + # power will be 105% of their normal voting power based on staked + # tokens (i.e. they will have a bonus of 5%). If the user increased + # their dissolve delay to 9 months, they would get 107.5% of the normal + # voting power of their tokens. And if they increased to 12 months, they + # would get 110%. If they increase further, they get no additional bonus. + # + # If you do not want this bonus to be applied for neurons with higher + # dissolve delay, set `bonus` to `0%` and those neurons will not receive + # higher voting power. + DissolveDelay: + # This parameter sets the maximum dissolve delay a neuron can have. + # When reached, the maximum dissolve delay bonus will be applied. + # This field is specified as a duration. For example: "8 years". + duration: 8 years + # If a neuron's dissolve delay is `duration`, its voting power will + # be increased by the dissolve delay `bonus` amount. + # This field is specified as a percentage. For instance, + # a value of "100%" means that the voting power will be doubled + # (multiplied by 2). + bonus: 100% + + # Users with neurons staked in the non-dissolving state for a long + # period of time are incentivized to take the long-term interests of + # the SNS into consideration when voting. To reward this long-term + # commitment, this bonus can be set to a percentage (greater than zero), + # which will result in neurons having their voting power increased in + # proportion to their age. + # + # For example, if the neuron has an age of 6 months, and the maximum age + # duration (defined below as `duration`) for the age bonus is 12 months, + # and the maximum bonus (defined as `bonus` below) is set to 10%, then + # that neuron’s voting power will be 105% of their normal voting power + # based on staked tokens plus dissolve delay bonus (i.e. they will have a + # bonus of 5%). If neuron aged another 3 months to have an age of 9 months, + # the neuron would get 107.5% of the normal voting power. And if the neuron + # aged another 3 months to 12 months, the neuron would get 110%. If the neuron + # ages further, it get no additional bonus. + # + # If this bonus should not be applied for older neurons, set the bonus + # to `0%` and older neurons will not receive higher voting power. + Age: + # This parameter sets the duration of time the neuron must be staked + # in the non-dissolving state, in other words its `age`, to reach + # the maximum age bonus. Once this age is reached, the neuron will + # continue to age, but no more bonus will be applied. This field + # is specified as a duration. For example: "2 years". + duration: 4 years + # If a neuron's age is `duration` or older, its voting power will be + # increased by this age`bonus` amount. + # This field is specified as a percentage. For instance, + # a value of "25%" means that the voting power will increase by a quarter + # (multiplied by 1.25). + bonus: 25% + + # Configuration of SNS voting reward parameters. + # + # The voting reward rate controls how quickly the supply of the SNS token + # increases. For example, setting `initial` to `2%` will cause the supply to + # increase by at most `2%` per year. A higher voting reward rate + # incentivizes users to participate in governance, but also results in + # higher inflation. + # + # The initial and final reward rates can be set to have a higher reward rate + # at the launch of the SNS and a lower rate further into the SNS’s lifetime. + # The reward rate falls quadratically from the `initial` rate to the `final` + # rate over the course of `transition_duration`. + # + # Setting both `initial` and `final` to `0%` will result in the system not + # distributing voting rewards at all. + # + # More details on SNS tokenomics can be found in the developer documentation: + # https://internetcomputer.org/docs/current/developer-docs/integrations/sns/tokenomics/rewards/#voting-rewards + RewardRate: + # The initial reward rate at which the SNS voting rewards will increase + # per year. This field is specified as a percentage. For example: "15%". + initial: 10% + + # The final reward rate at which the SNS voting rewards will increase + # per year. This rate is reached after `transition_duration` and remains + # at this level unless changed by an SNS proposal. This field is + # specified as a percentage. For example: "5%". + final: 2.25% + + # The voting reward rate falls quadratically from `initial` to `final` + # over the time period defined by `transition_duration`. + # + # Values of 0 result in the reward rate always being `final`. + # + # This field is specified as a duration. For example: "8 years". + transition_duration: 12 years + +# Configuration of the initial token distribution of the SNS. You can configure +# how SNS tokens are distributed in each of the three groups: +# (1) tokens that are given to the original developers of the dapp, +# (2) treasury tokens that are owned by the SNS governance canister, and +# (3) tokens which are distributed to the decentralization swap participants. +# +# The initial token distribution must satisfy the following preconditions to be +# valid: +# - The sum of all developer tokens in E8s must be less than `u64::MAX`. +# - The Swap's initial balance (see group (3) above) must be greater than 0. +# - The Swap's initial balance (see group (3) above) must be greater than or +# equal to the sum of all developer tokens. +Distribution: + # The initial neurons created when the SNS Governance canister is installed. + # Each element in this list specifies one such neuron, including its stake, + # controlling principal, memo identifying this neuron (every neuron that + # a user has must be identified by a unique memo), dissolve delay, and a + # vesting period. Even though these neurons are distributed at genesis, + # they are locked in a (restricted) pre-initialization mode until the + # decentralization swap is completed. Note that `vesting_period` starts + # right after the SNS creation and thus includes the pre-initialization mode + # period. + # + # For example: + # - principal: hpikg-6exdt-jn33w-ndty3-fc7jc-tl2lr-buih3-cs3y7-tftkp-sfp62-gqe + # stake: 1_000 tokens + # memo: 0 + # dissolve_delay: 2 years + # vesting_period: 4 years + Neurons: + # For the actual SNS launch, you should replace this with one or more + # principals of your intended genesis neurons. + # + # For testing, propose_sns.sh will fill this in automatically. + - principal: bzv3l-66vp6-w42cr-zouaz-7od2k-zdwhg-stqbm-3i65x-f3cea-ai7na-4ae + stake: 1_000 tokens + memo: 0 + dissolve_delay: 2 years + vesting_period: 4 years + # The initial SNS token balances of the various canisters of the SNS. + InitialBalances: + # The initial SNS token balance of the SNS Governance canister is known + # as the treasury. This is initialized in a special sub-account, as the + # main account of Governance is the minting account of the SNS Ledger. + # This field is specified as a token. For instance, "1 token". + governance: 2_000_000 tokens + + # The initial SNS token balance of the Swap canister is what will be + # available for the decentralization swap. These tokens will be swapped + # for ICP. This field is specified as a token. For instance, "1 token". + swap: 500_000 tokens + + # Checksum of the total number of tokens distributed in this section. + # This field is specified as a token. For instance, "1 token". + # 1_000 (neuron) + # 2 million (governance) + # + 500 thousand (swap) + # -------------- + total: 2_501_000 tokens + +# Configuration of the decentralization swap parameters. Choose these parameters +# carefully, if a decentralization swap fails, the SNS will restore the dapp +# canister(s) to the fallback controllers (defined in +# `fallback_controller_principals`) and you will need to start over. +Swap: + # The minimum number of direct participants that must participate for the + # decentralization swap to succeed. If a decentralization swap finishes due + # to the deadline or the maximum target being reached, and if there are less + # than `minimum_participants` (here, only direct participants are counted), + # the swap will be committed. + minimum_participants: 57 + + # Minimum amount of ICP from direct participants. This amount is required for + # the swap to succeed. If this amount is not achieved, the swap will be + # aborted (instead of committed) when the due date/time occurs. + # Must be smaller than or equal than `maximum_direct_participation_icp`. + minimum_direct_participation_icp: 100_000 tokens + + # Maximum amount of ICP from direct participants. If this amount is achieved, + # the swap will finalize immediately, without waiting for the due date/time; + # in this case, the swap would be committed if and only if the number of + # direct participants (`minimum_participants`) is reached (otherwise, it + # would be aborted). + # Must be at least `min_participants * minimum_direct_participation_icp`. + maximum_direct_participation_icp: 1_000_000 tokens + + # The minimum amount of ICP that each participant must contribute + # to participate. This field is specified as a token. For instance, + # "1 token". + minimum_participant_icp: 10 tokens + + # The maximum amount of ICP that each participant may contribute + # to participate. This field is specified as a token. For instance, + # "1 token". + maximum_participant_icp: 10_000 tokens + + # The text that swap participants must confirm before they may participate + # in the swap. + # + # This field is optional. If set, must be within 1 to 1,000 characters and + # at most 8,000 bytes. + # confirmation_text: > + # I confirm my understanding of the responsibilities and risks + # associated with participating in this token swap. + + # A list of countries from which swap participation should not be allowed. + # + # This field is optional. By default, participants from all countries + # are allowed. + # + # Each list element must be an ISO 3166-1 alpha-2 country code. + restricted_countries: + - AQ # Antarctica + + # Configuration of the vesting schedule of the neuron basket, i.e., the SNS + # neurons that a participants will receive from a successful + # decentralization swap. + VestingSchedule: + # The number of events in the vesting schedule. This translates to how + # many neurons will be in each participant's neuron basket. Note that + # the first neuron in each neuron basket will have zero dissolve delay. + # This value should thus be greater than or equal to `2`. + events: 3 + + # The interval at which the schedule will be increased per event. The + # first neuron in the basket will be unlocked with zero dissolve delay. + # Each other neuron in the schedule will have its dissolve delay + # increased by `interval` compared to the previous one. For example, + # if `events` is set to `3` and `interval` is `1 month`, then each + # participant's neuron basket will have three neurons (with equal stake) + # with dissolve delays zero, 1 month, and 2 months. Note that the notion + # of `Distribution.neurons.vesting_period` applies only to developer + # neurons. While neuron basket neurons do not use `vesting_period`, they + # have a vesting schedule. This field is specified as a duration. For + # example: "1 month". + interval: 1 month + + # Absolute time of day when the decentralization swap is supposed to start. + # + # An algorithm will be applied to allow at least 24 hours between the time + # of execution of the CreateServiceNervousSystem proposal and swap start. + # For example, if start_time is 23:30 UTC and the proposal is adopted and + # executed at 23:20 UTC, then the swap start will be at 23:30 UTC the next + # day (i.e., in 24 hours and 10 min from the proposal execution time). + # + # WARNING: Swap start_time works differently on mainnet and in testing. + # + # On mainnet: + # - Setting start_time to some value (e.g., 23:30 UTC) will allow the swap + # participants to be prepared for the swap in advance, e.g., + # by obtaining ICPs that they would like to participate with. + # - If start_time is not specified, the actual start time of the swap will + # be chosen at random (allowing at least 24 hours and less than 48 hours, + # as described above). + # + # In testing: + # - Setting start_time to some value works the same as explained above. + # - If start_time is not specified, the swap will begin immediately after + # the CreateServiceNervousSystem proposal is executed. This facilitates + # testing in an accelerated manner. + # + # start_time: 23:30 UTC # Intentionally commented out for testing. + + # The duration of the decentralization swap. When `start_time` is calculated + # during CreateServiceNervousSystem proposal execution, this `duration` will + # be added to that absolute time and set as the swap's deadline. + duration: 7 days + + # Whether Neurons' Fund participation is requested. + neurons_fund_participation: true diff --git a/scripts/sns/neuron_controller/start_dissolve_params.sh b/scripts/sns/neuron_controller/start_dissolve_params.sh new file mode 100755 index 00000000..e048e4df --- /dev/null +++ b/scripts/sns/neuron_controller/start_dissolve_params.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail + +export NEURON_ID=${1} +export MANAGE_CMD="(record {command = variant {Configure = record { operation = opt variant { StartDissolving = record {}} }}; neuron_id = ${NEURON_ID}:nat64;})" + +echo "${MANAGE_CMD}" diff --git a/scripts/sns/sns_config.cjs b/scripts/sns/sns_config.cjs index ebf4bd2c..e2a4835f 100755 --- a/scripts/sns/sns_config.cjs +++ b/scripts/sns/sns_config.cjs @@ -8,4 +8,5 @@ exports.canisterCommands = [ "dfx canister id rs", "dfx canister id vesting", "dfx canister id modclub_assets", + "dfx canister id neuron_controller", ]; diff --git a/src/neuron_controller/neuron_controller.did b/src/neuron_controller/neuron_controller.did new file mode 100644 index 00000000..96f3771b --- /dev/null +++ b/src/neuron_controller/neuron_controller.did @@ -0,0 +1,99 @@ +type AccountIdentifier = record { hash : vec nat8 }; +type AddHotKey = record { new_hot_key : opt principal }; +type Amount = record { e8s : nat64 }; +type By = variant { + NeuronIdOrSubaccount : record {}; + MemoAndController : ClaimOrRefreshNeuronFromAccount; + Memo : nat64; +}; +type ChangeAutoStakeMaturity = record { + requested_setting_for_auto_stake_maturity : bool; +}; +type ClaimOrRefresh = record { by : opt By }; +type ClaimOrRefreshNeuronFromAccount = record { + controller : opt principal; + memo : nat64; +}; +type Command = variant { + Spawn : Spawn; + Split : Split; + Follow : Follow; + ClaimOrRefresh : ClaimOrRefresh; + Configure : Configure; + RegisterVote : RegisterVote; + Merge : Merge; + DisburseToNeuron : DisburseToNeuron; + StakeMaturity : StakeMaturity; + MergeMaturity : MergeMaturity; + Disburse : Disburse; +}; +type Configure = record { operation : opt Operation }; +type Disburse = record { + to_account : opt AccountIdentifier; + amount : opt Amount; +}; +type DisburseToNeuron = record { + dissolve_delay_seconds : nat64; + kyc_verified : bool; + amount_e8s : nat64; + new_controller : opt principal; + nonce : nat64; +}; +type Follow = record { topic : int32; followees : vec NeuronId }; +type IncreaseDissolveDelay = record { + additional_dissolve_delay_seconds : nat32; +}; +type ManageNeuron = record { + id : opt NeuronId; + command : opt Command; + neuron_id_or_subaccount : opt NeuronIdOrSubaccount; +}; +type Merge = record { source_neuron_id : opt NeuronId }; +type MergeMaturity = record { percentage_to_merge : nat32 }; +type NeuronId = record { id : nat64 }; +type NeuronIdOrSubaccount = variant { + Subaccount : vec nat8; + NeuronId : NeuronId; +}; +type Operation = variant { + RemoveHotKey : RemoveHotKey; + AddHotKey : AddHotKey; + ChangeAutoStakeMaturity : ChangeAutoStakeMaturity; + StopDissolving : record {}; + StartDissolving : record {}; + IncreaseDissolveDelay : IncreaseDissolveDelay; + JoinCommunityFund : record {}; + LeaveCommunityFund : record {}; + SetDissolveTimestamp : SetDissolveTimestamp; +}; +type RegisterVote = record { vote : int32; proposal : opt NeuronId }; +type RemoveHotKey = record { hot_key_to_remove : opt principal }; +type SetDissolveTimestamp = record { dissolve_timestamp_seconds : nat64 }; +type Spawn = record { + percentage_to_spawn : opt nat32; + new_controller : opt principal; + nonce : opt nat64; +}; +type Split = record { amount_e8s : nat64 }; +type StakeMaturity = record { percentage_to_stake : opt nat32 }; + +type ManageNnsNeuronArgs = record { + neuron_id : nat64; + command : Command; +}; + +type ManageNnsNeuronResponse = variant { + Success: text; + InternalError : text; +}; + +type StakeNnsNeuronResponse = variant { + Success : nat64; + InternalError : text; +}; + +service : { + manage_nns_neuron : (ManageNnsNeuronArgs) -> (ManageNnsNeuronResponse); + get_neuron : (NeuronId) -> (ManageNnsNeuronResponse); + stake_nns_neuron : () -> (StakeNnsNeuronResponse); +} \ No newline at end of file diff --git a/src/neuron_controller/neuron_controller.wasm.gz b/src/neuron_controller/neuron_controller.wasm.gz new file mode 100644 index 00000000..b5b19cb5 Binary files /dev/null and b/src/neuron_controller/neuron_controller.wasm.gz differ