Our review
This skill enables managing recurring payment subscriptions on Solana using a Dynamic MPC wallet, including wallet creation, balance checks, SOL→USDC swaps, and the full lifecycle for both subscribers and merchants.
Strengths
- Automated MPC wallet creation with no manual setup needed.
- Handles both subscriber (subscribe, cancel, view) and merchant (create plan, collect, sunset) flows.
- Uses an MPC wallet for enhanced key security.
- Supports built-in SOL→USDC swaps.
Limitations
- Requires manual funding of SOL for transaction fees.
- Depends on Dynamic.xyz service for key management.
- Only works on Solana mainnet (no testnet).
Use this skill when you need to set up or interact with recurring payments on Solana, either as a subscriber or a merchant.
Do not use it for non-blockchain subscriptions or when you need fiat currency payments.
Security analysis
CautionThe skill runs a Node.js script that performs Solana wallet operations including sending funds and creating subscriptions. All actions are legitimate and described, but the financial nature demands caution. No malicious patterns like exfiltration or remote execution were observed.
- •Handles irreversible fund transfers (send-all, send) which could lead to loss if misused.
- •Executes blockchain transactions via Bash, requiring careful input validation to avoid errors.
Examples
Subscribe to the first plan offered by merchant address HXq3...abc on Solana.Cancel the subscription with PDA 9Yz2...def for plan HXq3...abc.Show my current Solana wallet balance and USDC balance.name: solana-subscriptions description: | Subscribe to Solana on-chain recurring payment plans using a Dynamic MPC wallet. Handles wallet creation, balance checks, SOL→USDC swaps, and the full lifecycle for both sides: subscribers (subscribe / cancel / view) and merchants (create-plan / collect / sunset / delete) — all from a single script. allowed-tools:
- Bash
- Read
Solana Subscriptions
Use this skill when the user asks to:
- Subscribe to a service, newsletter, or recurring payment plan on Solana
- Cancel a Solana subscription
- View their active subscriptions
- Send SOL or an SPL token to another address (or sweep the whole wallet)
- Create / publish a subscription plan (merchant flow)
- Collect payment from subscribers (merchant flow)
- Retire (sunset) or delete a plan (merchant flow)
- Set up a wallet for Solana subscriptions
The underlying script is subscriptions-skill.mjs in this directory. It signs every
transaction with a Dynamic MPC wallet. Sensitive secrets (the key share, API token,
and passphrases) are stored in the macOS Keychain when available — falling back to
.env otherwise — and are never logged.
Prerequisites
Only two manual steps — the wallet bootstraps itself after that.
-
Install dependencies once (from this directory):
pnpm install -
Configure credentials — copy
.env.example→.envand fill in:DYNAMIC_ENVIRONMENT_ID— from https://app.dynamic.xyz → SettingsDYNAMIC_AUTH_TOKEN— adyn_...token from the same page
That's it. Any command auto-creates the wallet on first use (you can still run
pnpm subs setup explicitly if you prefer). USDC can be sent directly or minted
from SOL with pnpm subs swap <amount_usdc>.
Wallet bootstrap & funding (important for the conversational flow)
The script handles its own prerequisites, so Claude should just run the command the user asked for and react to what it prints:
- No wallet yet? The command prints
No wallet configured yet — creating one…, creates the MPC wallet, and continues automatically. No separate setup step. - Wallet has no SOL? Any on-chain command stops before doing anything and
prints a funding prompt with the wallet address and the amount needed. When you
see this, relay the address to the user and ask them to send SOL (there is no
mainnet faucet — they fund it from an exchange or another wallet). After they
confirm, re-run the same command, or run
pnpm subs balanceto verify it landed.
So a typical first interaction is: run the command → it creates the wallet → it asks the user to fund the printed address → user funds it → re-run the command.
Step-by-step flow
1 — Discover plans
Ask the user for the merchant's Solana wallet address, then:
pnpm subs list-plans <merchant_address>
Output example:
[0] HXq3...abc 0.100000 USDC/1h (active)
metadata: https://cryptonfas.com/plans/weekly
[1] 9Yz2...def 5.000000 USDC/7d (active)
2 — Subscribe
pnpm subs subscribe <merchant_address> <plan_index>
The script will:
- Initialize a SubscriptionAuthority account if this is the user's first subscription
- Submit the
subscribetransaction - Print the subscription PDA for future reference
3 — Check subscriptions
pnpm subs subs
4 — Cancel
pnpm subs cancel <plan_pda> <sub_pda>
Cancellation queues the expiry at end of the current period — the user keeps access until then.
Send & sweep funds
Send SOL or any SPL token to another address:
pnpm subs send <recipient> <amount> [SOL|USDC|<mint>] # token defaults to SOL
pnpm subs send <recipient> all USDC # send the entire USDC balance
pnpm subs send-all <recipient> # sweep ALL SOL + USDC
Notes:
send-allmoves USDC first (it needs SOL to pay the fee and the recipient's token-account rent), then sweeps SOL. It leaves the rent-exempt minimum (~0.00089 SOL) behind, so the wallet ends up almost empty, not zero.- Sending an SPL token creates the recipient's associated token account if needed (the sender pays that one-time rent).
- ⚠️ Transfers are irreversible. Confirm the recipient address with the user before
sending, especially for
send-all.
Merchant flow
Create a plan
pnpm subs create-plan <amount_usdc> <period_hours> [metadata_uri]
# e.g. 0.50 USDC every 24h:
pnpm subs create-plan 0.50 24 https://example.com/plan.json
Prints the plan PDA. The calling wallet is the merchant, the authorized puller, and
the payout destination. Share <merchant_address> so subscribers can list-plans.
Collect payment
Within each billing period the merchant may pull up to the plan amount from a
subscriber. <delegator> is the subscriber's wallet:
pnpm subs collect <plan_pda> <sub_pda> <delegator> <amount_usdc>
If
collectfails withInvalid account ownerimmediately after asubscribe, the new accounts have not propagated to the RPC yet — wait a few seconds and retry.
Sunset a plan (stop new subscriptions)
pnpm subs sunset-plan <plan_pda> [end_in_minutes]
Sets the plan to Sunset: no new subscriptions, existing ones honored until the end
date. The protocol requires the end date to be at least one full billing period in
the future, so the command never sets it sooner. A plan is immutable once
sunset — this is a one-shot change.
Delete a plan (reclaim rent)
pnpm subs delete-plan <plan_pda>
Only works after a sunset plan's end date has passed (PLAN_NOT_EXPIRED
otherwise). Closes the plan account and returns its rent to the merchant.
Secrets & security
- At-rest secrets (key share, API token,
WALLET_BACKUP_PASSWORD) live in the macOS Keychain when available, not.env.setupwrites them there. setupbacks the share up to Dynamic (encrypted withWALLET_BACKUP_PASSWORD, auto-generated if unset) so it's recoverable.- The keystore passphrase is per-session and never stored —
setupprompts you to set one; signing reads it fromSUBS_KEYSTORE_PASSPHRASE(export it) or prompts. This keeps the decryption key in a different place than the share.
Helper commands:
pnpm subs secrets # move any secrets in .env into the Keychain & show locations
pnpm subs encrypt-shares # encrypt the key share if you created the wallet without a passphrase
- Never paste the keystore passphrase into chat or run signing commands unattended with it exported. Encryption protects secrets at rest, not against code in the session.
Handling common errors
| Error | Fix |
|---|---|
| Missing credentials | Copy .env.example → .env and fill in both values |
| Key shares are encrypted but SUBS_KEYSTORE_PASSPHRASE is not set | Export the passphrase used at setup before running |
| no record of a prior credit | Wallet needs SOL for gas — fund it |
| 0x205 alreadySubscribed | Treated as success — subscription already active |
| Invalid account owner (right after subscribe) | RPC lag — wait a few seconds and retry collect |
| custom program error: 0x1ff (INVALID_END_TS) | Sunset end date must be ≥ one billing period out; let the command default it |
| custom program error: 0x203 (PLAN_NOT_EXPIRED) | Can't delete until the sunset end date passes |
| Insufficient | Run swap to get USDC first |
Natural language examples
"Claude, use my Dynamic wallet to subscribe to Crypto NFAs weekly"
- Run
list-plans <merchant>to find the weekly plan index - Run
subscribe <merchant> <index>
"Subscribe me to this newsletter for 0.1 USDC/hour"
- Run
list-plans <merchant>to find the matching plan - Confirm price with user
- Run
subscribe <merchant> <index>
"Cancel my crypto newsletter subscription"
- Run
substo list active subscriptions - Identify the right one
- Run
cancel <plan_pda> <sub_pda>
"Create a plan that charges 5 USDC a month"
- Run
create-plan 5 720(720h ≈ 30 days) - Share the merchant wallet address so subscribers can find it via
list-plans
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.