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 different available clients and methods from the Contract Clients
can be found in the .client.ts
files:
Client name | Functionality | Methods list |
---|---|---|
Coconut Bandwidth Client | Manages the depositing and release of funds. Tracks double spending. | Coconut Bandwidth (opens in a new tab) |
Coconut DKG Client | Allows signers participating in issuing Coconut credentials to derive keys to be used. | Coconut DKG (opens in a new tab) |
Cw3FlexMultisig Client | Used 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 Client | Used 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 Client | Manages the network topology of the mixnet, tracking delegations and rewards. | Mixnet (opens in a new tab) |
Name Service Client | Operates as a directory of user-defined aliases, analogous to a Domain Name System (DNS). | Name service (opens in a new tab) |
Service provider Directory Client | Allows users to register their service provider in a public directory. | Service Provider (opens in a new tab) |
Vesting Client | Manages NYM token vesting functionality. | Vesting (opens in a new tab) |
Environment Setup
Begin by creating a directory and configuring your application environment:
npm create vite@latest
During the environment setup, choose React and subsequently opt for Typescript if you want your application to function smoothly following this tutorial. Next, navigate to your application directory and run the following commands:
cd < YOUR_APP >
npm i
npm run dev
Installation
Install the packages and their dependencies if you don't already have them:
npm install @nymproject/contract-clients @cosmjs/cosmwasm-stargate
Query clients
In the src
folder, open the App.tsx
file and delete all the code.
Imports
Import the contracts' client in your app:
import { contracts } from '@nymproject/contract-clients';
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
Example: using the mixnet smart contract client to query
In this example, we will use the MixnetQueryClient
from 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<any>([]);
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 mainnet mixnet contract address (which will be different on mainnet, QA, etc)
);
const result = await client.getMixNodesDetailed({});
setMixnodes(result.nodes)
}
useEffect(() => {
fetchMixnodes();
}, [])
return(
<>
<table>
<tbody>
{mixnodes?.map((value: any, index: number) => {
return(
<tr key={index}>
<td> {value?.bond_information?.mix_node?.identity_key} </td>
</tr>
)
})
}
</tbody>
</table>
</>
)
}
By pasting the above code in the App.tsx
file and npm run dev
your app from the terminal, you should see an unstyled printed list of Nym mixnodes!
Execute clients
Installation
Install the packages and their dependencies if you don't already have them:
npm install @nymproject/contract-clients @cosmjs/cosmwasm-stargate @cosmjs/proto-signing
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 MixnetClient
and the signer
from the Contract Clients
(opens in a new tab) to execute methods.
Note that you will need to create a settings.ts
file (here created in the same directory), using 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";
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() {
// Cosmos client
signer = await DirectSecp256k1HdWallet.fromMnemonic(settings.mnemonic, {
prefix: "n",
});
const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(
settings.url,
signer,
{
gasPrice: GasPrice.fromString("0.025unym"),
}
);
// Save globally
cosmWasmSigningClient = cosmWasmClient;
// Nym client
const mixnetClient = new contracts.Mixnet.MixnetClient(
cosmWasmSigningClient,
settings.address, // Sender (that account of the signer)
settings.mixnetContractAddress // Contract address (different on mainnet, QA, etc)
);
// Save globally
signerMixnetClient = mixnetClient;
}
// 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;
}
const res = await signerMixnetClient.delegateToMixnode(
{ mixId },
"auto",
undefined,
[{ amount: `${amountToDelegate}`, denom: "unym" }]
);
console.log(res);
};
// Undelegate all
const doUndelegateAll = async () => {
for (const delegation of delegations.delegations) {
await signerMixnetClient.undelegateFromMixnode(
{ mixId: delegation.mix_id },
"auto"
);
}
};
// Sending tokens
const doSendTokens = async () => {
const memo = "test sending tokens";
const res = await cosmWasmSigningClient.sendTokens(
settings.address,
nodeAddress,
[{ amount: amountToSend, denom: "unym" }],
"auto",
memo
);
console.log(res);
};
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>
);
}