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

@31third/sdk

v0.1.0-alpha.4

Published

31Third SDK for Safe automation deployment and policy-guarded execution

Readme

@31third/sdk

SDK for deploying the StrategyExecutor framework on Safe and executing policy-guarded rebalancings. It helps you create the Safe proposal, attach on-chain policies, and run an execution wallet (AI agent or automation) that can trade only when policies pass.

Table of contents:

Concept

Important: Safe signers that approve the module deployment must be different from the StrategyExecutor execution wallet. The execution wallet is hot and should never be used to propose or sign the Safe deployment.

Create a Safe, deploy a StrategyExecutor module, and add policies that guard on-chain execution. This lets you run an AI agent (or any other trading automation) that can execute trades only if the policies pass. The Safe still owns the assets; the StrategyExecutor enforces the rules.

Setup overview:

  1. Create a Safe and fund it with assets.
  2. Choose an execution wallet (hot wallet) that will be the scheduler and registry in single-wallet mode.
  3. Have Safe signers propose and approve the deployment of the StrategyExecutor module and policies.
  4. The execution wallet (AI agent or automation) calculates rebalances and calls executeTradeNow.

Two execution modes:

  1. Single-wallet executor (recommended for most use cases): one wallet is both scheduler and registry. The AI agent signs directly and calls executeTradeNow.
  2. Chainlink Automation executor: your wallet is the scheduler, and the Chainlink registry triggers execution. Use a registry address for the chain and keep scheduler/registry distinct.

Quick links:

  • Safe app: https://app.safe.global/
  • Chainlink Automation supported networks: https://docs.chain.link/chainlink-automation/overview/supported-networks

Security notes:

  • Use a dedicated hot wallet for execution with limited funds.
  • Keep policies strict (asset universe, slippage, allocation) before enabling autonomous execution.
  • Treat the executor wallet as production infrastructure; rotate keys and monitor activity.

Registry addresses (Chainlink Automation v2.1+)

  • Ethereum mainnet (1): 0x6593c7De001fC8542bB1703532EE1E5aA0D458fD
  • Polygon mainnet (137): 0x08a8eea76D2395807Ce7D1FC942382515469cCA1
  • Base mainnet (8453): 0xf4bAb6A129164aBa9B113cB96BA4266dF49f8743
  • Arbitrum One (42161): 0x37D9dC70bfcd8BC77Ec2858836B923c560E891D1

Install

npm install @31third/sdk

Deployment note: the module deployment proposal must be created by a Safe signer, not the execution wallet.

Quick start (single-wallet executor)

Steps:

  1. Create a Safe and fund it with assets on https://app.safe.global/.
  2. Deploy StrategyExecutor with policies (single-wallet mode).
  3. Calculate a rebalancing.
  4. Execute the rebalancing.
import { proposeDeployModuleBatchTx } from '@31third/sdk';
import { JsonRpcProvider, Wallet } from 'ethers';

const provider = new JsonRpcProvider(process.env.RPC_URL!);
const safeSigner = new Wallet(process.env.SAFE_SIGNER_PK!, provider);
const safe = process.env.SAFE_ADDRESS!;
const scheduler = process.env.EXECUTOR_ADDRESS!;
const registry = process.env.EXECUTOR_ADDRESS!;
const feedRegistry = process.env.FEED_REGISTRY!;

await proposeDeployModuleBatchTx({
  automationId: 'uuid-or-id',
  safeAddress: safe,
  signer: safeSigner, // Safe signer, not the executor
  chainId: 8453,
  scheduler, // scheduler == registry for single-wallet mode
  registry,
  batchTrade: '0xBatchTrade',
  // Hint: include only the policies you need.
  policyConfig: {
    cooldown: 3600,
    assetUniverse: {
      assetUniverseTokens: ['0xToken1', '0xToken2'],
    },
    slippage: {
      feedRegistry,
      maxSlippageBps: 50,
    },
    staticAllocation: {
      feedRegistry,
      targetTokens: ['0xToken1', '0xToken2'],
      targetBps: [5000, 5000],
      triggerThresholdBps: 50,
      toleranceThresholdBps: 50,
    },
  },
});
import { calculateRebalancing } from '@31third/sdk';

const rebalancing = await calculateRebalancing({
  apiBaseUrl: 'https://api.31third.com/1.3',
  apiKey: process.env.API_KEY!,
  chainId: 8453,
  payload: {
    wallet: process.env.SAFE_ADDRESS,
    signer: process.env.SAFE_ADDRESS,
    baseEntries: [],
    targetEntries: [],
    maxSlippage: 0.01,
    maxPriceImpact: 0.05,
    minTradeValue: 0.01,
    skipBalanceValidation: false,
  },
});
import { executeRebalancing } from '@31third/sdk';
import { JsonRpcProvider, Wallet } from 'ethers';

const executor = new Wallet(process.env.EXECUTOR_PK!, new JsonRpcProvider(process.env.RPC_URL!));
const tx = await executeRebalancing({
  signer: executor,
  strategyExecutor: process.env.STRATEGY_EXECUTOR!,
  rebalancing,
});
await tx.wait();

Rebalancing payload parameters (SDK-relevant)

These are the fields you can set in calculateRebalancing({ payload }):

  • wallet: Safe address the rebalancing is calculated for.
  • signer: address that will sign/execute on-chain.
  • simulationTxOrigin: optional override for Tenderly simulation (if needed).
  • baseEntries: list of { tokenAddress, amount } for the assets to sell (amount in wei).
  • targetEntries: list of { tokenAddress, allocation } (allocation as fraction, e.g. 0.2 = 20%).
  • maxDeviationFromTarget: max deviation from target allocation (default 0.005).
  • maxSlippage: max slippage for calculated trades (default 0.005).
  • maxPriceImpact: max price impact for the basket trade (default 0.01).
  • minTradeValue: minimum trade value in USD (default 1).
  • batchTrade: enable batch trade (default true).
  • revertOnError: revert whole batch if one trade fails (default true).
  • skipBalanceValidation: skip balance checks (default false).
  • failOnMissingPricePair: fail if any required price pair is missing (default true).
  • async: calculate asynchronously (default false).

Token address note: use ETH or 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee for native ETH.

Chain overrides

You can override chain constants by passing chainOverrides to deployment helpers:

import { proposeDeployModuleBatchTx } from '@31third/sdk';

await proposeDeployModuleBatchTx({
  /* ... */
  chainOverrides: {
    safeTxServiceUrls: {
      8453: 'https://safe-transaction-base.safe.global',
    },
    multisendAddresses: {
      8453: '0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526',
    },
    create2FactoryAddresses: {
      8453: '0xce0042B868300000d44A59004Da54A005ffdcf9f',
    },
    safeAppPrefixes: {
      8453: 'base',
    },
  },
});

Fields:

  • safeTxServiceUrls: Safe Transaction Service API per chain id.
  • multisendAddresses: MultiSend contract address per chain id.
  • create2FactoryAddresses: CREATE2 factory per chain id.
  • safeAppPrefixes: Safe app URL prefix per chain id.

Policy reference

This SDK can deploy these policies and attach them to the StrategyExecutor. All policies run on-chain before execution and can veto trades.

AssetUniversePolicy

Purpose: restrict trades to a fixed list of allowed tokens.

How it works:

  • On every trade, checks that trade.from and trade.to are in the allowed token set.
  • Any token not explicitly allowed fails the policy.

Owner controls:

  • allowToken(token) adds a token to the universe.
  • disallowToken(token) removes a token from the universe.

Failure modes (custom errors):

  • AssetUniverseFromTokenNotAllowed(token)
  • AssetUniverseToTokenNotAllowed(token)

Use cases:

  • Prevent AI or external executors from trading into unknown assets.
  • Enforce allowlists per portfolio or strategy.

StaticAllocationPolicy

Purpose: enforce a target portfolio allocation (in bps) and only allow rebalances when a deviation threshold is met.

Inputs:

  • targetTokens and targetBps (must sum to 10_000).
  • assetUniverse (optional, if provided it defines the full supported token set).
  • feedRegistry for price feeds.
  • triggerThresholdBps: minimum deviation from target that triggers a rebalance.
  • toleranceThresholdBps: maximum deviation allowed after executing the proposed trades.

How it works:

  1. Loads current balances for all supported tokens.
  2. Computes current USD weights via feed registry.
  3. If no token deviates by at least triggerThresholdBps, it fails with StaticAllocationNoRebalanceTrigger.
  4. Simulates the proposed trades using minToReceiveBeforeFees and updates balances.
  5. Computes predicted USD weights. If any token is outside toleranceThresholdBps, it fails.

Failure modes (custom errors):

  • StaticAllocationFeedMissing(token)
  • StaticAllocationZeroPortfolioValue()
  • StaticAllocationNoRebalanceTrigger()
  • StaticAllocationTokenNotSupported(token)
  • StaticAllocationInsufficientBalance(token, required, available)
  • StaticAllocationZeroPredictedValue()
  • StaticAllocationOutsideTolerance()

Notes:

  • Requires all tokens to have price feeds in the registry.
  • targetTokens must be in the asset universe when assetUniverse is provided.
  • Use assetUniverse to include on-ramp tokens (e.g., USDC/USDT) even if the target allocation is only WBTC/WETH; the universe defines which tokens the strategy can trade through.

SlippagePolicy

Purpose: ensure minToReceiveBeforeFees isn’t below a maximum slippage bound.

Inputs:

  • feedRegistry for price feeds.
  • maxSlippageBps (<= 10_000).

How it works:

  • For each trade, gets USD price feeds for from and to.
  • Computes expected output amount and enforces minToReceiveBeforeFees >= expected * (1 - maxSlippageBps/10_000).

Failure modes (custom errors):

  • SlippageFeedMissing(tradeIndex, token)
  • SlippageMinToReceiveTooLow(tradeIndex, minToReceive, minAllowed)

Notes:

  • Requires feeds for both from and to tokens.
  • Uses token decimals and feed decimals to normalize expected output.

AI integration guide (structured)

Use this when implementing an AI agent that proposes and executes trades:

Inputs:

  • SAFE_ADDRESS: Safe that holds assets.
  • STRATEGY_EXECUTOR: Deployed module address.
  • RPC_URL: Chain RPC.
  • API_KEY: 31Third API key for rebalancing.
  • CHAIN_ID: 1 / 137 / 8453 / 42161.
  • EXECUTOR_PK: Private key of the executor wallet (scheduler==registry).

Steps:

  1. Fetch current Safe token balances and use those amounts for baseEntries in calculateRebalancing. It is not necessary to include all balances; include only the tokens/amounts you want to rebalance. All selected tokens must be in the defined asset universe.
  2. Call calculateRebalancing with rebalancing/wallet payload.
  3. Decode txData into trades/config.
  4. Call checkPoliciesVerbose on StrategyExecutor.
  5. If ok, call executeTradeNow with approvals and encoded trade data.
  6. Record tx hash and any policy failure reasons for auditing.

Expected outputs:

  • Rebalancing response (txData + requiredAllowances).
  • Execution tx hash (or a policy failure reason).

Current status

  • Only Base is supported right now.
  • Default Base feed registry: 0x1DB380699aEBCEdf252C8a91E20867D8A09c1dcd
  • Supported Base tokens:
    • WETH 0x4200000000000000000000000000000000000006
    • WBTC 0x0555E30da8f98308EdB960aa94C0Db47230d2B9c
    • USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
    • EURC 0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42
    • cbBTC 0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf
    • cbETH 0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22
    • AAVE 0x54330d28ca3357F294334BDC454a032e7f353416
    • LINK 0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196
    • USDe 0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34
    • sUSDe 0x2113938A47a0F084bB494c289c8A5c0c98D8Ca2d
    • MORPHO 0xBaA644bCfe0E546D67f58E5E8EC529618B8B8350