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

@ab-org/predicate-market-sdk

v2.0.0

Published

Prediction-market specific helpers built on top of `@ab-org/sdk-core`.

Downloads

791

Readme

@ab-org/predicate-market-sdk

Prediction-market specific helpers built on top of @ab-org/sdk-core.

Key features

  • Built-in wallet connection modal (social via OIDC relay + WalletAccount, injected wallets via WalletConnectorno FedCM in SignInModal for Google/X)
  • Connection state via createWalletConnectController() and createAccountController() from @ab-org/sdk-core
  • Unified smart-wallet session metadata with capability policy support
  • High-level execution helpers via createWalletExecutionController()
  • Deposit / withdraw controllers with USDT-first defaults
  • Dynamic token & chain lists via MarketDataProvider (backend-driven, mock included)
  • Quote / slippage API — fetch real-time pricing before confirming deposit or withdraw
  • Predicate-market policy adapter for deposit / withdraw / trade flows

Installation

npm install @ab-org/sdk-core @ab-org/predicate-market-sdk

Quick start

import {
  WalletConnector,
  MetaMaskProvider,
  createAccountController,
  createWalletConnectController,
  createWalletExecutionController,
} from "@ab-org/sdk-core";
import {
  createDepositController,
  createWithdrawController,
  createMarketDataProvider,
  createPredicateMarketPolicyAdapter,
  type CustodyAdapter,
} from "@ab-org/predicate-market-sdk";

declare const custodyAdapter: CustodyAdapter;

const connector = new WalletConnector([
  new MetaMaskProvider(),
  // new CubistSocialProvider(cubistClient)
]);

const walletConnect = createWalletConnectController({ connector, defaultAdapterId: "metamask" });
const account = createAccountController();
const execution = createWalletExecutionController();

// Use the mock provider until real backend endpoints are ready
const marketData = createMarketDataProvider();

const deposit = createDepositController(custodyAdapter, marketData);
const withdraw = createWithdrawController(custodyAdapter, marketData);
const policy = createPredicateMarketPolicyAdapter({
  appId: "prediction-market",
  origin: window.location.origin,
});

Connect wallet

<button onClick={() => (walletConnect.isConnected ? walletConnect.disconnect() : walletConnect.openModal())}>
  {walletConnect.isConnected ? "Disconnect" : "Connect Wallet"}
</button>

Configure SignInModal

The SDK ships with bundled auth config (Google client id, Twitter client id, CubeSigner env/org) so you can call initSDK with only signIn. Override via env (NEXT_PUBLIC_*) or by passing options to initSDK.

Google / X in SignInModal use the SDK's bundled OIDC relay auth: a popup opens your NEXT_PUBLIC_RELAY_ORIGIN routes /relay/google and /relay/x, then the SDK's built-in WalletAccount bridge turns the returned OIDC token into the session provider.

import { initSDK, SignInModal } from "@ab-org/predicate-market-sdk";

initSDK({
  // Optional: only used by other Twitter flows; SignInModal X login uses /relay/x on RELAY_ORIGIN
  twitterRedirectUri: typeof window !== "undefined" ? `${window.location.origin}/auth/twitter-callback` : undefined,
  signIn: {
    socialProviders: [
      { id: "google", label: "Continue with Google" },
      { id: "x", label: "Continue with X" },
    ],
    wallets: [
      { id: "metamask", name: "MetaMask" },
      { id: "okx", name: "OKX Wallet" },
      { id: "phantom", name: "Phantom" },
    ],
    initialVisibleCount: 4,
  },
});

<SignInModal />;

Rules:

  • NEXT_PUBLIC_RELAY_ORIGIN (or RELAY_ORIGIN) must match where you serve /relay/google and /relay/x

Funding chain & funding token (withdraw / balance)

  • getChainInfo(chainId?) — resolves RPC, explorer metadata, native currency fields, and defaultFundingTokenAddress (per-chain default ERC-20 for the funding leg). If chainId is omitted or empty, defaults to 3131 (Tenderly BSC vnet). Built-in ids are 3131 and 56 (BSC mainnet); unknown ids throw.
  • getFundingTokenAddress(chainId?) — same optional chainId as getChainInfo. If NEXT_PUBLIC_FUNDING_TOKEN_ADDRESS / FUNDING_TOKEN_ADDRESS or legacy defaultFundingTokenAddress`**.
  • DEFAULT_FUNDING_TOKEN_ADDRESS — shorthand for getChainInfo().defaultFundingTokenAddress (default funding chain 3131).
  • fetchFundingTokenBalance(address, { chainId, rpcUrl?, tokenAddress?, decimals?, displaySymbol? }) — uses getChainInfo(chainId) for RPC when rpcUrl is omitted, getFundingTokenAddress(chainId) when tokenAddress is omitted, and decimals default chain.nativeCurrencyDecimals when omitted (override if your funding token uses different decimals).
  • createFundingWithdrawExecutor({ chainId?, rpcUrl?, tokenAddress?, … }) — uses the same chainId for getChainInfo, default token address (getFundingTokenAddress(chainId)), and order payload (default 3131 when chainId omitted).

Type note: EvmChainInfo includes defaultFundingTokenAddress. If you construct chain objects manually in TypeScript, add that field or use getChainInfo instead of literals.

  • socialProviders: undefined uses built-in defaults (google, x)
  • socialProviders: [] hides all social buttons
  • known social ids like google and x automatically reuse built-in icons unless you override icon
  • wallets: undefined uses the built-in wallet registry
  • wallets: [] hides all wallet buttons
  • known wallet ids automatically reuse built-in metadata like installUrl and detected installed state unless you override them
  • component props still override initSDK({ signIn }) on a per-modal basis

The package still exports signInWithGoogle (Google Identity Services, optional FedCM) for custom integrations; the built-in SignInModal does not use it for Google.

Address & balance

if (!account.isConnected) return <p>Please connect wallet</p>;
return (
  <div>
    Address: {account.address?.slice(0, 6)}...{account.address?.slice(-4)}
    <br />
    Balance: {account.balance?.formatted} {account.balance?.symbol}
  </div>
);

Market data — token / chain lists & quotes

Both deposit and withdraw controllers expose market-data helpers that delegate to the injected MarketDataProvider:

// 1. Fetch available tokens
const tokens = await deposit.fetchTokens();
// → [{ symbol: "USDT", name: "Tether", decimals: 6, … }, …]

// 2. After the user picks a token, fetch the chains it supports
const chains = await deposit.fetchChains("USDT");
// → [{ id: "ETH", name: "Ethereum", estimatedTime: "~15 min" }, …]

// 3. After user picks token + chain, fetch the deposit address (backend-provided)
const { address, minimumDeposit } = await deposit.fetchDepositAddress("USDT", "ETH");
// QR code is generated client-side from the address — no backend QR needed

// 4. After user enters amount, fetch a quote
const quote = await deposit.fetchQuote("USDT", "ETH", "100");
// → { quoteId, estimatedAmount, slippage, fee, feeToken, exchangeRate, expiresAt }

The same token / chain / quote API is available on the withdraw controller:

const tokens = await withdraw.fetchTokens();
const chains = await withdraw.fetchChains("USDT");
const quote  = await withdraw.fetchQuote("USDT", "ETH", "200");

Implementing a real MarketDataProvider

Replace createMarketDataProvider() with your own implementation:

import type { MarketDataProvider } from "@ab-org/predicate-market-sdk";

const realMarketData: MarketDataProvider = {
  async getSupportedTokens(direction) {
    const res = await fetch(`/api/market/tokens?direction=${direction}`);
    return res.json();
  },
  async getSupportedChains(token, direction) {
    const res = await fetch(`/api/market/chains?token=${token}&direction=${direction}`);
    return res.json();
  },
  async getQuote(request) {
    const res = await fetch("/api/market/quote", {
      method: "POST",
      body: JSON.stringify(request),
    });
    return res.json();
  },
  async getDepositAddress(token, chain) {
    const res = await fetch(`/api/market/deposit-address?token=${token}&chain=${chain}`);
    return res.json();
  },
};

Deposit modal

<button
  onClick={() =>
    deposit.open({
      preferredToken: "USDC",
      preferredChain: "ETH",
      onStatusChange: (status) => console.log("deposit status", status),
    })
  }
>
  Deposit
</button>

Smart-wallet session model

Social login and injected wallets now converge on the same WalletSession shape.

const account = createAccountController();

console.log(account.session?.walletType); // "injected" | "smart"
console.log(account.chainContext?.walletChainDescriptor.label);
console.log(account.capabilities); // provider capability matrix
console.log(account.capabilityPolicy); // optional scoped session policy

Trading helpers

import { encodeFunctionData, erc20Abi } from "viem";

async function approveSpender(spender: string, value: bigint) {
  if (!account.address) return;

  const callData = encodeFunctionData({
    abi: erc20Abi,
    functionName: "approve",
    args: [spender, value],
  });

  await execution.sendTransaction({
    from: account.address,
    to: tokenAddress,
    data: callData,
  });
}

Use execution.signTransaction(), execution.signMessage(), and execution.signTypedData() instead of building raw EIP-1193 requests in app code.

Capability policies

const depositPolicy = policy.deposit("USDC", "ETH", "1000000");
const withdrawPolicy = policy.withdraw("USD1", "AB_CORE", "500000");
const tradePolicy = policy.trade("ETH", ["eth_sendTransaction", "eth_signTypedData_v4"]);

These policies can be passed into your smart-wallet authorization flow so app actions stay scoped by chain, method, token, and amount.

Withdraw modal

<button
  onClick={() =>
    withdraw.open({
      defaultToken: "USDT",
      defaultChain: "AB_CORE",
      targetAddress: "0x...",
      defaultAmount: "100",
      onStatusChange: (status) => console.log("withdraw", status),
    })
  }
>
  Withdraw
</button>