Skip to content

CryptosDAO/CryptosChainSDK

Repository files navigation

Cryptos EVM SDK

Official TypeScript SDK for interacting with the Cryptos EVM network.

Built on top of viem with first-class TypeScript support.


Installation

npm install @cryptos/evm-client @cryptos/contracts

For React apps:

npm install @cryptos/evm-client @cryptos/contracts @cryptos/react

Quick Start

import { createCryptosClient } from "@cryptos/evm-client";

// Create a read-only client
const client = createCryptosClient();

// Get the current block number
const blockNumber = await client.public.getBlockNumber();
console.log("Current block:", blockNumber);

Packages

Package Description
@cryptos/evm-client Core client for read/write operations
@cryptos/contracts Typed contract wrappers (ERC20, etc.)
@cryptos/react React hooks for dApps

Chain Configuration

The SDK comes pre-configured for Cryptos Testnet Beta:

import { cryptosTestnetBeta } from "@cryptos/evm-client";

console.log(cryptosTestnetBeta);
// {
//   id: 77777777,
//   name: "Cryptos Testnet Beta",
//   nativeCurrency: { name: "CRYPTOS", symbol: "CRYPTOS", decimals: 18 },
//   rpcUrls: { default: { http: ["https://rpc-testnet-beta-evm.cryptos.com"] } },
//   testnet: true
// }

Client Setup

Read-Only Client

For reading blockchain state (no private key needed):

import { createCryptosClient } from "@cryptos/evm-client";

const client = createCryptosClient();

// Access the public client for all read operations
const blockNumber = await client.public.getBlockNumber();
const balance = await client.public.getBalance({
  address: "0x1234567890123456789012345678901234567890"
});

Client with Wallet (for Transactions)

To send transactions, you need to provide an account:

import { createCryptosClient } from "@cryptos/evm-client";
import { privateKeyToAccount } from "viem/accounts";

// Create account from private key
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY_HERE");

// Create client with wallet capabilities
const client = createCryptosClient({ account });

// Now client.wallet is available for write operations
console.log("Wallet address:", account.address);

Custom RPC URL

const client = createCryptosClient({
  rpcUrl: "https://your-custom-rpc.example.com",
});

Common Read Operations

Get Block Number

const blockNumber = await client.public.getBlockNumber();
console.log("Block:", blockNumber); // e.g., 12345678n

Get Native Token Balance (CRYPTOS)

import { formatEther } from "viem";

const balance = await client.public.getBalance({
  address: "0x1234567890123456789012345678901234567890",
});

console.log("Balance (wei):", balance);
console.log("Balance (CRYPTOS):", formatEther(balance));

Get Transaction Count (Nonce)

const nonce = await client.public.getTransactionCount({
  address: "0x1234567890123456789012345678901234567890",
});
console.log("Nonce:", nonce);

Sending Native Tokens (CRYPTOS)

Send CRYPTOS from your wallet to another address:

import { createCryptosClient } from "@cryptos/evm-client";
import { privateKeyToAccount } from "viem/accounts";
import { parseEther } from "viem";

// Setup client with wallet
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY_HERE");
const client = createCryptosClient({ account });

// Send 1.5 CRYPTOS to recipient
const hash = await client.wallet.sendTransaction({
  to: "0xRecipientAddressHere",
  value: parseEther("1.5"),
});

console.log("Transaction hash:", hash);

// Wait for confirmation
const receipt = await client.public.waitForTransactionReceipt({ hash });
console.log("Confirmed in block:", receipt.blockNumber);
console.log("Status:", receipt.status); // "success" or "reverted"

ERC20 Token Interactions

Using the ExampleErc20 Wrapper

The SDK provides a typed wrapper for ERC20 tokens:

import { createCryptosClient } from "@cryptos/evm-client";
import { ExampleErc20 } from "@cryptos/contracts";

const client = createCryptosClient();

// Create ERC20 wrapper (pass the token contract address)
const token = ExampleErc20(client, "0xTokenContractAddressHere");

// Read token info
const name = await token.read.name();
const symbol = await token.read.symbol();
const decimals = await token.read.decimals();
const totalSupply = await token.read.totalSupply();

console.log(`${name} (${symbol})`);
console.log(`Decimals: ${decimals}`);
console.log(`Total Supply: ${totalSupply}`);

// Check balance
const balance = await token.read.balanceOf("0xYourAddressHere");
console.log(`Balance: ${balance}`);

Transfer ERC20 Tokens

import { createCryptosClient } from "@cryptos/evm-client";
import { ExampleErc20 } from "@cryptos/contracts";
import { privateKeyToAccount } from "viem/accounts";

// Setup client with wallet
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY_HERE");
const client = createCryptosClient({ account });

// Create ERC20 wrapper
const token = ExampleErc20(client, "0xTokenContractAddressHere");

// Transfer 1000 tokens (assuming 18 decimals)
const amount = 1000n * 10n ** 18n; // 1000 tokens in wei
const hash = await token.write.transfer("0xRecipientAddressHere", amount);

console.log("Transfer tx:", hash);

// Wait for confirmation
const receipt = await client.public.waitForTransactionReceipt({ hash });
console.log("Transfer confirmed:", receipt.status);

Watch Transfer Events

const token = ExampleErc20(client, "0xTokenContractAddressHere");

const unwatch = token.watch.Transfer({
  onLogs: (logs) => {
    for (const log of logs) {
      console.log("Transfer event:", {
        from: log.args.from,
        to: log.args.to,
        value: log.args.value,
      });
    }
  },
  onError: (error) => {
    console.error("Watch error:", error);
  },
  pollingInterval: 5000, // Poll every 5 seconds
});

// Later: stop watching
// unwatch();

Generic Contract Interactions

Use createContract to interact with any smart contract:

import { createCryptosClient } from "@cryptos/evm-client";
import { createContract } from "@cryptos/contracts";
import { privateKeyToAccount } from "viem/accounts";

// Your contract's ABI
const myAbi = [
  {
    name: "getValue",
    type: "function",
    stateMutability: "view",
    inputs: [],
    outputs: [{ type: "uint256" }],
  },
  {
    name: "setValue",
    type: "function",
    stateMutability: "nonpayable",
    inputs: [{ name: "newValue", type: "uint256" }],
    outputs: [],
  },
  {
    name: "ValueChanged",
    type: "event",
    inputs: [
      { name: "oldValue", type: "uint256", indexed: false },
      { name: "newValue", type: "uint256", indexed: false },
    ],
  },
] as const;

// Setup client
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY_HERE");
const client = createCryptosClient({ account });

// Create contract wrapper
const contract = createContract({
  client,
  address: "0xYourContractAddressHere",
  abi: myAbi,
});

// Read contract state
const value = await contract.read("getValue");
console.log("Current value:", value);

// Write to contract
const hash = await contract.write("setValue", [42n]);
console.log("setValue tx:", hash);

// Watch events
const unwatch = contract.watch("ValueChanged", {
  onLogs: (logs) => {
    console.log("Value changed:", logs);
  },
});

React Hooks

useCryptosClient

Create a memoized client instance:

import { useCryptosClient } from "@cryptos/react";

function MyComponent() {
  const client = useCryptosClient();

  const handleClick = async () => {
    const block = await client.public.getBlockNumber();
    console.log("Block:", block);
  };

  return <button onClick={handleClick}>Get Block</button>;
}

With custom options:

const client = useCryptosClient({
  rpcUrl: "https://custom-rpc.example.com",
  chainId: 77777777,
});

useBalance

Poll the native token balance of an address:

import { useBalance } from "@cryptos/react";
import { formatEther } from "viem";

function BalanceDisplay({ address }: { address: `0x${string}` }) {
  const { balance, isLoading, error } = useBalance(address, {
    pollMs: 5000, // Poll every 5 seconds (default)
  });

  if (isLoading && balance === undefined) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return <div>Balance: {formatEther(balance ?? 0n)} CRYPTOS</div>;
}

useBlockNumber

Poll the current block number:

import { useBlockNumber } from "@cryptos/react";

function BlockDisplay() {
  const { blockNumber, isLoading, error } = useBlockNumber({
    pollMs: 3000, // Poll every 3 seconds (default)
  });

  if (isLoading && blockNumber === undefined) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return <div>Current Block: {blockNumber?.toString()}</div>;
}

Type Safety

The SDK provides TypeScript utilities for safer wallet operations:

import { createCryptosClient, assertWallet } from "@cryptos/evm-client";
import { privateKeyToAccount } from "viem/accounts";

const client = createCryptosClient({
  account: privateKeyToAccount("0x..."),
});

// assertWallet throws if wallet is not configured
assertWallet(client);

// After assertion, TypeScript knows client.wallet exists
const hash = await client.wallet.sendTransaction({
  to: "0x...",
  value: 1000n,
});

Complete Example: Token Transfer dApp

import { createCryptosClient } from "@cryptos/evm-client";
import { ExampleErc20 } from "@cryptos/contracts";
import { privateKeyToAccount } from "viem/accounts";
import { formatUnits, parseUnits } from "viem";

async function main() {
  // 1. Setup
  const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
  const client = createCryptosClient({ account });

  console.log("Wallet:", account.address);

  // 2. Check native balance
  const nativeBalance = await client.public.getBalance({
    address: account.address
  });
  console.log("CRYPTOS Balance:", formatUnits(nativeBalance, 18));

  // 3. Setup token
  const tokenAddress = "0xYourTokenAddress" as `0x${string}`;
  const token = ExampleErc20(client, tokenAddress);

  const symbol = await token.read.symbol();
  const decimals = await token.read.decimals();
  const tokenBalance = await token.read.balanceOf(account.address);

  console.log(`${symbol} Balance:`, formatUnits(tokenBalance, decimals));

  // 4. Transfer tokens
  const recipient = "0xRecipientAddress" as `0x${string}`;
  const amount = parseUnits("100", decimals); // 100 tokens

  console.log(`Transferring 100 ${symbol} to ${recipient}...`);

  const hash = await token.write.transfer(recipient, amount);
  console.log("Transaction:", hash);

  const receipt = await client.public.waitForTransactionReceipt({ hash });
  console.log("Status:", receipt.status);
}

main().catch(console.error);

API Reference

@cryptos/evm-client

Export Description
createCryptosClient(config?) Create a client for read/write operations
cryptosTestnetBeta Chain configuration for Cryptos Testnet Beta
assertWallet(client) Assert that client has a wallet configured

@cryptos/contracts

Export Description
createContract({ client, address, abi }) Create a generic contract wrapper
ExampleErc20(client, address?) Create an ERC20 token wrapper
ERC20_ABI Standard ERC20 ABI
ADDRESSES Deployed contract addresses by network

@cryptos/react

Export Description
useCryptosClient(options?) Hook to create/memoize a client
useBalance(address?, options?) Hook to poll native token balance
useBlockNumber(options?) Hook to poll current block number

License

MIT

About

CryptosChainSDK

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors