nara-sdk
v1.0.90
Published
SDK for the Nara chain (Solana-compatible)
Readme
TypeScript/JavaScript SDK for interacting with the Nara blockchain. Build agents, submit transactions, query accounts, cross-chain bridge, and integrate with on-chain programs.
Install
npm install nara-sdkFeatures
- Agent Registry — Register agents, bind Twitter, submit tweets, verify, referral system
- Quest (Boost PoMI) — Proof of Machine Intelligence ZK quest system — credit-gated, answer-to-earn
- Skills Hub — On-chain skill registry for AI agents, upload/query skill content
- ZK ID — Zero-knowledge anonymous identity, deposit, withdraw, ownership proofs
- Cross-chain Bridge — Nara ↔ Solana bridge via Hyperlane warp routes (USDC, SOL), with in-tx fee extraction and validator signature tracking
Quick Start
import { Connection, Keypair } from '@solana/web3.js';
import { getQuestInfo, submitAnswer, generateProof } from 'nara-sdk';
const connection = new Connection('https://mainnet-api.nara.build');Cross-chain Bridge
Bridge tokens between Solana and Nara with built-in fee extraction (0.5% or per-token floor, whichever is higher).
One-step bridge
import { Connection, Keypair } from '@solana/web3.js';
import { bridgeTransfer, setAltAddress } from 'nara-sdk';
const solanaConn = new Connection('https://api.mainnet-beta.solana.com');
// Disable Nara ALT when sending from Solana
setAltAddress(null);
const result = await bridgeTransfer(solanaConn, wallet, {
token: 'USDC', // 'USDC' | 'SOL'
fromChain: 'solana', // 'solana' | 'nara'
recipient: targetPubkey, // destination chain address
amount: 1_000_000n, // raw units (1 USDC = 1_000_000)
});
console.log(result.signature); // source chain tx
console.log(result.messageId); // cross-chain message ID (0x...)
console.log(result.feeAmount); // fee deducted
console.log(result.bridgeAmount); // net amount bridgedBuild instructions for relay
import { makeBridgeIxs } from 'nara-sdk';
const { instructions, uniqueMessageKeypair, feeAmount, bridgeAmount } =
makeBridgeIxs({
token: 'USDC',
fromChain: 'solana',
sender: userPubkey,
recipient: targetPubkey,
amount: 1_000_000n,
});
// uniqueMessageKeypair must sign the txTrack cross-chain message
import {
extractMessageId,
queryMessageSignatures,
queryMessageStatus,
} from 'nara-sdk';
// 1. Extract message ID from source tx
const messageId = await extractMessageId(connection, signature);
// 2. Query validator signatures (3-way parallel scan on S3)
const sigs = await queryMessageSignatures(messageId, 'solana');
console.log(sigs.signedCount, '/', sigs.totalValidators); // e.g. 3/3
console.log(sigs.fullySigned); // true
// 3. Check delivery on destination chain
const status = await queryMessageStatus(naraConn, messageId, 'nara');
console.log(status.delivered); // true
console.log(status.deliverySignature); // destination txSupported tokens
| Token | Solana side | Nara side | Decimals | Min bridge | Min fee | |---|---|---|---|---|---| | USDC | collateral (lock) | synthetic (mint, Token-2022) | 6 | 5 USDC | 0.5 USDC | | USDT | collateral (lock) | synthetic (mint, Token-2022) | 6 | 5 USDT | 0.5 USDT | | SOL | native (lamports) | synthetic (mint, Token-2022) | 9 | 0.1 SOL | 0.01 SOL |
Requests below the per-token minAmount are rejected client-side.
Add new tokens at runtime:
import { registerBridgeToken } from 'nara-sdk';
registerBridgeToken('XYZ', {
symbol: 'XYZ',
decimals: 6,
minAmount: 5_000_000n, // 5.0
minFee: 500_000n, // 0.5 (fee floor)
solana: { warpProgram, mode: 'collateral', mint, tokenProgram },
nara: { warpProgram, mode: 'synthetic', mint, tokenProgram },
});Fee configuration
Fee formula: fee = max(amount × 0.5%, token.minFee) — deducted from the
bridged amount on the source chain in the same transaction. Below the
crossover (100 USDC / 2 SOL) the floor dominates; above, the percentage wins.
Fee recipients are chain-specific (one per source chain):
import { setBridgeFeeRecipient, getBridgeFeeRecipient } from 'nara-sdk';
// Override fee recipient at runtime (per chain)
setBridgeFeeRecipient('solana', 'SolanaFeeRecipientPubkey...');
setBridgeFeeRecipient('nara', 'NaraFeeRecipientPubkey...');
// Read current recipient
const recipient = getBridgeFeeRecipient('solana'); // PublicKey
// Or per-call
await bridgeTransfer(conn, wallet, {
...params,
feeBps: 100, // 1% (overrides default 50 bps)
feeRecipient: customPubkey, // override recipient
skipFee: true, // or skip entirely
});Agent Registry
import {
registerAgent,
getAgentRecord,
setTwitter,
verifyTwitter,
submitTweet,
approveTweet,
} from 'nara-sdk';
// Register an agent
await registerAgent(connection, wallet, agentId, name, metadataUri);
// Twitter verification flow
await setTwitter(connection, wallet, agentId, handle);
await verifyTwitter(connection, verifierWallet, agentId);
// Tweet submission & approval
await submitTweet(connection, wallet, agentId, tweetId, tweetUrl);
await approveTweet(connection, verifierWallet, agentId, tweetId, boostCreditsDelta);Quest (Boost PoMI)
Boost PoMI is a single-track reward system. The staking channel is closed — boost credits are the sole admission ticket for submitting an answer:
- 1 credit is consumed per successful reward
submitAnswerthrows ifstakeInfo.boostCredits === 0- Credits are granted by the
stake_authority(seeadjustBoostCredits) or as part of agent-registry flows (approveTweet,verifyTwitter, etc.)
import {
getQuestInfo,
getStakeInfo,
generateProof,
submitAnswer,
} from 'nara-sdk';
const quest = await getQuestInfo(connection);
console.log(`Boost slots: ${quest.boostRemainingSlots}/${quest.boostRewardCount}`);
const stakeInfo = await getStakeInfo(connection, wallet.publicKey);
console.log(`Your boost credits: ${stakeInfo?.boostCredits ?? 0}`);
const proof = await generateProof(
answer,
quest.answerHash,
wallet.publicKey,
quest.round,
);
const { signature } = await submitAnswer(connection, wallet, proof.solana);Relevant QuestInfo fields:
boostRewardCount/boostWinnerCount/boostRewardPerWinner/boostRemainingSlots— the single Boost PoMI winner bucketround/question/answerHash/deadline/timeRemaining
Legacy staking (stake / unstake) remains callable so existing stakers can
withdraw; it no longer gates mining.
Documentation
Full API reference at nara.build/docs.
License
MIT
