Skip to Content
New: a threat-model-first guide to choosing your network defence, plus the nym-smoldvpn dVPN package and nym-swizzle sender hygiene.

Nym Smart Contract Clients

To query or execute on any of the Nym contracts, use the Contract Clients, which contain read-only query and signing clients for all of Nym’s smart contracts.

Contract Clients

ClientFunctionalityMethods
Coconut BandwidthManages depositing and release of funds. Tracks double spending.Source 
Coconut DKGAllows signers to derive keys for issuing Coconut credentials.Source 
Cw3FlexMultisigUsed by the Coconut APIs to issue credentials. cw3-flex-multisig  backed by cw4.Source 
Cw4GroupUsed by the Coconut APIs. Cw4 Group  stores members with an admin.Source 
MixnetManages the network topology, tracking delegations and rewards.Source 
Name ServiceDirectory of user-defined aliases, analogous to DNS.Source 
Service Provider DirectoryPublic directory for registering service providers.Source 
VestingManages NYM token vesting functionality.Source 

Environment Setup

Create a new project with Vite:

npm create vite@latest

Choose React + TypeScript, then:

cd <YOUR_APP> npm i npm run dev

Query Example

Installation

npm install @nymproject/contract-clients @cosmjs/cosmwasm-stargate

Querying the Mixnet Contract

This example uses MixnetQueryClient to fetch a paged list of mixnodes from the contract. Create a settings.ts file for your network configuration:

settings.ts
export const settings = { url: "wss://rpc.nymtech.net:443", mixnetContractAddress: "n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr", };
App.tsx
import { useEffect, useState } from "react"; import { contracts } from "@nymproject/contract-clients"; import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; import { settings } from "./settings"; import Box from "@mui/material/Box"; import CircularProgress from "@mui/material/CircularProgress"; const getClient = async () => { const cosmWasmClient = await SigningCosmWasmClient.connect(settings.url); const client = new contracts.Mixnet.MixnetQueryClient( cosmWasmClient, settings.mixnetContractAddress ); return client; }; export const Mixnodes = () => { const [mixnodes, setMixnodes] = useState<any>(); const getMixnodes = async () => { const client = await getClient(); const { nodes } = await client.getMixNodesDetailed({}); setMixnodes(nodes); }; useEffect(() => { getMixnodes(); }, []); if (!mixnodes) { return ( <Box sx={{ display: "flex" }}> <CircularProgress /> </Box> ); } return ( <div style={{ marginTop: "1rem" }}> {mixnodes?.length && mixnodes.map((mixnode: any) => ( <Box className="codeBox" key={mixnode.bond_information.mix_id}> <span style={{ marginRight: "1rem" }}> {`id: ${mixnode.bond_information.mix_id}`} </span> <span>{`owner: ${mixnode.bond_information.owner}`}</span> </Box> ))} </div> ); };

Execute Example

Installation

npm install @nymproject/contract-clients @cosmjs/cosmwasm-stargate @cosmjs/proto-signing

Executing Contract Methods

This example uses MixnetClient with a signer to execute methods like delegation.

Update your settings.ts to include signing credentials:

settings.ts
export const settings = { url: "wss://rpc.nymtech.net:443", mixnetContractAddress: "<ENTER MIXNET CONTRACT ADDRESS>", mnemonic: "<ENTER MNEMONIC>", address: "<ENTER NYM ADDRESS>", };
App.tsx
import { contracts } from "@nymproject/contract-clients"; import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; import { GasPrice } from "@cosmjs/stargate"; import { settings } from "./settings"; export default function Exec() { let signer: DirectSecp256k1HdWallet; let signerMixnetClient: any; let cosmWasmSigningClient: SigningCosmWasmClient; let mixId: number; let amountToDelegate: string; let nodeAddress: string; let amountToSend: string; let delegations: any; async function ExecuteOnNyx() { signer = await DirectSecp256k1HdWallet.fromMnemonic(settings.mnemonic, { prefix: "n", }); const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner( settings.url, signer, { gasPrice: GasPrice.fromString("0.025unym") } ); cosmWasmSigningClient = cosmWasmClient; const mixnetClient = new contracts.Mixnet.MixnetClient( cosmWasmSigningClient, settings.address, settings.mixnetContractAddress ); signerMixnetClient = mixnetClient; } const getDelegations = async () => { if (!signerMixnetClient) return; delegations = await signerMixnetClient.getDelegatorDelegations({ delegator: settings.address, }); }; const doDelegation = async () => { if (!signerMixnetClient) return; const res = await signerMixnetClient.delegateToMixnode( { mixId }, "auto", undefined, [{ amount: `${amountToDelegate}`, denom: "unym" }] ); console.log(res); }; const doUndelegateAll = async () => { for (const delegation of delegations.delegations) { await signerMixnetClient.undelegateFromMixnode( { mixId: delegation.mix_id }, "auto" ); } }; const doSendTokens = async () => { const res = await cosmWasmSigningClient.sendTokens( settings.address, nodeAddress, [{ amount: amountToSend, denom: "unym" }], "auto", "test sending tokens" ); console.log(res); }; ExecuteOnNyx(); setTimeout(() => getDelegations(), 1000); return ( <div> <p>Send Tokens</p> <input type="string" placeholder="Node Address" onChange={(e) => (nodeAddress = e.target.value)} /> <input type="number" placeholder="Amount" onChange={(e) => (amountToSend = e.target.value)} /> <button onClick={() => doSendTokens()}>Send Tokens</button> <p>Delegate</p> <input type="number" placeholder="Mixnode Id" onChange={(e) => (mixId = +e.target.value)} /> <input type="number" placeholder="Amount" onChange={(e) => (amountToDelegate = e.target.value)} /> <button onClick={() => doDelegation()}>Delegate</button> <button onClick={() => doUndelegateAll()}>Undelegate All</button> </div> ); }
Last updated on