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

@cdr-kit/story

v0.6.0

Published

Thin TypeScript wrappers over @story-protocol/core-sdk: register IP, mint license tokens, attach PIL terms, register derivatives, wrap IP. The agent-as-publisher surface for cdr-kit.

Readme

@cdr-kit/story

Thin TypeScript wrappers over @story-protocol/core-sdk for the Story Protocol IP creator surface: register an IP asset, attach PIL license terms, mint license tokens, register derivatives, wrap IP into WIP. The companion to @cdr-kit/agent, which adds the headline agent.publish() one-shot that collapses IP-register + PIL-attach + create-license-gated-vault + write-encrypted-data into a single call.

npm install @cdr-kit/story @story-protocol/core-sdk viem
import { createStoryClient, registerIpAsset, registerPilTerms, attachLicenseTerms, PILFlavor } from "@cdr-kit/story";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const client = await createStoryClient({ account, chainId: 1315 /* Aeneid */ });

// 1. Register an IP asset (from an existing SPG NFT collection)
const ip = await registerIpAsset(client, {
  nft: { type: "mint", spgNftContract: "0xYourSpgCollection" },
  ipMetadata: { ipMetadataURI: "ipfs://..." },
});
// → { ipId, tokenId, txHash }

// 2. Register PIL terms (commercialUse, 1 WIP per license, 5% derivative rev share)
const terms = await registerPilTerms(client, {
  flavor: PILFlavor.commercialUse({
    defaultMintingFee: 1_000_000_000_000_000_000n,
    commercialRevShare: 5,
  }),
});
// → { licenseTermsId, txHash }

// 3. Attach the PIL terms to the IP
await attachLicenseTerms(client, { ipId: ip.ipId, licenseTermsId: terms.licenseTermsId });

Why this package exists

@story-protocol/core-sdk is the canonical SDK but ships a maximalist surface with several footguns: every method returns a different shape, PIL flavor params have no decision tree, wrapIp vs approveWip ordering matters, and chaining the "register IP → attach terms → mint license tokens" flow takes 50+ lines of glue. @cdr-kit/story normalizes the return shapes, exposes the canonical 9 calls, and pairs with @cdr-kit/agent's publish() for the one-shot author flow.

Exports

| Function | Purpose | Returns | |---|---|---| | createStoryClient(opts) | Memoized SDK client bound to a wagmi/viem account | StoryClient | | registerIpAsset(client, req) | Register an existing NFT as a Story IP asset | { ipId, tokenId, txHash } | | mintAndRegisterIp(client, req) | Mint a fresh NFT in your SPG collection + register it as IP in one tx | { ipId, tokenId, txHash } | | registerPilTerms(client, { flavor }) | Register a PIL license terms entry (idempotent by content hash) | { licenseTermsId, txHash } | | attachLicenseTerms(client, { ipId, licenseTermsId, licenseTemplate? }) | Attach PIL terms to an IP — required before any license can be minted | { txHash } | | mintLicenseTokens(client, { licensorIpId, licenseTermsId, amount, receiver?, maxMintingFee? }) | Buyer mints license token(s) — the payment for commercial flavors | { licenseTokenIds: bigint[], txHash } | | registerDerivative(client, { childIpId, parentIpIds, licenseTermsIds, licenseTokenIds? }) | Register a child IP as a derivative of one or more parents | { txHash } | | wrapIp(client, { amountWei }) | Wrap native IP → WIP (ERC-20) for use as the royalty token | { txHash } | | approveWip(client, { spender, amountWei }) | Approve the RoyaltyModule (or any spender) to pull WIP from your wallet | { txHash } |

Re-exported from @story-protocol/core-sdk: PILFlavor (the 4 flavor builders), StoryClient type.

PIL flavor decision tree

| Flavor | Mints license tokens? | Allows derivatives? | Charges per mint? | Use when… | |---|---|---|---|---| | PILFlavor.nonCommercialSocialRemixing() | yes (free) | yes | no (0 fee) | open-source IP, public good, attribution-only | | PILFlavor.creativeCommonsAttribution() | yes (free) | yes | no (0 fee) | CC-BY shape — attribution required, no commercial restriction | | PILFlavor.commercialUse({ defaultMintingFee, commercialRevShare }) | yes (paid) | no | yes | paid one-off use, you don't want others remixing your work commercially | | PILFlavor.commercialRemix({ defaultMintingFee, commercialRevShare }) | yes (paid) | yes (rev flows back) | yes | paid use + derivatives allowed; revenue from derivatives flows back to you via the royalty graph |

Picking guidance. If you want the buyer to pay → commercial*. If you want derivatives → *Remix or nonCommercialSocialRemixing. If you want both → commercialRemix. If you just want to release IP openly → nonCommercialSocialRemixing or creativeCommonsAttribution.

Required params for commercial flavors. defaultMintingFee is wei-denominated WIP charged per mintLicenseTokens() call (× amount). commercialRevShare is a uint16 percentage (1–100). The fee goes to the licensor; rev share applies to all downstream derivatives.

The one-shot: agent.publish()

@cdr-kit/agent ships agent.publish({ data, spgNftContract, pilTerms }) which collapses 4 normally-separate calls into one:

import { CdrAgent } from "@cdr-kit/agent";
import { PILFlavor } from "@cdr-kit/story";

const agent = new CdrAgent({ privateKey: process.env.PRIVATE_KEY!, network: "aeneid" });

const result = await agent.publish({
  data: new TextEncoder().encode("the secret data"),
  spgNftContract: "0xYourSpgCollection",
  pilTerms: PILFlavor.commercialUse({
    defaultMintingFee: 1_000_000_000_000_000_000n,
    commercialRevShare: 5,
  }),
});
// → { ipId, tokenId, licenseTermsId, vaultUuid, vaultTxHash, ipRegisterTxHash, writeTxHash }

Behind the scenes: mintAndRegisterIpregisterPilTermsattachLicenseTermscreateVault(LicenseReadCondition, licenseTermsId)writeVaultData(encryptedSecret). The buyer flow is then: wrapIpapproveWipmintLicenseTokensaccessLicenseGated.

React hooks

@cdr-kit/react exposes the corresponding hooks (@cdr-kit/story is an optional peer dep on the React package — pay only when you publish):

  • useStoryClient(chainId?) — memoized StoryClient bound to the connected wallet
  • useRegisterIp(client){ registerIp, isLoading, error }
  • useMintLicenseToken(client){ mint, isLoading, error }
  • useAttachLicenseTerms(client){ attach, isLoading, error }
  • usePublish(){ publish, isLoading, error, result } — render-side wrapper for agent.publish()

See /docs/hooks/use-story-client etc.

Skill

The design-publish-with-story Claude Code skill walks through PIL flavor selection, the SPG NFT collection prerequisite, common failure modes (forgot to wrap IP, forgot to approve WIP, missing royalty whitelist), and when to use publish() vs the individual wrappers.

Live on Aeneid

All Story IP modules are deployed at canonical addresses on Aeneid (chain 1315) — see @cdr-kit/contracts for the live registry. Mainnet not yet deployed.