arc-sdk-test
v0.0.55
Published
Arc SDK Test
Readme
arcane-sdk
TypeScript SDK for interacting with the Arcane privacy protocol on Solana — deposits, withdrawals, private transfers, and fee quotes.
Installation
npm install arcane-sdkPeer dependencies (optional, for React):
npm install @solana/wallet-adapter-react reactPrerequisites
- A Solana wallet (
Keypairfor backend/scripts, or a wallet adapter withsignMessage/signAllTransactionsfor frontend) - A Range API key (
rangeApiKey) - An RPC endpoint or existing
@solana/web3.jsConnection
Supported networks: mainnet and devnet (inferred from the RPC URL, or set explicitly via network).
Creating an ArcaneSDK instance
Create one SDK instance per configuration (network, RPC, wallet). Initialization loads active relayers for the target network.
Node / backend
import { Keypair } from "@solana/web3.js";
import { ArcaneSDK } from "arcane-sdk";
const wallet = Keypair.generate(); // or your existing keypair
const sdk = await ArcaneSDK.create({
rangeApiKey: process.env.RANGE_API_KEY!,
rpcEndpoint: "https://api.devnet.solana.com",
wallet,
});React (wallet-adapter)
Wrap your app with ConnectionProvider and WalletProvider, then use the React hook:
import { useArcaneSdk } from "arcane-sdk/react";
function MyComponent() {
const sdk = useArcaneSdk({
rangeApiKey: import.meta.env.VITE_RANGE_API_KEY,
});
if (!sdk) return null; // wallet not connected yet
// use sdk...
}Init options
| Option | Required | Description |
|--------|----------|-------------|
| rangeApiKey | yes | Range API key for risk/oracle features |
| wallet | yes | Anchor-compatible wallet (Keypair or wallet adapter) |
| rpcEndpoint | one of | Solana JSON-RPC URL (Node/scripts) |
| connection | one of | Existing Connection (e.g. from useConnection()) |
| network | no | "mainnet" or "devnet" — override when the RPC URL has no cluster hint |
After creation, inspect runtime config via sdk.config or helpers like sdk.getNetwork(), sdk.relayers, and sdk.getTokenMints().
getEncryptionKey
Derives a note-encryption key from a wallet signature and stores it on the SDK instance (sdk.encryptKey). Required before any deposit that uses on-chain note backup (onChainBackup: true, including arcaneTransfer).
The wallet signs the message arcane:notes:v1. Accepts a backend Keypair or a frontend wallet adapter with signMessage.
await sdk.getEncryptionKey(wallet);
// sdk.encryptKey is now setThe key is used to encrypt secret notes before they are stored on-chain via backupNotes, so you can recover notes later from the same wallet.
buildDepositTx
Builds an unsigned deposit transaction for a pre-generated secret note.
1. Generate deposit parameters
// 1 SOL deposit (lamports)
const { note } = sdk.generateDepositParams(1_000_000_000n, null);
// SPL token deposit — pass the token mint
const usdcMint = sdk.getTokenMint("USDC");
const { note: usdcNote } = sdk.generateDepositParams(1_000_000n, usdcMint);Deposit amounts must match supported pool denominations for each token.
2. Build the transaction
await sdk.getEncryptionKey(wallet); // required when onChainBackup is true
const { tx, note } = await sdk.buildDepositTx({
senderPublicKey: wallet.publicKey,
note,
onChainBackup: true, // encrypt and store note on-chain (recommended)
computeUnitPrice: 50_000, // optional priority fee
});Sign and send the returned tx with your wallet. Save the returned note — it is required to withdraw later.
| Parameter | Description |
|-----------|-------------|
| senderPublicKey | Depositor's public key |
| note | Secret note from generateDepositParams |
| onChainBackup | When true, encrypts the note and adds a backupNotes instruction (requires getEncryptionKey) |
| computeUnitPrice | Priority fee in micro-lamports (default 50000) |
withdraw
Withdraws funds from the privacy pool to a recipient using a secret note from a prior deposit. The SDK:
- Validates the recipient against the risk API
- Fetches Merkle commitments from the indexer
- Generates a ZK withdraw proof
- Submits the proof to a relayer (chosen at random, or by index)
- Polls until the relayer confirms the on-chain transaction
const result = await sdk.withdraw({
note: "arcane-1-...", // secret note from deposit
recipient: "RecipientPubkey...", // withdrawal destination
relayerIdx: 0, // optional — random relayer when omitted
});
console.log(result.txHash); // on-chain transaction signature
console.log(result.status); // "success" | "failed"| Parameter | Description |
|-----------|-------------|
| note | Secret note from the original deposit |
| recipient | Recipient public key (PublicKey or base58 string) |
| relayerIdx | Optional index into sdk.relayers |
Withdraw fees are calculated automatically from the relayer fee and on-chain platform fee.
arcaneTransfer
End-to-end private transfer: deposit into the pool (split across supported denominations), then withdraw each successful note to the recipient. Handles signing, sending, and settlement automatically.
Requires getEncryptionKey before calling — all deposits use on-chain backup.
import { PublicKey } from "@solana/web3.js";
await sdk.getEncryptionKey(wallet);
const result = await sdk.arcaneTransfer(
[
{
mint: new PublicKey(sdk.getTokenMint("USDC")),
amount: "25.5", // human-readable amount
recipient: new PublicKey("RecipientPubkey..."),
},
{
mint: new PublicKey(sdk.getTokenMints().Solana),
amount: "1.5",
recipient: new PublicKey("AnotherRecipient..."),
},
],
{ uniqueRelayer: true } // optional — use one relayer for all withdraws
);
if (result.error) {
console.log("Deposit failures:", result.depositFailed);
console.log("Withdraw failures:", result.withdrawFailed);
}| Field | Description |
|-------|-------------|
| items[].mint | Token mint to transfer |
| items[].amount | Human-readable amount (e.g. "1.5" SOL) |
| items[].recipient | Withdrawal destination for that transfer |
| options.uniqueRelayer | When true, all withdraws share one randomly selected relayer |
The SDK splits each amount into the nearest supported deposit denominations, builds and sends deposit transactions, waits for settlement, then withdraws each note to its recipient. Partial failures are reported in depositFailed and withdrawFailed without throwing.
getQuote
Fetches a withdraw fee quote from the Arcane indexer before executing a withdrawal. Returns estimated relayer fees, recipient amount, ETA, and how the amount splits across denominations.
const { quote } = await sdk.getQuote({
amount: 1.5, // human-readable amount
amountLamports: 1_500_000_000, // same amount in smallest units
recipient: "RecipientPubkey...",
asset: "SOL", // optional — default "SOL"
});
console.log(quote.recipientAmount); // amount recipient receives after fees
console.log(quote.totalRelayerFee);
console.log(quote.etaSeconds);
console.log(quote.splits); // per-denomination breakdown
console.log(quote.platformFee); // platform fee (added by SDK)| Parameter | Description |
|-----------|-------------|
| amount | Human-readable transfer/withdraw amount |
| amountLamports | Amount in smallest token units |
| recipient | Intended withdrawal recipient |
| asset | Indexer asset label (default "SOL") |
| network | Optional cluster override |
getQuote is also exported as a standalone function but requires an initialized SDK context.
Typical flows
Deposit and withdraw
const sdk = await ArcaneSDK.create({ rangeApiKey, rpcEndpoint, wallet });
await sdk.getEncryptionKey(wallet);
const { note } = sdk.generateDepositParams(1_000_000_000n, null);
const { tx } = await sdk.buildDepositTx({
senderPublicKey: wallet.publicKey,
note,
onChainBackup: true,
});
// sign and send tx...
const { txHash } = await sdk.withdraw({
note,
recipient: "RecipientPubkey...",
});Quote before withdraw
const { quote } = await sdk.getQuote({
amount: 1,
amountLamports: 1_000_000_000,
recipient: "RecipientPubkey...",
});
console.log(`Recipient receives ~${quote.recipientAmount} SOL`);
await sdk.withdraw({ note, recipient: "RecipientPubkey..." });Supported deposit denominations
Amounts must decompose exactly into these pool denominations:
| Token | Denominations | |-------|---------------| | SOL | 0.1, 1, 5, 10, 50, 100, 500 | | USDC | 1, 10, 50, 100, 1000, 10000, 100000, 1000000 | | Arcane | 1, 10, 50, 100, 500, 1000, 10000, 100000, 1000000 | | Bitcoin | 0.01, 0.05, 0.1, 0.5, 1, 5 | | Ethereum | 0.1, 1, 10, 50, 100, 500 |
Use sdk.getDepositAmounts("Solana") (or another symbol) to retrieve the list programmatically.
License
MIT
