npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sixpenceai/sdk

v0.1.0

Published

Framework-agnostic TypeScript SDK for Sixpence lending, vaults, swaps, subgraphs, and partner integrations.

Readme

Sixpence SDK

Framework-agnostic TypeScript SDK for partner applications that need to read Sixpence markets and subgraphs or execute lending, vault, and swap operations.

The SDK is built on viem. It does not require Next.js, wagmi, RainbowKit, or Sixpence UI components. React Query bindings, low-level adapters, experimental routers, stock metadata, and server-only helpers are isolated in separate entrypoints.

Documentation:

Install

npm install @sixpenceai/sdk viem

React applications can optionally install @tanstack/react-query and import from @sixpenceai/sdk/react:

npm install @sixpenceai/sdk viem react @tanstack/react-query

For an unreleased development snapshot, pin an exact reviewed Git commit rather than the moving dev branch:

npm install git+https://github.com/0xJomo/sixpence-sdk.git#<commit-sha> viem

The supported runtime is Node.js 20 or newer. Browser consumers must provide a browser-compatible viem transport.

| Peer | Supported versions | | --- | --- | | viem | >=2.22.0 <3 | | react | >=18 <20 (optional) | | @tanstack/react-query | >=5 <6 (optional) |

Package entrypoints

| Import | Purpose | Runtime boundary | | --- | --- | --- | | @sixpenceai/sdk | Stable client, configuration, types, errors, lending/vault/swap APIs | Browser and Node.js | | @sixpenceai/sdk/react | Optional TanStack React Query hooks | React applications | | @sixpenceai/sdk/server | Liquidation, risk-monitor, points, and pagination helpers | Server only | | @sixpenceai/sdk/advanced | Low-level transports and service constructors | Custom integrations | | @sixpenceai/sdk/experimental | Pre-stable Uniswap V2/V3 route builders | API may change before a minor release | | @sixpenceai/sdk/stocks | Static stock-token metadata | Browser and Node.js |

Only import the entrypoints you use. The default browser entrypoint does not bundle private keys, cron state, databases, storage clients, or notification adapters.

Create a client

import { createPublicClient, createWalletClient, custom, http } from "viem";
import { bsc } from "viem/chains";
import { createSixpenceClient } from "@sixpenceai/sdk";

const publicClient = createPublicClient({
  chain: bsc,
  transport: http(process.env.BSC_RPC_URL),
});

const walletClient = createWalletClient({
  chain: bsc,
  transport: custom(window.ethereum),
});

const [account] = await walletClient.getAddresses();

const sixpence = createSixpenceClient({
  marketId: "usstocks-bsc-v3",
  deployment: "production",
  publicClient,
  walletClient,
  account,
});

Deployment selection is explicit. Use deployment: "preview" for the dev BSC pool; the SDK never infers a deployment from NODE_ENV or Vercel variables.

The built-in registry contains only deployments whose configured subgraphs pass the release smoke test. Ethereum mainnet is intentionally not advertised while the source application's Goldsky endpoint returns 404 Subgraph not found. Partners with a restored endpoint can pass an explicit market and vaultDeployment override without waiting for a package release. A custom lending-only market may omit vault configuration; client.vaults is then undefined. Set vaultDeployment: false to opt out explicitly on any chain.

Read markets and accounts

const reserves = await sixpence.markets.listReserves({ limit: 100 });

const positions = await sixpence.accounts.listPositions(account, { limit: 100 });
const transactions = await sixpence.accounts.listTransactions(account, { limit: 50 });

Paginated GraphQL list methods return Page<T> with a cursor and an explicit truncated flag. Token amounts use { raw: bigint, decimals: number }; rates, ratios, prices, and vault values retain their documented domain-specific scale. Convert them only at the presentation boundary.

Each SixpenceClient is scoped to exactly one configured market and Pool. Shared GraphQL endpoints may index several Pools, but market and account services always add the selected Pool filter before pagination. Applications that show an account across several markets must create one client per market, query them independently, and merge the results by market-aware identifiers. Never query one endpoint and assume it represents every market on the chain.

On-chain oracle reads return both the raw value and baseCurrencyUnit:

const price = await sixpence.lending.getAssetPrice(asset);
// price.raw / price.baseCurrencyUnit, with on-chain provenance

The SDK never assumes that every deployment uses eight oracle decimals.

For transaction-time contract truth, read the Aave UI providers at one pinned block instead of treating indexed aggregates as authoritative:

const reserves = await sixpence.lending.getReservesData();
const user = await sixpence.lending.getUserReservesData(account, {
  blockNumber: reserves.provenance.blockNumber,
});
const balances = await sixpence.lending.getWalletBalances(
  account,
  reserves.reserves.map((reserve) => reserve.underlyingAsset),
  { blockNumber: reserves.provenance.blockNumber },
);

All RAY/BPS values and balances remain bigint. The service preserves all 54 reserve tuple fields and does not invent fields absent from the on-chain ABI.

Simulate and execute lending operations

Every contract operation follows the same lifecycle:

const operation = {
  kind: "supply" as const,
  asset: "0x..." as const,
  amount: 1_000_000n,
};

const request = sixpence.lending.prepare(operation);
const simulation = await sixpence.lending.simulate(operation);
const { hash, receipt } = await sixpence.lending.execute(operation);

Supported lending operations include:

  • ERC20 approval
  • ERC20 and native supply
  • ERC20 and native borrow
  • credit delegation
  • ERC20 and native withdraw
  • ERC20 and native repay
  • testnet faucet minting on deployments that declare a faucet
  • capability-gated swap-and-repay through lending.swapAndRepay

Reverted receipts throw TransactionError; they are never returned as a successful result.

Swap-and-repay deployments are explicit because adapter, router, swapper, and wrapped-native addresses are chain-specific. The SDK requires a positive minimum debt-asset output and defaults ERC20 approvals to the exact amount.

Vaults

GraphQL and on-chain vault methods share one namespace:

if (!sixpence.vaults) throw new Error("This deployment has no vault capability");

const vaults = await sixpence.vaults.list({ limit: 50 });
const metadata = await sixpence.vaults.getMetadata(vaultAddress);
const allowance = await sixpence.vaults.getAllowance(
  metadata.asset,
  account,
  vaultAddress,
);
if (allowance < amount) {
  await sixpence.vaults.execute({
    kind: "approve",
    token: metadata.asset,
    vault: vaultAddress,
    amount,
  });
}
await sixpence.vaults.simulate({
  kind: "deposit",
  vault: vaultAddress,
  assets: amount,
  receiver: account,
});
await sixpence.vaults.execute({
  kind: "deposit",
  vault: vaultAddress,
  assets: amount,
  receiver: account,
});

Token deposits and redemptions require a non-zero minimum output. The SDK does not inherit the frontend's historical minAmountOut = 0 behavior. A depositToken caller must obtain a token-aware expected share amount from its deployment's quote source and apply minimumAfterSlippage; ERC-4626 previewDeposit only quotes the vault's base asset and must not be reused for an arbitrary token route. Lend Yield deployments do not expose USD global stats unless the subgraph can prove asset decimals and USD prices; the SDK throws SchemaCapabilityError instead of silently assuming six decimals or a $1 price.

Swaps

DE1 quoting must be configured when the client is created. quoteEndpoint should be an application-owned proxy that protects the provider credential, and validateSwapQuoteEconomics must obtain fresh, independent reference prices:

import {
  createQuoteEconomicsValidator,
  createSixpenceClient,
} from "@sixpenceai/sdk";

const swapClient = createSixpenceClient({
  marketId: "usstocks-bsc-v3",
  deployment: "production",
  publicClient,
  walletClient,
  account,
  quoteEndpoint: new URL("/api/stocks/swap", window.location.origin).toString(),
  validateSwapQuoteEconomics: createQuoteEconomicsValidator({
    resolveReferences: getFreshReferencePrices,
    maxDeviationBps: 500,
  }),
});

getFreshReferencePrices is application-owned and must return independently validated prices, token decimals, and a bounded update timestamp. See the type-checked swap example for a fail-closed subgraph-oracle implementation that re-queries on every validation phase and rejects references older than five minutes. Production consumers should choose a maximum age that matches their assets and oracle update policy.

const quote = await swapClient.swaps.quoteDe1({
  sellToken,
  buyToken,
  sellAmount,
  slippageBps: 50,
});

await swapClient.swaps.simulate(quote);
await swapClient.swaps.execute(quote, {
  approval: "exact",
  resetAllowance: "auto",
  refreshQuote: () => swapClient.swaps.quoteDe1({
    sellToken,
    buyToken,
    sellAmount,
    slippageBps: 50,
  }),
});

Quote intent, chain, amounts, calldata recipient, native value, and expiry are validated before execution. Transaction and allowance targets are independently allowlisted; the audited DE1 router is built in when quoteEndpoint is set, while custom providers must supply their own target lists and calldata validator. DE1 also requires an application-owned, fresh reference-price validator. The SDK enforces a 20% maximum provider-reported price impact by default and requires a fresh quote after an approval confirms. Unlimited approvals require a separate explicit allowlist.

Referral signatures

import { createReferralClient } from "@sixpenceai/sdk";

const referrals = createReferralClient({
  apiBaseUrl: "https://www.sixpence.xyz",
  signer: {
    signMessage: ({ message }) => walletClient.signMessage({ account, message }),
  },
});

await referrals.applyCode({ address: account, code: "PARTNER" });

The SDK requests a nonce, verifies every challenge claim, expiry, and canonical message, then signs and submits the one-time authorization. It never signs an arbitrary message supplied by the endpoint.

React Query

import { useSixpenceAccountPositions } from "@sixpenceai/sdk/react";

const positions = useSixpenceAccountPositions(sixpence, account);

Cache keys include the SDK client identity, deployment endpoint, chain/market, address, and pagination inputs to prevent cross-chain cache contamination. List hooks return Page<T>, including nextCursor; pagination state is never discarded by the React adapter.

The React entrypoint also exports hooks for markets, account transactions, reserve history, vault lists, and vault balances. See the API reference for the complete list.

Analytics and activity

Protocol snapshots and global activity feeds are exposed with an explicit endpoint scope and bounded time window:

const window = {
  fromTimestamp: BigInt(Math.floor(Date.now() / 1000) - 30 * 86_400),
  toTimestamp: BigInt(Math.floor(Date.now() / 1000)),
};
const daily = await sixpence.analytics.listLendingDailySnapshots({ window });
const activity = await sixpence.analytics.listLendingActivity({ window });

The scope is deliberately endpoint-wide because the deployed protocol snapshot entity uses a shared protocol id. Activity rows retain each reserve's Pool, so consumers can derive market-scoped views without mislabeling endpoint totals.

Stock token addresses on BSC, Sepolia, and Robinhood are likewise discovered from markets.listReserves() for the selected Pool. The static /stocks metadata entrypoint does not guess addresses that the source registry does not contain.

Advanced entrypoints

  • @sixpenceai/sdk/advanced: low-level GraphQL transports and service factories
  • @sixpenceai/sdk/experimental: Uniswap route builders with a pre-stable API
  • @sixpenceai/sdk/stocks: stock-token metadata only
  • @sixpenceai/sdk/server: node-safe discovery and pagination helpers

Server helpers

import {
  collectAllPages,
  createLiquidationDiscoveryService,
  createLiquidationExecutionService,
  createLiquidationPlanner,
  createPointsIndexerReader,
  createRiskMonitorReader,
} from "@sixpenceai/sdk/server";

The server entrypoint contains stateless discovery, liquidation planning and execution, risk-monitor reads, points-indexer reads, and pagination primitives. It does not bundle a private key, database lock, cron route, storage client, or Telegram adapter. Those remain application-owned dependencies. Liquidation planning requires an injected binding for every allowed Pool and verifies Pool.ADDRESSES_PROVIDER() plus the provider's data-provider and oracle addresses on-chain before accepting a candidate.

Errors

SDK-defined configuration, transport, validation, simulation, and transaction boundaries use structured error classes:

  • UnsupportedChainError
  • UnsupportedCapabilityError
  • ConfigurationError
  • HttpError
  • TimeoutError
  • RpcError
  • OnchainReadError
  • GraphQLExecutionError
  • GraphQLPartialDataError
  • SchemaCapabilityError
  • SimulationError
  • TransactionError
  • DataValidationError
  • ValidationError

Subgraph outages are never converted into empty arrays. Unknown chains never fall back to BSC or another configured network.

Caller-controlled cancellation reasons and JavaScript runtime failures can still propagate as native errors. Consumers should branch on SdkError.code when available and retain a final unknown-error path.

Development

npm install
npm run check
npm run smoke:package
npm run smoke:graphql

npm run check enforces type checking, coverage thresholds, tests, and both module builds. npm run smoke:package installs the packed tarball into an isolated ESM/CommonJS/TypeScript consumer. npm run smoke:graphql verifies the live advertised deployment registry.

See the release procedure for the complete publication gate and the capability matrix for the source-to-SDK migration boundary.