🚀 DAY 5 OF LAUNCH WEEK: Introducing Socket Firewall Enterprise.Learn more →
Socket
Book a DemoInstallSign in
Socket

@sei-js/confidential-transfers

Package Overview
Dependencies
Maintainers
3
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package was removed
Sorry, it seems this package was removed from the registry

@sei-js/confidential-transfers

A TypeScript library for the Confidential Transfers Module

unpublished
latest
Source
npmnpm
Version
0.0.0-internal-20250416210143
Version published
Maintainers
3
Created
Source

Confidential Transfers with Typescript

This library is a TS library used to interact with the Confidential Transfers module on Sei.

Typescript Workflow

The goal is to have a generic typescript library that can be used in both backend and browser environments to:

  • Generate the objects required to interact with the CT Module
  • Query the confidential transfers modules
  • Send transactions to the chain

Getting Started:

  • Start a instance of sei-chain locally
  • Run yarn to install dependencies
  • Run yarn build-wasm to build the wasm file from go code in confidentialWasm
  • Build the package by running yarn build
  • Run yarn test to run src/test/test.ts and see the library in action.

Note that running tests will require a running instance of sei-chain locally.

Usage

There are functions in this library for both Ethers and Viem users.

Usage (Ethers)

This section covers how to use the Ethers-based confidential transfer functions.

1. Sign a Denom

In the Confidential Transfers Module, an account for a denom has a unique keypair. This keypair is derived from a secret that is generated by:

  • Appending "ct:" to the denom
  • keccak256 hashing the appended denom
  • Signing the hash with the wallet

Your public and private keys (for the confidential balances) can be derived from this Signature and thus it should never be revealed or stored server side.

To generate this signature on some denom:

import { getDenomToSignEthers } from "confidential-ts";

const denom = "usei";
const denomHash = getDenomToSignEthers(denom);
const signedDenom = await wallet.signMessage(denomHash);

The examples below also assume you have generated an ethers wallet. For example:

    const provider = new ethers.JsonRpcProvider("http://localhost:8545");
    const testWallet = ethers.Wallet.createRandom().connect(provider);

2. Initialize an Account

Creates a confidential account on chain for the specified address and denom. signedDenom refers to the signature of the hashed denom (generated in Step 1. above)

await initializeAccountEthers(signedDenom, wallet.address, denom, wallet);

3. Query Account Info

Fetches the full confidential account state from the precompile contract.

import { queryAccountEthers } from "confidential-ts";

const account = await queryAccountEthers(wallet.Address, denom, wallet);

4. Decrypt Account Balances

Decrypts the pending and available balance commitments stored on chain.

signedDenom refers to the signature of the hashed denom (generated in Step 1. above)

The 3rd parameter, decryptFullAvailableBalance is a boolean that indicates whether to decrypt the available balance. This can take a long time and should only be set to true if you need it. Otherwise, it decrypts the decryptableAvailableBalance by default.

import { decryptAccountEthers } from "confidential-ts";

const decrypted = await decryptAccountEthers(signedDenom, account, false);
console.log("Decrypted balances:", decrypted);

5. Deposit into Account

Initiates a confidential deposit of the specified amount into the account. NOTE: The deposit amount is in the native decimal place (6 decimals for usei)

import { depositEthers } from "confidential-ts";

const depositAmount = 1000000 // 1 SEI
await depositEthers(denom, depositAmount, wallet);

6. Apply Pending Balance

Moves any pending balance into the available balance for spending. signedDenom refers to the signature of the hashed denom (generated in Step 1. above)

import { applyPendingBalanceEthers } from "confidential-ts";

await applyPendingBalanceEthers(wallet.address, denom, signedDenom, wallet);

7. Withdraw from Account

Withdraws a specified amount from the confidential balance. signedDenom refers to the signature of the hashed denom (generated in Step 1. above)

NOTE: The withdraw amount is in the native decimal place (6 decimals for usei)

import { withdrawEthers } from "confidential-ts";

const withdrawAmount = 1000000 // 1 SEI
await withdrawEthers(wallet.address, denom, withdrawAmount, signedDenom, wallet);

8. Transfer Between Accounts

Transfers a confidential balance from one account to another. The recipient must have already initialized an account. signedDenom refers to the signature of the hashed denom (generated in Step 1. above)

NOTE: The deposit amount is in the native decimal place (6 decimals for usei)

import { transferEthers } from "confidential-ts";

const transferAmount = 500000 // 0.5 SEI
await transferEthers(wallet.address, recipientAddress, denom, transferAmount, signedDenom, wallet);

9. Close Account

Closes a confidential account and clears its on-chain state.

import { closeAccountEthers } from "confidential-ts";

await closeAccountEthers(wallet.address, denom, signedDenom, wallet);

Each method internally handles proof generation, encryption and decoding, contract calls, and gas estimation using Ethers v6.

For a full working script that tests these functions end-to-end, see the sample file src/test/test.ts.

Usage (Viem)

This section shows how to use the Viem-based confidential transfer functions with frontend frameworks like React. These examples use wagmi and viem.

1. Generate a Signed Denom

Confidential accounts use a unique keypair per denom. To derive this keypair, you must:

  • Append "ct:" to your denom
  • Hash it with keccak256
  • Sign the hash with your wallet
import { getDenomToSignViem } from "sei-confidential";
import { useSignMessage } from "wagmi";

const { signMessageAsync } = useSignMessage();

const denom = "usei";
const ctDenomHash = getDenomToSignViem(denom);

const signedDenom = await signMessageAsync({
  message: ctDenomHash,
});

2. Initialize an Account

Creates a confidential account on-chain. Requires a signed denom.

import { getInitializeAccountViemArgs } from "sei-confidential";
import { useWriteContract, useAccount } from "wagmi";
import { usePublicClient } from "wagmi";

const { address } = useAccount();
const publicClient = usePublicClient();
const { writeContractAsync } = useWriteContract();

const txParams = await getInitializeAccountViemArgs(signedDenom, address, "usei");
const estimatedGas = await publicClient.estimateContractGas(txParams);
await writeContractAsync({ ...txParams, gas: estimatedGas });

3. Query Account

Fetch encrypted confidential balance and metadata from chain.

import { queryAccountViem } from "sei-confidential";
import { usePublicClient } from "wagmi";

const publicClient = usePublicClient();
const account = await queryAccountViem(publicClient, address, "usei");

4. Decrypt Confidential Balances

Use the signed denom to decrypt account balances off-chain.

import { decryptAccountViem } from "sei-confidential";

const decrypted = await decryptAccountViem(signedDenom, account, false);
console.log("Decrypted account:", decrypted);

Set the last parameter to true to also decrypt the full available balance (expensive).

5. Deposit

Send tokens into your confidential account.

import { getDepositViemArgs } from "sei-confidential";

const amount = BigInt(1_000_000); // 1 SEI = 1_000_000 microsei
const depositParams = getDepositViemArgs(address, "usei", amount);
const estimatedGas = await publicClient.estimateContractGas(depositParams);
await writeContractAsync({ ...depositParams, gas: estimatedGas });

6. Apply Pending Balance

Move pending balance to available balance (required after a deposit or receiving funds).

import { getApplyPendingBalancesViemArgs } from "sei-confidential";

const applyParams = await getApplyPendingBalancesViemArgs(address, "usei", publicClient, signedDenom);
const estimatedGas = await publicClient.estimateContractGas(applyParams);
await writeContractAsync({ ...applyParams, gas: estimatedGas });

7. Withdraw

Withdraw from your confidential balance.

import { getWithdrawViemArgs } from "sei-confidential";

const withdrawParams = await getWithdrawViemArgs(address, "usei", 500000, publicClient, signedDenom);
const estimatedGas = await publicClient.estimateContractGas(withdrawParams);
await writeContractAsync({ ...withdrawParams, gas: estimatedGas });

8. Transfer

Send confidential tokens to another account.

import { getTransferViemArgs } from "sei-confidential";

const transferParams = await getTransferViemArgs(address, recipient, "usei", 500000, publicClient, signedDenom);
const estimatedGas = await publicClient.estimateContractGas(transferParams);
await writeContractAsync({ ...transferParams, gas: estimatedGas });

Note: The recipient must have initialized their account before they can receive confidential transfers.

Setup Requirements

Make sure your app includes the following:

  • wagmi and viem hooks (useAccount, useSignMessage, useWriteContract, usePublicClient)
  • An initialized signer and connected wallet
  • confidential-ts installed and imported

Reference

All Viem-compatible functions return pre-filled contract parameters for execution via viem or wagmi's writeContractAsync. These include:

  • address: precompile contract address
  • abi: precompile ABI
  • functionName: the contract function to call
  • args: properly encoded parameters

You must estimate gas and call the contract using your client or wagmi.

const gas = await publicClient.estimateContractGas(generatedParams);
await writeContractAsync({ ...generatedParams, gas });

For a complete interactive example, see Homepage/Examples.tsx in the project.

How it works

This module has 2 parts, a go library (confidentialWasm), and a typescript library.

Go (confidentialWasm)

Since the important primitives for the Confidential Transfers module (encoding libraries, proof generation) are written in Go, we don't want to rewrite these libraries in typescript as that might cause irregularities.

The confidentialWasm directory contains a go project that will be compiled to WASM, where it can be read by typescript.

Protos

This library currently contains it's own protos (in the confidentialWasm/proto directory) that need to be copied from the sei-chain repository to update.

To update the protos:

  • Copy the updated .proto files from the sei-chain to the confidentialWasm/proto/confidentialTransfers directory.
  • From the root directory, run yarn build-protos to regenerate the proto files in confidentialWasm/cttypes/confidentialTransfers

The files in the confidentialWasm/cttypes contain helper functions that help us convert functional types to their generated proto message equivalent. This conversion is also replicated in the sei-chain repo.

Methods

The methods directory contains functions that we want to be able to call from typescript.

confidentialWasm/main.go contains a mapping of functionName to the corresponding methods defined in the methods directory. For each method, it simply parses the input arguments from the js caller, performs the logic in go, then returns a JSON encoded string as the result.

Typescript (src)

The src directory contains the typescript interfaces and methods that users can use.

The src/interface directory contains the main interfaces and methods that this library exposes - these are split into methods meant for Ethers and Viem users (examples provided below)

The src/payload directory contains the underlying functions. In order to invoke the WASM code generated in confidentialWasm, the typescript API

  • Starts a go runtime in the browser/node environment
  • Stories the WASM methods in the globalThis object
  • Encodes/Decodes the user's input appropriately and calls the appropriate WASM method store in globalThis
  • Encodes/Deocdes the responses

Keywords

sei

FAQs

Package last updated on 16 Apr 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts