Examples
1. Nym Smart Contracts

Nym Smart Contract Clients

As previously mentioned, to query or execute on any of the Nym contracts, you'll need to use one of the Contract Clients (opens in a new tab), which contains read-only query and signing clients for all of Nym's smart contracts.

Contract Clients list

Lists of the diffent available clients and methods from the Contract Clients can be found in the .client.ts files:

Client nameFunctionalityMethods list
Coconut Bandwidth ClientManages the depositing and release of funds. Tracks double spending.Coconut Bandwidth (opens in a new tab)
Coconut DKG ClientAllows signers partcipating in issuing Coconut credentials to derive keys to be used.Coconut DKG (opens in a new tab)
Cw3FlexMultisig ClientUsed by the Coconut APIs to issue credentials. This (opens in a new tab) is a multisig contract that is backed by the cw4 (group) contract, which independently maintains the voter set.Cw3Flex Multisig (opens in a new tab)
Cw4Group ClientUsed by the Coconut APIs to issue credentials. Cw4 Group (opens in a new tab) stores a set of members along with an admin, and allows the admin to update the state.Cw4Group (opens in a new tab)
Mixnet ClientManages the network topology of the mixnet, tracking delegations and rewardingMixnet (opens in a new tab)
Name Service ClientOperates as a directory of user-defined aliases, analogous to a Domain Name System (DNS).Name service (opens in a new tab)
Service provider Directory ClientAllows users to register their service provider in a public directory.Service Provider (opens in a new tab)
Vesting ClientManages NYM token vesting functionality.Vesting (opens in a new tab)

Depending on your app or project's architecture, this could be any of the ESM or CJS versions of the Contract Clients.

Set-up your environment

Create your directory and set-up your app environment:

npx create-react-app my-app
Installation

Install the package and its dependencies from Cosmos Stargate:

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

Query clients

Imports

Import the contracts' client in your app:

import { contracts } from '@nymproject/contract-clients';
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
Polyfills

You will need to install:

npm install --save url fs assert crypto-browserify stream-http https-browserify os-browserify buffer stream-browserify process react-app-rewired

and create a config-overrides.jsfile:

const webpack = require('webpack');
module.exports = function override(config, env) {
    config.resolve.fallback = {
        url: require.resolve('url'),
        fs: require.resolve('fs'),
        assert: require.resolve('assert'),
        crypto: require.resolve('crypto-browserify'),
        http: require.resolve('stream-http'),
        https: require.resolve('https-browserify'),
        os: require.resolve('os-browserify/browser'),
        buffer: require.resolve('buffer'),
        stream: require.resolve('stream-browserify'),
    };
    config.plugins.push(
        new webpack.ProvidePlugin({
            process: 'process/browser',
            Buffer: ['buffer', 'Buffer'],
        }),
    );
 
    return config;
}

Update your package.json file:

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject" // don't change the eject
  },
Example: using the Mixnet smart contract client to query

In this example, we will use the MixnetQueryClientfrom the Contract Clients to simply query the contract and return a list of Mixnodes.

import "./App.css";
import { contracts } from "@nymproject/contract-clients";
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { useEffect, useState } from "react";
 
export default function Mixnodes() {
 
    const [mixnodes, setMixnodes] = useState(null);
 
  async function fetchMixnodes(){
    // Set-up the CosmWasm Client
    const cosmWasmClient = await SigningCosmWasmClient.connect("wss://rpc.nymtech.net:443");
 
    const client = new contracts.Mixnet.MixnetQueryClient(
      cosmWasmClient,
      "n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr" // the contract address (which is different on mainnet, QA, etc)
    );
    console.log("client:", client)
    const result = await client.getMixNodesDetailed({});
    console.log(result)
    setMixnodes(result.nodes)
 
  }
 
  useEffect(() => {
    fetchMixnodes();
  }, [])
 
    return(
      <>
        <table>
          <tbody>
            {mixnodes?.map((value, index) => {
              return(
                  <tr key={index}>
                    <td> {value?.bond_information?.mix_node?.identity_key} </td>
                  </tr>
                )
              })
            }
          </tbody>
        </table>
      </>
    )
  }

Execute clients

Imports

Import the contracts' execute clients in your app:

import { contracts } from '@nymproject/contract-clients';
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
Example: using the Mixnet smart contract client to execute methods

In this example, we will use the MixnetClientand the signer from the Contract Clients (opens in a new tab) to execute methods.

Note that for the settings.ts file, we have used the following structure:

 
export const mySettings = {
    url: "wss://rpc.nymtech.net:443",
    mixnetContractAddress: <ENTER MIXNET CONTACT ADDRESS HERE>,
    mnemonic: '<ENTER MNEMONIC HERE>,
    address: <ENTER NYM ADDRESS HERE>
};
 
export const settings = mySettings;
 
import "./App.css";
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.ts";
 
export default function Exec() {
  let signer = null;
  let address = null;
  let signerMixnetClient = null;
  let cosmWasmSigningClient = null;
  let mixId = null;
  let amountToDelegate = null;
  let balance = null;
  let nodeAddress = null;
  let amountToSend = null;
  let delegations = null;
 
  async function ExecuteOnNyx() {
    // Signer
    try {
      // Generate a signer from a mnemonic
      signer = await DirectSecp256k1HdWallet.fromMnemonic(settings.mnemonic, {
        prefix: "n",
      });
      const accounts = await signer.getAccounts();
      address = accounts[0].address;
    } catch (error) {
      console.error("Problem getting the signer: ", error);
    }
 
    try {
      const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(
        settings.url,
        signer,
        {
          gasPrice: GasPrice.fromString("0.025unym"),
        }
      );
      cosmWasmSigningClient = cosmWasmClient;
      try {
        balance = await cosmWasmSigningClient?.getBalance(address, "unym");
        console.log("balance", balance);
      } catch (error) {
        console.error("problem geting the balance: ", error);
      }
 
      const mixnetClient = new contracts.Mixnet.MixnetClient(
        cosmWasmSigningClient,
        settings.address, // sender (that account of the signer)
        settings.mixnetContractAddress // contract address (different on mainnet, QA, etc)
      );
      signerMixnetClient = mixnetClient;
    } catch (error) {
      console.error("Problem getting the cosmWasmSigningClient: ", error);
    }
  }
 
  // Get delegations
  const getDelegations = async () => {
    if (!signerMixnetClient) {
      return;
    }
    const delegationsObject = await signerMixnetClient.getDelegatorDelegations({
      delegator: settings.address,
    });
    delegations = delegationsObject;
  };
 
  // Make delegation
  const doDelegation = async () => {
    if (!signerMixnetClient) {
      return;
    }
    try {
      const res = await signerMixnetClient.delegateToMixnode(
        { mixId },
        "auto",
        undefined,
        [{ amount: `${amountToDelegate}`, denom: "unym" }]
      );
      console.log("delegations: ", res);
    } catch (error) {
      console.error(error);
    }
  };
 
  // Undelegate all
  const doUndelegateAll = async () => {
    if (!signerMixnetClient) {
      return;
    }
    console.log("delegations", delegations);
    try {
      for (const delegation of delegations.delegations) {
        await signerMixnetClient.undelegateFromMixnode(
          { mixId: delegation.mix_id },
          "auto"
        );
      }
    } catch (error) {
      console.error(error);
    }
  };
 
  // Sending tokens
  const doSendTokens = async () => {
    const memo = "test sending tokens";
 
    try {
      const res = await cosmWasmSigningClient.sendTokens(
        settings.address,
        nodeAddress,
        [{ amount: amountToSend, denom: "unym" }],
        "auto",
        memo
      );
      console.log("res", res);
    } catch (error) {
      console.error(error);
    }
  };
 
  ExecuteOnNyx();
  setTimeout(() => getDelegations(), 1000);
 
  return (
    <div>
      <p>Exec</p>
      <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)}
        />
        <div>
          <button onClick={() => doSendTokens()}>Send Tokens</button>
        </div>
      </div>
      <div>
        <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)}
        />
        <div>
          <button onClick={() => doDelegation()}>Delegate</button>
        </div>
        <div>
          <button onClick={() => doUndelegateAll()}>Undelegate All</button>
        </div>
      </div>
    </div>
  );
}