Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dynamic Solana Subscriptions Skill

A Claude skill for subscribing to on-chain recurring payment plans using Dynamic MPC wallets.

What it does

  • Creates a Dynamic WaaS Solana MPC wallet
  • Checks SOL and USDC balance
  • Swaps SOL → USDC via Dynamic's Swap API
  • Sends SOL or any SPL token to another address (incl. sweep-all)
  • Lists subscription plans for any merchant address
  • Subscribes to a plan (initializes SubscriptionAuthority if needed)
  • Cancels subscriptions
  • Creates subscription plans (for merchants)
  • Collects payments (for merchants)
  • Sunsets / deletes plans and reclaims rent (for merchants)

Quick start

# 1. Install dependencies
pnpm install

# 2. Configure credentials
cp .env.example .env
# Edit .env: add DYNAMIC_ENVIRONMENT_ID and DYNAMIC_AUTH_TOKEN

# 3. Just run a command — the wallet is created automatically on first use.
#    (You can also create it explicitly with: pnpm subs setup)
pnpm subs balance

# 4. Fund the wallet with SOL for gas. Any on-chain command will print the
#    wallet address and ask you to fund it if the balance is empty.
#    Once it has SOL, mint USDC from it if needed:
pnpm subs swap 1.00

# 5. Browse plans
pnpm subs list-plans <merchant_solana_address>

# 6. Subscribe
pnpm subs subscribe <merchant_solana_address> 0

First run auto-creates the MPC wallet and (if unfunded) prints a prompt to send SOL to the new address. There is no mainnet faucet — fund it from an exchange or another wallet, then re-run.

Commands

Command Description
setup Create a Dynamic WaaS Solana wallet
encrypt-shares Encrypt SOL_WALLET_KEY_SHARES at rest (needs SUBS_KEYSTORE_PASSPHRASE)
secrets Move sensitive secrets from .env into the macOS Keychain & show where each lives
balance Check SOL and USDC balance
swap <usdc> Swap SOL → USDC
send <recipient> <amount|all> [SOL|USDC|<mint>] Send SOL or an SPL token
send-all <recipient> Sweep all SOL + USDC to one address
create-plan <usdc> <period_hours> [metadata_uri] Publish a plan (merchant)
list-plans <merchant> List plans for a merchant
subscribe <merchant> <n> Subscribe to plan n (0-based)
subs List your active subscriptions
collect <plan_pda> <sub_pda> <delegator> <amount> Collect payment (merchant)
cancel <plan_pda> <sub_pda> Cancel a subscription
sunset-plan <plan_pda> [end_in_minutes] Retire a plan — no new subscriptions (merchant)
delete-plan <plan_pda> Delete an expired plan & reclaim rent (merchant)

Claude skill

The SKILL.md file is a Claude Code skill definition. Install it and Claude can handle requests like:

"Claude, use my Dynamic wallet to subscribe to Crypto NFAs weekly"

Package manager & private registry

This project uses pnpm (packageManager is pinned in package.json; run via corepack enable or install pnpm directly). The committed .npmrc sets always-auth=false so pnpm doesn't demand credentials for public registries.

The @dynamic-labs-wallet/* packages are served from a private jfrog registry. Your global ~/.npmrc must carry the auth token for that host — and because some tarballs live under a different repo path on the same host, the token must be authorized at the host root, e.g.:

//<your-jfrog-host>/:_authToken=${YOUR_TOKEN}

(npm sends host-wide auth implicitly; pnpm matches by path, so the host-root entry is required.) Never commit tokens — keep them in your global ~/.npmrc only.

Tech stack

Security

Credentials are loaded from .env and never logged or transmitted beyond the Dynamic and Solana APIs. Run pnpm subs without arguments to see the usage summary.

Securing the MPC key share

SOL_WALLET_KEY_SHARES is the customer-side half of MPC signing. Combined with your DYNAMIC_AUTH_TOKEN (and WALLET_BACKUP_PASSWORD), it confers signing authority — treat it like a private key. It is encrypted, not hashed, because the share must be recoverable to sign.

Where things are stored

Value Sensitivity Stored in
SOL_WALLET_ADDRESS, DYNAMIC_ENVIRONMENT_ID, TOKEN_MINT Non-sensitive .env
SOL_WALLET_KEY_SHARES, DYNAMIC_AUTH_TOKEN, WALLET_BACKUP_PASSWORD Sensitive macOS Keychain (falls back to .env off-macOS)
SUBS_KEYSTORE_PASSPHRASE Sensitive nowhere — per session
  • Encryption at rest: the key share is wrapped with AES-256-GCM (unique salt + IV, tamper-evident), key derived via PBKDF2-SHA256 (600k iterations) from the keystore passphrase. Envelope: enc:v1:<salt>:<iv>:<authTag>:<ciphertext>.
  • Per-session passphrase: SUBS_KEYSTORE_PASSPHRASE is never stored. setup prompts you to set one; signing reads it from the env var (export it for the session) or prompts interactively. Keeping it out of the Keychain means a Keychain compromise alone can't decrypt the share.
  • pnpm subs secrets moves any secrets sitting in .env into the Keychain. pnpm subs encrypt-shares encrypts the share if you set the wallet up without a passphrase.
  • Back up WALLET_BACKUP_PASSWORD off-machine (e.g. a password manager): it's the recovery key for the Dynamic-side backup. Losing both it and the local share = no recovery.

Threat model — what this does and does not protect

  • ✅ A leaked .env contains no signing material — secrets are in the Keychain.
  • ✅ A Keychain compromise alone can't decrypt the share — the passphrase is supplied per session, not stored.
  • ❌ Does not protect against code running in your session: to sign, the share is decrypted into process memory and the passphrase is in the runtime env. Don't paste SUBS_KEYSTORE_PASSPHRASE into chat or export it in an unattended agent session.
  • 🔐 Real defense-in-depth is the 2-of-2 MPC threshold: the client share alone cannot sign — it also needs the Dynamic server share via DYNAMIC_AUTH_TOKEN.

Also persist the full walletMetadata object (including externalServerKeySharesBackupInfo) — it's required to sign/export and is not recoverable from fetchWalletMetadata, which returns identity only. This skill re-fetches it per environment via getWallets(); a production service should cache it durably.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages