# Membership

This document provides a comprehensive overview of the "Membership" smart contract messages and its sdk. The contract acts primarily as a proxy, forwarding messages received from a list of administrators.

## Contract Specification

The membership contract is the one in charge of managing who are the members of the nomos Super Account. The other contracts query this contract to know who can make certain operations such as creating and voting proposals. This membership abstraction allows us to create different membership models. As example, another membership contract instead of storing the members can query a token to check if the balance is enough for the account to be a member.

### Instantiate Message

When the contract is instantiated, it requires the following parameters:

* **admins**: The owner/admin that can update the members list.
* **members**: The members of the contract.

Message definition in rust:

```rust
#[cw_serde]
pub struct InstantiateMsg {
    pub admin: Option<String>,
    pub members: Vec<Member>,
}
```

### Execute Messages

The contract supports the following execution messages:

* **Update admin**:
  * Allows to update the admin with a new address, or clearing the admin.
  * This action can be performed only by an admin.
* **Update Members**:
  * Updates the list of member addresses.
  * It receives an array of remove and add members. The add members also contains the weight of the members. The removal is applied after the addition, so if a member is in both arrays, the member is not added.
  * Can only be done by an admin.

Rust messages definition:

```rust
#[cw_serde]
pub enum ExecuteMsg {
    UpdateAdmin { admin: Option<String> },
    UpdateMembers {
        remove: Vec<String>,
        add: Vec<Member>,
    },
    AddHook { addr: String },
    RemoveHook { addr: String },
}
```

### Query Messages

Query operations supported by the Membership contract include:

* **Admin**:
  * Returns the admin of the contract.
* **Total weight**:
  * Returns the aggregated weight of all addresses at a given block.
* **List members**:
  * Returns all members given a limit (limit of members to return) and a "start\_after" option which defines from which address start searching.

Rust message definitions:

```rust
#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {
    #[returns(cw_controllers::AdminResponse)]
    Admin {},
    #[returns(cw4::TotalWeightResponse)]
    TotalWeight { at_height: Option<u64> },
    #[returns(cw4::MemberListResponse)]
    ListMembers {
        start_after: Option<String>,
        limit: Option<u32>,
    },
    #[returns(cw4::MemberResponse)]
    Member {
        addr: String,
        at_height: Option<u64>,
    },
    #[returns(cw_controllers::HooksResponse)]
    Hooks {},
}
```

## In SDK

The JavaScript/TypeScript API provides a convenient interface for interacting with the Membership contract through CosmWasm's `CosmWasmClient` and `SigningCosmWasmClient`.

### Initialization

```typescript
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import {Membership} from "nomos-v2"

const client:SigningCosmwasmClient = // ...
const wallet = new Membership(client, "<membership_address>")
```

## Membership Client

### Query Methods

* `admin()`: Retrieves the current administrator and the contract's mutability status.
* `totalWeight({ atHeight })`: Fetches the total weight of the membership at a specific block height.
* `listMembers({ limit, startAfter })`: Lists members of the contract with optional pagination.
* `member({ addr, atHeight })`: Retrieves details about a specific member by address.
* `hooks()`: Lists all registered hooks within the contract.

### Transaction Methods

* `updateAdmin({ admin }, fee, memo, _funds)`: Updates the administrator of the contract. This action can only be performed by the current admin.
* `updateMembers({ add, remove }, fee, memo, _funds)`: Updates the list of members by adding and/or removing members.
* `addHook({ addr }, fee, memo, _funds)`: Registers a new hook address to the contract.
* `removeHook({ addr }, fee, memo, _funds)`: Removes an existing hook address from the contract.

## Usage

To interact with the Membership contract, instantiate a `MembershipClient` with the appropriate `SigningCosmWasmClient`, sender address, and contract address. This setup allows for executing both query and transaction operations based on the permissions provided to the user.

### Example: Creating a client and updating membership

```typescript
import { CosmWasmClient, SigningCosmWasmClient, StdFee } from "@cosmjs/cosmwasm-stargate";
import { Coin } from "@cosmjs/amino";

// Instantiate the SigningCosmWasmClient with necessary credentials
const client: SigningCosmWasmClient = new SigningCosmWasmClient(...);
const contractAddress = "<contract_address>";
const senderAddress = "<sender_address>";

// Create the Membership client
const membershipClient = new MembershipClient(client, senderAddress, contractAddress);

// Query current admins
const adminResponse = await membershipClient.admin();
console.log('Current Admin:', adminResponse.admin);

// Update members
const executionResult = await membershipClient.updateMembers({
  add: [{ addr: "cosmos1...", weight: 10 }],
  remove: ["cosmos1...removed"]
}, "auto", "Adding and removing members");
console.log('Execution Result:', executionResult);
```
