# Devolopers - SDKs APIs & Contracts

> **Status:** Testnet first. Addresses and package names marked **TBA** will be published in Releases.

### TL;DR — 5‑minute Quickstart (testnet)

```bash
# 1) Install SDKs (JS or Python)
npm i @methexis/sdk      # JS/TS
# or
pip install methexis-sdk # Python

# 2) Configure RPC + signer (env)
export ETH_RPC=https://rpc.testnet.example.org
export WALLET=0xYOUR_ADDR

# 3) Register a dataset (hash + manifest URI)
mhx data register \
  --content-hash 0xA3F5...7C1E \
  --meta-uri ipfs://bafy.../manifest.yaml \
  --bond 80
```

**What just happened:** you pinned data to IPFS, registered it on‑chain, and posted a refundable bond. A committee will now review your dataset.

***

### Environments

| Env         | Chain            | RPC                               | Contracts                     |
| ----------- | ---------------- | --------------------------------- | ----------------------------- |
| **Testnet** | Ethereum testnet | `https://rpc.testnet.example.org` | `TBA` (published in Releases) |
| **Mainnet** | Ethereum         | `https://…`                       | `TBA` (after audit)           |

**Chain ID**: TBA • **Block explorer**: TBA

***

### Packages

* **JavaScript/TypeScript:** `@methexis/sdk` (Ethers v6 under the hood)
* **Python:** `methexis-sdk` (web3.py + requests)
* **CLI:** `mhx` (thin wrapper over contracts & IPFS helpers)

> Source: `https://github.com/methexisxyz` (modules: token, staking, rewards, governance, data‑registry, validator)

***

### Core Contracts & ABIs (overview)

* **Token (ERC‑20):** `$MTHX`
* **Staking / Rewards**
* **Data Registry** → `registerDataset(bytes32 contentHash, string metaURI)`; `setDatasetStatus(uint256 id, Status)`
* **Training Coordination** → `startRound`, `submitModelUpdate`, `finalizeRound`
* **Governance (DAO)** → `propose`, `vote`, `queue`, `execute`

**Events (minimal schema)**\
`DatasetRegistered(datasetId, contentHash, submitter)`\
`DatasetStatusChanged(datasetId, status)`\
`RoundStarted(roundId, prevModelHash)`\
`ModelProposed(roundId, modelHash, signers, metricsURI)`\
`ModelFinalized(roundId, modelHash)`\
`RewardsDistributed(roundId, total, breakdownURI)`\
`Slashed(account, amount, reason)`

> Full ABIs are published with releases. You can also import them from the SDK.

***

### JavaScript / TypeScript (Ethers v6) examples

#### 1) Setup

```ts
import { ethers } from "ethers";
import { getContracts } from "@methexis/sdk"; // helper that returns typed ethers.Contract

const provider = new ethers.JsonRpcProvider(process.env.ETH_RPC!);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

const { DataRegistry, Training, Staking, Governance } = await getContracts({
  chain: "testnet", signer: wallet,
});
```

#### 2) Register a dataset

```ts
// contentHash = sha256 of the archive; metaURI = ipfs://<manifestCID>
const tx = await DataRegistry.registerDataset(
  "0xA3F5...7C1E",
  "ipfs://bafy.../manifest.yaml"
);
const receipt = await tx.wait();
const evt = receipt.logs.find(l => l.fragment?.name === "DatasetRegistered");
console.log("datasetId:", evt?.args?.datasetId?.toString());
```

#### 3) Watch validation status → drive UX

```ts
DataRegistry.on("DatasetStatusChanged", (datasetId, status) => {
  console.log("status", datasetId.toString(), status);
  // update your UI: Pending → Accepted/Rejected
});
```

#### 4) Listen to training lifecycle

```ts
Training.on("RoundStarted", (roundId, prevHash) =>
  console.log("Round", roundId.toString(), "prev", prevHash)
);

Training.on("ModelProposed", (roundId, modelHash, signers, metricsURI) =>
  console.log("Proposed", { roundId: roundId.toString(), modelHash, metricsURI })
);

Training.on("ModelFinalized", (roundId, modelHash) =>
  console.log("Finalized", roundId.toString(), modelHash)
);

Training.on("RewardsDistributed", (roundId, total, breakdownURI) =>
  console.log("Rewards", roundId.toString(), total.toString(), breakdownURI)
);
```

#### 5) Propose a governance change

```ts
// Example: setValidatorRewardShare(62%)
const iface = new ethers.Interface(["function setValidatorRewardShare(uint256 bps)"]);
const callData = iface.encodeFunctionData("setValidatorRewardShare", [6200]); // 62.00%

const txP = await Governance.propose(callData, "Increase validator share to 62%");
await txP.wait();
console.log("Proposal submitted");
```

***

### Python (web3.py) examples

```python
from web3 import Web3
from methexis_sdk import load_contracts

web3 = Web3(Web3.HTTPProvider(os.environ["ETH_RPC"]))
acct = web3.eth.account.from_key(os.environ["PRIVATE_KEY"])
contracts = load_contracts(web3, acct, chain="testnet")

# Register dataset
tx = contracts.DataRegistry.functions.registerDataset(
    "0xA3F5...7C1E",
    "ipfs://bafy.../manifest.yaml"
).build_transaction({"from": acct.address, "nonce": web3.eth.get_transaction_count(acct.address)})
signed = web3.eth.account.sign_transaction(tx, private_key=os.environ["PRIVATE_KEY"])
txhash = web3.eth.send_raw_transaction(signed.rawTransaction)
print("tx", web3.to_hex(txhash))
```

***

### Indexer API (optional convenience)

While contracts/events are the source of truth, an indexer helps you avoid manual log scans.

**REST (proposed):**

```
GET  /v1/datasets/:id              -> { id, contentHash, status, submitter, metaURI }
GET  /v1/datasets?status=Accepted  -> [...paged results...]
GET  /v1/rounds/:roundId           -> { roundId, prevModelHash, modelHash, metricsURI, finalizedAt }
GET  /v1/rewards/:roundId          -> { total, breakdownURI, allocations[] }
GET  /v1/validators/:addr          -> { stake, uptime, roundsParticipated, slashes[] }
GET  /v1/events?from_block=...     -> stream of canonical events
```

**Webhooks (proposed):**

* `dataset.status.changed` — payload: `{ datasetId, status }`
* `round.finalized` — payload: `{ roundId, modelHash, metricsURI }`
* `rewards.distributed` — payload: `{ roundId, total, breakdownURI }`

> API keys are issued per project; rate limits apply. The indexer mirrors on‑chain data and links off‑chain URIs.

***

### Data flow helpers

#### Hashing (sha256) & IPFS upload (JS)

```ts
import { create } from "ipfs-http-client";
import { createHash } from "crypto";
import fs from "fs";

const ipfs = create({ url: "https://ipfs.your-gateway.example/api/v0" });

const buf = fs.readFileSync("./cleancode-docs-v1.tar.zst");
const contentHash = "0x" + createHash("sha256").update(buf).digest("hex");

const { cid } = await ipfs.add(buf, { pin: true });
const manifestCID = await ipfs.add(fs.readFileSync("./manifest.yaml"));
console.log({ contentHash, archiveCID: cid.toString(), manifestURI: `ipfs://${manifestCID.cid}` });
```

***

### Event‑driven architecture (recommended)

* Subscribe to **DatasetStatusChanged** and **RoundStarted/Finalized** to drive UX.
* Use **idempotent** handlers (event replay safe).
* Handle **reorgs**: wait N confirmations (e.g., 12) before acting on payments or irreversible actions.

***

### Contract interaction patterns

* **Always simulate** (staticcall / eth\_call) before sending txs that mutate state.
* **Gas & revert handling:** surface revert reasons to users.
* **Timelock awareness:** governance changes aren’t immediate; poll timelock or listen to `Queued`/`Executed` (ABI TBA).
* **Multisig compatibility:** proposals can be composed & signed by Safe; execution still goes through DAO where required.

***

### Versioning & Compatibility

* **Semver** for SDKs and contract releases (`vMAJOR.MINOR.PATCH`).
* **Breaking changes** → new contract addresses (posted in Releases); SDK will expose both `v1` and `v2` namespaces during migration.
* **Deprecations** are announced at least one quarter in advance in the **Roadmap** page.

***

### Security & Keys

* Prefer **hardware wallets** or **remote signers**.
* Never store private keys in code or CI; use vaults / KMS.
* Rotate API keys and restrict by IP where possible (indexer).
* Monitor for **Slashed** events and set alerts.

***

### Testing & Local Dev

* Local anvil/Hardhat/Foundry support (fork testnet).
* Mock IPFS gateway + fixtures for dataset manifests.
* Contract interfaces shipped with the SDK for quick tests.

**Example (Foundry):**

```bash
forge test -vvv
# Deploy to local dev chain
forge script script/Deploy.s.sol --broadcast --rpc-url http://localhost:8545
```

***

### Error Model (SDK)

* **`MhxError`** base class with `code` and `context`.
* Common codes: `E_NO_FUNDS`, `E_REVERTED`, `E_BAD_MANIFEST`, `E_POLICY_VIOLATION`, `E_RATE_LIMIT`, `E_TIMEOUT`.
* All network calls support **retry with backoff** and **abort signals**.

***

### Frequently Used Recipes

* **“Show me all Accepted datasets since block X”** → indexer `GET /v1/datasets?status=Accepted&from_block=X` or filter `DatasetStatusChanged` and query `status=Accepted`.
* **“Notify users when a round finalizes”** → subscribe to `ModelFinalized` + `RewardsDistributed`, then send webhook.
* **“Governance dashboard”** → index proposals from `ProposalCreated` (ABI TBA), tally votes per block, show timelock ETA.

***

### Support & Links

* **Releases & Addresses:** GitHub → Releases
* **Package registry:** npm / PyPI
* **Status page:** TBA
* **Responsible disclosure:** see **Audits & Security** page
