Agent skill

Cashu TS Migration

by shopstr-eng in shopstr-eng/shopstr

Migrate a TypeScript/JavaScript codebase from @cashu/cashu-ts v2 to v4.

GPL-3.0Auto-check passedBackend & APIs

Install Cashu TS Migration

skills CLI
$ npx skills add shopstr-eng/shopstr --skill cashu-ts-migration -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install shopstr-eng/shopstr cashu-ts-migration --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/shopstr-eng/shopstr.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/cashu-ts-migration .claude/skills/cashu-ts-migration && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
cashu-ts-migration
GitHub stars
103
Token cost
~3.1k tokens
SKILL.md length
983 words
Files
1
Skills in repo
1
Repo updated
First seen
Licence
GPL-3.0

At a glance

Migrate a TypeScript/JavaScript codebase from @cashu/cashu-ts v2 to v4.

  • Works in 10 steps: Class rename: import aliasing keeps… → Drop removed constructor options → Method renames (BOLT11 helpers) → …
  • Bumping cashu-ts past 2.x to unlock v3+ Wallet ergonomics (rate-limit aware retries
  • SKILL.md covers Pre-flight (do once), Step 1 — Class rename: import…, Step 2 — Drop removed… and Step 3 — Method renames…, plus 9 more sections
  • Calls git, npx and npm

What it does

Cashu TS Migration is an agent skill from shopstr-eng/shopstr. Migrate a TypeScript/JavaScript codebase from @cashu/cashu-ts v2 to v4. Use when bumping cashu-ts past 2.x to unlock v3+ Wallet ergonomics (rate-limit aware retries, Amount boundary type, KeyChain, BOLT-method-typed quote helpers). Covers import renames, deprecated method renames, removed constructor options, the Amount boundary, the new getDecodedToken(token, keysetIds) signature, runtime loadMint() requirement, and Jest mock updates.

Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering Rate limiting. It works with Jest, JavaScript and TypeScript. The repository describes itself as: A global, permissionless Nostr marketplace for Bitcoin commerce. The licence is GPL-3.0.

When your agent uses it

  • Bumping cashu-ts past 2.x to unlock v3+ Wallet ergonomics (rate-limit aware retries
  • Amount boundary type
  • BOLT-method-typed quote helpers)

Example prompts

  • “/cashu-ts-migration”

Requirements

  • Node.js

Workflow steps

10 steps, taken from the step headings in SKILL.md.

  1. Class rename: import aliasing keeps blast radius small
  2. Drop removed constructor options
  3. Method renames (BOLT11 helpers)
  4. Keysets moved into KeyChain
  5. The Amount boundary (CRITICAL)
  6. getDecodedToken requires a second argument
  7. MintQuoteState lives on the bolt11-specific response
  8. Add await wallet.loadMint() at every construction site
  9. Update Jest mocks
  10. Validation order

What it can do on your machine

Read from SKILL.md and the folder at commit fcfc0bd. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • git
    • npx
    • npm

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use git, npx and npm, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Cashu TS Migration loads about 3.1k tokens when it runs. Until then it costs about 118 tokens; SKILL.md has 983 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~118
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from shopstr-eng/shopstr at commit fcfc0bd, republished under its GPL-3.0 licence (© shopstr-eng). 983 words, ~3,090 tokens.

Download SKILL.mdSave it as .claude/skills/cashu-ts-migration/SKILL.md (or your agent's skills folder).
name
cashu-ts-migration
description
Migrate a TypeScript/JavaScript codebase from `@cashu/cashu-ts` v2 to v4. Use when bumping cashu-ts past 2.x to unlock v3+ Wallet ergonomics (rate-limit aware retries, `Amount` boundary type, `KeyChain`, BOLT-method-typed quote helpers). Covers import renames, deprecated method renames, removed constructor options, the `Amount` boundary, the new `getDecodedToken(token, keysetIds)` signature, runtime `loadMint()` requirement, and Jest mock updates.

@cashu/cashu-ts v2 → v4 Migration

cashu-ts v3 was a hard breaking change: classes were renamed (CashuMint/CashuWallet → Mint/Wallet), keysets moved into a KeyChain, all amounts became an opaque Amount class, mint/melt quote helpers were split per-payment-method (Bolt11/Bolt12), and wallets must be explicitly initialized with loadMint(). v4 layered additional API hardening on top. The authoritative migration guide ships in the package itself: read node_modules/@cashu/cashu-ts/migration-4.0.0.SKILL.md before starting.

Pre-flight (do once)

  1. Read node_modules/@cashu/cashu-ts/migration-4.0.0.SKILL.md end-to-end.
  2. Pin the new version in package.json, run npm install.
  3. Independent prerequisite — @noble/hashes ≥ v2: v2 dropped implicit .js extension resolution from ESM subpath imports. Sed-rename every from "@noble/hashes/utils" to from "@noble/hashes/utils.js" (and any other subpath you import). Skip and you get cryptic Next.js/Vite/Webpack module resolution errors that look like a cashu-ts problem.
  4. @cashu/crypto/modules/common was dropped: hashToCurve is re-exported from @cashu/cashu-ts itself. Replace import { hashToCurve } from "@cashu/crypto/modules/common" with import { hashToCurve } from "@cashu/cashu-ts".

Step 1 — Class rename: import aliasing keeps blast radius small

CashuMint and CashuWallet no longer exist. Use the new Mint / Wallet exports. Aliasing in the import line preserves every downstream call site:

ts
// before
import { CashuMint, CashuWallet } from "@cashu/cashu-ts";

// after
import { Mint as CashuMint, Wallet as CashuWallet } from "@cashu/cashu-ts";

This pattern lets new CashuMint(...) / new CashuWallet(...) keep working everywhere. Apply across all production AND test files.

Step 2 — Drop removed constructor options

The Wallet constructor no longer accepts { keys } (or other preload options). Construct the wallet with just the mint, then call loadMint():

ts
// before
const wallet = new CashuWallet(mint, { keys: storedKeys });

// after
const wallet = new CashuWallet(mint);
await wallet.loadMint(); // hydrates mint info, keysets, keys

Step 3 — Method renames (BOLT11 helpers)

All quote-related wallet methods were split per payment method. For Lightning (the common case), append Bolt11. A bulk sed pass works because the names are unambiguous within wallet.X(:

v2/early-v3v3+ / v4
wallet.createMintQuote(wallet.createMintQuoteBolt11(
wallet.checkMintQuote(wallet.checkMintQuoteBolt11(
wallet.mintProofs(wallet.mintProofsBolt11(
wallet.createMeltQuote(wallet.createMeltQuoteBolt11(
wallet.meltProofs(wallet.meltProofsBolt11(
bash
for f in $(git ls-files '*.ts' '*.tsx'); do
  sed -i \
    -e 's/wallet\.createMintQuote(/wallet.createMintQuoteBolt11(/g' \
    -e 's/wallet\.checkMintQuote(/wallet.checkMintQuoteBolt11(/g' \
    -e 's/wallet\.mintProofs(/wallet.mintProofsBolt11(/g' \
    -e 's/wallet\.createMeltQuote(/wallet.createMeltQuoteBolt11(/g' \
    -e 's/wallet\.meltProofs(/wallet.meltProofsBolt11(/g' \
    -e 's/wallet?\.createMeltQuote(/wallet?.createMeltQuoteBolt11(/g' \
    "$f"
done

Be sure to handle optional-chain forms (wallet?.createMeltQuote() explicitly.

Step 4 — Keysets moved into KeyChain

wallet.getKeySets() is gone. Use wallet.keyChain.getKeysets() which returns Keyset[] (a domain class), not the raw API DTO MintKeyset.

bash
sed -i 's/wallet\.getKeySets()/wallet.keyChain.getKeysets()/g' "$f"

If the codebase has type annotations using MintKeyset against the result, the cheapest fix is to alias Keyset as MintKeyset in the import — both classes expose .id so most call sites are unaffected:

ts
import { Keyset as MintKeyset } from "@cashu/cashu-ts";

If your code reads more than .id (e.g. active), you'll need to switch to Keyset proper and adjust field accesses.

Step 5 — The Amount boundary (CRITICAL)

Amount is a class. Every quote/proof/response now carries Amount where v2 had number. The migration guide presents two strategies:

  • Choice A: refactor your domain types to Amount end-to-end.
  • Choice B (recommended for sat-denominated marketplaces below MAX_SAFE_INTEGER): keep internal types as number, convert at the cashu-ts boundary with .toNumber().

Choice B was the right call for shopstr (sat-only marketplace, simpler diff). Apply systematically:

ts
// arithmetic — both Amounts → both .toNumber()
const total = meltQuote.amount.toNumber() + meltQuote.fee_reserve.toNumber();

// reduce sums over Proofs (Proof.amount is Amount in v3+)
const total = proofs.reduce((acc, p) => acc + p.amount.toNumber(), 0);

// passing to functions that take number (e.g. UI formatters)
formatWithCommas(meltQuote.fee_reserve.toNumber(), "sats");

// re-extracting an Amount from a response
const meltAmount = meltResponse.quote.amount.toNumber();

A single sed pass catches the high-volume reduce patterns:

bash
sed -i \
  -e 's/acc + token\.amount/acc + token.amount.toNumber()/g' \
  -e 's/acc + p\.amount/acc + p.amount.toNumber()/g' \
  -e 's/acc + current\.amount/acc + current.amount.toNumber()/g' \
  -e 's/meltQuote\.amount + meltQuote\.fee_reserve/meltQuote.amount.toNumber() + meltQuote.fee_reserve.toNumber()/g' \
  "$f"

Method inputs that accept AmountLike (e.g. wallet.createMintQuoteBolt11(amount), wallet.send(amount, proofs, ...)) accept raw number. No conversion needed at input sites.

Step 6 — getDecodedToken requires a second argument

ts
getDecodedToken(token, keysetIds: string[])

The second argument is the list of keyset IDs the caller is willing to trust for V2 (Hashed) keysets. Pass [] if your application only handles standard hex (V1) keyset IDs (the universal default for current Cashu mints). For mints using v2 hashed keyset IDs you must obtain the IDs out-of-band first via getTokenMetadata.

ts
// before
const decoded = getDecodedToken(token);

// after (safe for v1 hex keysets)
const decoded = getDecodedToken(token, []);

Step 7 — MintQuoteState lives on the bolt11-specific response

MintQuoteBaseResponse is method-agnostic and does NOT carry state. Use the Bolt11 variants (returned by checkMintQuoteBolt11) which extend the base with state: MintQuoteState. Same story for fee_reserve on melt — only present on MeltQuoteBolt11Response. Once you've completed Step 3 the typed return values flow correctly.

ts
import { MintQuoteState } from "@cashu/cashu-ts";
const status = await wallet.checkMintQuoteBolt11(quote);
if (status.state === MintQuoteState.PAID) { ... }
Show full SKILL.md (427 more words)Show less

Step 8 — Add await wallet.loadMint() at every construction site

This is a runtime requirement TypeScript will not enforce. Audit every new CashuWallet(...) site and ensure loadMint() is awaited before any keyChain.*, createMintQuoteBolt11, createMeltQuoteBolt11, checkProofsStates, receive, send, etc. is called. Skip and the wallet's lazily-loaded mint info will be undefined and methods will throw.

bash
# Find every construction site
grep -rn "new CashuWallet(" --include="*.ts" --include="*.tsx"

For wallets stored in React state via setWallet and only used later in handlers that already call loadMint(), the construction-site call may be skipped — but adding it is harmless and defensive.

Step 9 — Update Jest mocks

Test mocks need three coordinated changes:

  1. Use the new export names in jest.mock factories (Mint/Wallet, not CashuMint/CashuWallet).
  2. Rename method keys to the Bolt11 variants.
  3. Wrap keysets as keyChain: { getKeysets: ... } (not getKeySets: at the top level).
  4. Add loadMint to every mock wallet implementation, including per-test mockImplementation overrides.
ts
// before
jest.mock("@cashu/cashu-ts", () => ({
  CashuMint: jest.fn().mockImplementation(() => ({})),
  CashuWallet: jest.fn().mockImplementation(() => ({
    createMeltQuote: mockCreateMeltQuote,
    getKeySets: mockGetKeySets,
    send: mockSend,
    meltProofs: mockMeltProofs,
  })),
}));

// after
jest.mock("@cashu/cashu-ts", () => ({
  Mint: jest.fn().mockImplementation(() => ({})),
  Wallet: jest.fn().mockImplementation(() => ({
    loadMint: jest.fn().mockResolvedValue(undefined),
    createMeltQuoteBolt11: mockCreateMeltQuote,
    keyChain: { getKeysets: mockGetKeySets },
    send: mockSend,
    meltProofsBolt11: mockMeltProofs,
  })),
}));

For tests that use auto-mocking (jest.mock("@cashu/cashu-ts") with no factory) plus (CashuWallet as jest.Mock).mockImplementation(...), the alias trick from Step 1 means the local binding resolves to the auto-mock — only the method-name keys inside the implementation need updating.

Number.prototype shim for Choice B test mocks

Test mocks return raw numbers for fields that are now Amount. Production code calls .toNumber() on them and explodes (is not a function). The cleanest fix is a one-line shim in jest.setup.js so raw numbers stay compatible:

js
// jest.setup.js
if (!Number.prototype.toNumber) {
  Object.defineProperty(Number.prototype, "toNumber", {
    value: function () {
      return this.valueOf();
    },
    writable: true,
    configurable: true,
  });
}

This is test-scope only; production Amount objects bring their own .toNumber(). Without this shim you'd have to wrap every mock value in a fake { toNumber: () => N }, which bloats fixtures.

Step 10 — Validation order

  1. npx tsc --noEmit — must reach exit 0 before running tests. Fix Amount boundary errors and method-rename leftovers first; these surface cleanly in tsc output.
  2. npx jest — expect failures clustered in wallet UI tests if Step 9 wasn't applied. Compare pass count to your pre-migration baseline; the goal is zero new failures.
  3. Restart the dev server and confirm the app compiles and serves a clean response. The dev server will catch missed @noble/hashes extension paths (Step 0) that tsc allows.

What this migration does NOT cover

  • Bolt12 helpers (createMintQuoteBolt12, mintProofsBolt12, etc.) — adopt as needed.
  • Mint operation durability (timeouts, retries, failover, durable pending operations) — these are enabled by the v3+ rate-limit-aware retry primitives but require separate application-level work (typically a dedicated mint-retry-service).
  • OutputConfig (4th arg to wallet.send / mint helpers) for advanced output shaping like P2PK locking — only needed if migrating away from the legacy pubkey config field.

Quick reference: bulk sed bundle

For a typical mid-sized codebase the following sed bundle clears 80%+ of the breakage. Apply, then iterate on the residual tsc errors:

bash
FILES=$(git ls-files '*.ts' '*.tsx')
for f in $FILES; do
  sed -i \
    -e 's|from "@noble/hashes/utils"|from "@noble/hashes/utils.js"|g' \
    -e 's|from "@cashu/crypto/modules/common"|from "@cashu/cashu-ts"|g' \
    -e 's/wallet\.createMintQuote(/wallet.createMintQuoteBolt11(/g' \
    -e 's/wallet\.checkMintQuote(/wallet.checkMintQuoteBolt11(/g' \
    -e 's/wallet\.mintProofs(/wallet.mintProofsBolt11(/g' \
    -e 's/wallet\.createMeltQuote(/wallet.createMeltQuoteBolt11(/g' \
    -e 's/wallet\.meltProofs(/wallet.meltProofsBolt11(/g' \
    -e 's/wallet?\.createMeltQuote(/wallet?.createMeltQuoteBolt11(/g' \
    -e 's/wallet\.getKeySets()/wallet.keyChain.getKeysets()/g' \
    -e 's/acc + p\.amount/acc + p.amount.toNumber()/g' \
    -e 's/acc + token\.amount/acc + token.amount.toNumber()/g' \
    -e 's/acc + current\.amount/acc + current.amount.toNumber()/g' \
    "$f"
done

© shopstr-eng, GPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/cashu-ts-migration of shopstr-eng/shopstr.

Open the folder on GitHubat commit fcfc0bd

Compare with similar skills

Cashu TS Migration next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Cashu TS Migration compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Cashu TS Migration this skillshopstr-eng/shopstr103—~3.1kAutomated safety check: PassGPL-3.0
Bungalfrevn/apollo237—~2kAutomated safety check: NotesMIT
Jest Skillsickn33/agentic-awesome-skills47k1 repos~1.4kAutomated safety check: PassMIT
Vitest Skillsickn33/agentic-awesome-skills47k1 repos~1.2kAutomated safety check: PassMIT
Javascript Typescript Jestgithub/awesome-copilot40k1 repos~559Automated safety check: PassMIT
Jest UnitPramodDutta/qaskills235—~3.8kAutomated safety check: PassMIT

Similar skills

  • Bun

    galfrevn/apollo

    A skill your agent uses when building, running, testing, or bundling JavaScript/TypeScript applications.

    237 GitHub stars~2k tokensUpdated 1 mo ago
    Testing & QAAuto-check: notes
  • Jest Skill

    sickn33/agentic-awesome-skills

    Generates Jest unit and integration tests in JavaScript or TypeScript.

    47k GitHub starsUsed in 1 repo~1.4k tokens
    Testing & QAAuto-check passed
  • Vitest Skill

    sickn33/agentic-awesome-skills

    Generates Vitest tests in JavaScript/TypeScript with Vite-native speed.

    47k GitHub starsUsed in 1 repo~1.2k tokens
    Testing & QAAuto-check passed
  • Javascript Typescript Jest

    github/awesome-copilot

    Official

    Best practices for writing JavaScript/TypeScript tests using Jest, including mocking strategies, test structure, and common patterns.

    40k GitHub starsUsed in 1 repo~559 tokens
    Testing & QAAuto-check passed
  • Jest Unit

    PramodDutta/qaskills

    Unit testing skill using Jest for TypeScript and JavaScript, covering mocking, spies, snapshots, coverage, async testing, and custom matchers.

    235 GitHub stars~3.8k tokensUpdated 6 days ago
    Testing & QAAuto-check passed
  • Test Suite Analysis

    prime-radiant-inc/greenfield

    Layer 1 skill for extracting behavioral intelligence from test suites.

    292 GitHub stars~3.2k tokensUpdated 2 mo ago
    Testing & QAAuto-check passed

Questions about Cashu TS Migration

What does Cashu TS Migration do?

Migrate a TypeScript/JavaScript codebase from @cashu/cashu-ts v2 to v4. Cashu TS Migration is an agent skill from shopstr-eng/shopstr. Migrate a TypeScript/JavaScript codebase from @cashu/cashu-ts v2 to v4.

When should I use Cashu TS Migration?

Cashu TS Migration fits situations like: bumping cashu-ts past 2.x to unlock v3+ Wallet ergonomics (rate-limit aware retries; amount boundary type; BOLT-method-typed quote helpers).

How do I install Cashu TS Migration in Claude Code?

Run `npx skills add shopstr-eng/shopstr --skill cashu-ts-migration -a claude-code`. Or copy the skill folder (.agents/skills/cashu-ts-migration in shopstr-eng/shopstr) into .claude/skills/cashu-ts-migration in your project. Claude Code loads it when a task matches its description.

How do I install Cashu TS Migration in Codex?

Run `npx skills add shopstr-eng/shopstr --skill cashu-ts-migration -a codex`. Or copy the skill folder (.agents/skills/cashu-ts-migration in shopstr-eng/shopstr) into .agents/skills/cashu-ts-migration in your project. Codex loads it when a task matches its description.

Can I use Cashu TS Migration in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add shopstr-eng/shopstr --skill cashu-ts-migration -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/cashu-ts-migration, .gemini/skills/cashu-ts-migration, .github/skills/cashu-ts-migration and .opencode/skills/cashu-ts-migration in your project.

What does Cashu TS Migration need to run?

Going by SKILL.md and its folder, Cashu TS Migration needs the command-line tools its instructions call (git, npx and npm). Our summary lists: Node.js.

Does Cashu TS Migration access the network?

SKILL.md contains no URLs. Its commands use git, npx and npm, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Cashu TS Migration safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Cashu TS Migration use?

Cashu TS Migration is published under the GPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Cashu TS Migration use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Cashu TS Migration?

Skills that share tags, products or a category with Cashu TS Migration: Bun (galfrevn/apollo, 237 stars), Jest Skill (sickn33/agentic-awesome-skills, 47k stars), Vitest Skill (sickn33/agentic-awesome-skills, 47k stars) and Javascript Typescript Jest (github/awesome-copilot, 40k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Cashu TS Migration?

shopstr-eng (a GitHub organization) maintains it in shopstr-eng/shopstr, which has 103 GitHub stars. The repository was last updated on October 1, 2026.

Source: shopstr-eng/shopstr on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.