diff --git a/.env.example b/.env.example index a7e7b5b..95fd04b 100644 --- a/.env.example +++ b/.env.example @@ -5,14 +5,22 @@ DYNAMIC_ENVIRONMENT_ID=your-environment-id-here DYNAMIC_AUTH_TOKEN=dyn_your_token_here -# Populated automatically by the `setup` command — DO NOT edit or share. -# SOL_WALLET_KEY_SHARES holds your MPC key share; treat it like a private key. +# Set automatically by `setup`. The wallet address is non-sensitive and lives here. +# The MPC key share is sensitive: on macOS it is stored in the Keychain (not this +# file); elsewhere it falls back to SOL_WALLET_KEY_SHARES below. SOL_WALLET_ADDRESS= SOL_WALLET_KEY_SHARES= -# Password protecting the Dynamic-side key-share backup. Leave blank and `setup` -# will generate a strong random one and write it here; or pin your own before setup. -# Required to sign — back it up. Losing it means re-running `setup` for a new wallet. +# Per-session passphrase that encrypts the key share (AES-256-GCM). It is NEVER +# stored — `setup`/`encrypt-shares` prompt for it, and signing reads it from this +# env var (export it for the session) or prompts you. Back it up: lose it and the +# encrypted share can only be recovered via WALLET_BACKUP_PASSWORD (below). +# SUBS_KEYSTORE_PASSPHRASE= + +# Recovery password for the key-share backup stored on Dynamic (setup enables +# backUpToDynamic). Leave blank and `setup` generates a strong random one (stored in +# the Keychain on macOS); or pin your own here. Must NOT equal DYNAMIC_ENVIRONMENT_ID. +# Back it up off-machine — without it the Dynamic backup can't be decrypted. WALLET_BACKUP_PASSWORD= # Optional: override Solana RPC (defaults to https://api.mainnet-beta.solana.com). @@ -24,9 +32,6 @@ WALLET_BACKUP_PASSWORD= # Solana mainnet USDC — replace with your token mint if using a different token TOKEN_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v -# Optional: default merchant address for plan search -# MERCHANT_ADDRESS= - # Optional: SOL→USDC swap slippage tolerance, as a 0–1 fraction (default 0.1 = 10%). # Swaps request an exact USDC output, so too tight a value makes the route fail with # LessThanMinimumAmountOut (0x1778). Lower it for a tighter fill on larger swaps. diff --git a/README.md b/README.md index 7a6bae8..9eb8a7c 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,8 @@ pnpm subs subscribe 0 | 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 ` | Swap SOL → USDC | | `send [SOL\|USDC\|]` | Send SOL or an SPL token | @@ -98,3 +100,48 @@ is required.) Never commit tokens — keep them in your global `~/.npmrc` only. 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::::`. +- **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. diff --git a/SKILL.md b/SKILL.md index 3d1ef9a..73b0e40 100644 --- a/SKILL.md +++ b/SKILL.md @@ -23,7 +23,37 @@ Use this skill when the user asks to: - 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; key shares live in `.env` and are never logged. +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. + +--- + +## Network switching + +The skill defaults to **mainnet**. When the user asks to use devnet (e.g. "use devnet", +"switch to devnet", "test on devnet"), run: + +```bash +pnpm subs network devnet +``` + +To switch back to mainnet: + +```bash +pnpm subs network mainnet +``` + +The choice is written to `.env` so it persists for all subsequent commands in the +session. On devnet, SOL can be funded via airdrop — remind the user: +``` +solana airdrop 2
--url devnet +``` + +To check the active network at any time: +```bash +pnpm subs network +``` --- @@ -176,12 +206,34 @@ 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`. `setup` writes them there. +- **`setup` backs the share up to Dynamic** (encrypted with `WALLET_BACKUP_PASSWORD`, + auto-generated if unset) so it's recoverable. +- The **keystore passphrase is per-session and never stored** — `setup` prompts you + to set one; signing reads it from `SUBS_KEYSTORE_PASSPHRASE` (export it) or prompts. + This keeps the decryption key in a different place than the share. + +Helper commands: + +```bash +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 | -| `No Solana wallet configured` | Run `setup` first | +| `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` | diff --git a/package.json b/package.json index 1ee473f..a4381b4 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@solana-program/system": "0.12.0", "@solana-program/token": "0.13.0", "@solana/kit": "6.9.0", - "@solana/subscriptions": "0.2.0", + "@solana/subscriptions": "0.4.0-rc.2", "@solana/web3.js": "1.98.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..143bbad --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1765 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@dynamic-labs-wallet/node': + specifier: 1.0.5 + version: 1.0.5(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@dynamic-labs-wallet/node-svm': + specifier: 1.0.5 + version: 1.0.5(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana-program/system': + specifier: 0.12.0 + version: 0.12.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)) + '@solana-program/token': + specifier: 0.13.0 + version: 0.13.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)) + '@solana/kit': + specifier: 6.9.0 + version: 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana/subscriptions': + specifier: 0.4.0-rc.2 + version: 0.4.0-rc.2(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))(@solana/sysvars@6.9.0(typescript@6.0.3))(typescript@6.0.3) + '@solana/web3.js': + specifier: 1.98.4 + version: 1.98.4(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + +packages: + + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + + '@dynamic-labs-wallet/core@1.0.5': + resolution: {integrity: sha512-5zuU5w+StdhKI1CfqZFVFSdz4LpAGM/FNT3v2CCmQoRpxvN0AIE1A0ITGVXU6F3k173hwA6SWmdxKiwyhA+ESA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/core/-/@dynamic-labs-wallet/core-1.0.5.tgz} + peerDependencies: + '@dynamic-labs-wallet/forward-mpc-client': 0.10.0 + + '@dynamic-labs-wallet/forward-mpc-client@0.10.0': + resolution: {integrity: sha512-e17ixbWfmD/zmHuVivvK/36zxMvVFQhfjZ1JOR6HMsly8s4xmlzLy7m49Heykd5V98YLs5spAy5QLQyw0ojGXg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.10.0.tgz} + peerDependencies: + '@dynamic-labs-wallet/primitives': '>=0.0.336 || 0.0.1' + + '@dynamic-labs-wallet/forward-mpc-shared@0.7.0': + resolution: {integrity: sha512-mN6zT5J8JbZxkOJxEjgGrjURybVn/t9DD+pWW5U4DRZH6Qakn5n1LIB4Lg4Y7OW9WwrlMH2IJ9RNgBW35RaF1A==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.7.0.tgz} + peerDependencies: + '@dynamic-labs-wallet/primitives': '>=0.0.336 || 0.0.1' + + '@dynamic-labs-wallet/node-svm@1.0.5': + resolution: {integrity: sha512-bY+u0wgQ3CD+9lyPxMQivUKCGxpJvfL6P3MFl2LVUb0p4t1GNe1A9nwXJMJC7HjGryLr1gg7W9aUhVNTw9+N8A==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/node-svm/-/@dynamic-labs-wallet/node-svm-1.0.5.tgz} + + '@dynamic-labs-wallet/node@1.0.5': + resolution: {integrity: sha512-FeammJzXtD3Rm9nRvzkWtM0Sf9TC/3uL7hTvfnBUAeiyJyuNhh3s4pZtcfonI7UTmeNi3PxAmHBPXNAdzm/sOQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/node/-/@dynamic-labs-wallet/node-1.0.5.tgz} + + '@dynamic-labs-wallet/primitives@1.0.5': + resolution: {integrity: sha512-m99T1meeokz47E94JtGYiu+DSW8GVXYvZblt1+DXpG+uUxumuRK/YJTvYjc0jEkvQSZbJJwUNwSoCOvqI9tDcw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/primitives/-/@dynamic-labs-wallet/primitives-1.0.5.tgz} + + '@dynamic-labs/logger@4.84.1': + resolution: {integrity: sha512-0/QnGlA4UUOlqKl0fIrefQ+kXvFVAUgHkExnESIbdlJYH3BTEX61LTb/Sx7lYRho55QkR6XVjEjeZzHY8ngGoA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs/logger/-/@dynamic-labs/logger-4.84.1.tgz} + + '@dynamic-labs/sdk-api-core@0.0.984': + resolution: {integrity: sha512-smSL1nUDZ753Ldeb848GJufOzEMzkGUcDdxUVcfmfHnA8kEdmKO+c/4nfQEUeDNvaFxd9ueB9ZKTYkLC2t/uXg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs/sdk-api-core/-/@dynamic-labs/sdk-api-core-0.0.984.tgz} + + '@evervault/wasm-attestation-bindings@0.3.1': + resolution: {integrity: sha512-pJsbax/pEPdRXSnFKahzGZeq2CNTZ0skAPWpnEZK/8vdcvlan7LE7wMSOVr+Z+MqTBnVEnS7O80TKpXKU5Rsbw==} + + '@noble/ciphers@0.4.1': + resolution: {integrity: sha512-QCOA9cgf3Rc33owG0AYBB9wszz+Ul2kramWN8tXG44Gyciud/tbkEqvxRF/IpqQaBpRBNi9f4jdNxqB2CQCIXg==} + + '@noble/curves@1.9.7': + resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@2.0.1': + resolution: {integrity: sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==} + engines: {node: '>= 20.19.0'} + + '@noble/hashes@1.7.1': + resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@2.0.1': + resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} + engines: {node: '>= 20.19.0'} + + '@noble/hashes@2.2.0': + resolution: {integrity: sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==} + engines: {node: '>= 20.19.0'} + + '@noble/post-quantum@0.5.4': + resolution: {integrity: sha512-leww0zzIirrvwaYMPI9fj6aRIlA/c6Y0/lifQQ1YOOyHEr0MNH3yYpjXeiVG+tWdPps4XxGclFWX2INPO3Yo5w==} + engines: {node: '>= 20.19.0'} + + '@solana-program/system@0.12.0': + resolution: {integrity: sha512-ZnAAWeGVMWNtJhw3GdifI2HnhZ0A0H0qs8tBkcFvxp/8wIavvO+GOM4Jd0N22u2+Lni2zcwvcrxrsxj6Mjphng==} + peerDependencies: + '@solana/kit': ^6.1.0 + + '@solana-program/token-2022@0.9.0': + resolution: {integrity: sha512-j8fPBc/oUApYF7aW0ub6cIV7dbbtXC+Y6oDcI9SUs6BXXSq+lj7p7XRU+GEH8qWfyQ5ziRiOLI9s2AZjJY1Icg==} + peerDependencies: + '@solana/kit': ^6.0.0 + '@solana/sysvars': ^5.0 + + '@solana-program/token@0.13.0': + resolution: {integrity: sha512-/Apjrd5lwOJGrPB0J5Rv7EBeclvyEBQPAGA85Scm7wBH+GpkbdLDM9uK3TNg8jjFKyWQYai/JtPHbrx7VgFLSg==} + peerDependencies: + '@solana/kit': ^6.5.0 + + '@solana/accounts@6.9.0': + resolution: {integrity: sha512-g36AJreJrgf9AAjOfbdFHEFUTymBgzbWHoEDElZ+fDKvqBINDiUVKzDApwc7C7kGPMFqQBaoEHnQRxf2IqfKZQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/accounts/-/accounts-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/addresses@6.9.0': + resolution: {integrity: sha512-tWnG2L6lo/ZhcMT019F3myDsH87MM8EZbTO0cgwgvVPlEdIGblROFF3tGVrb7FVCOlbPI0ONCFyPbnrmR58LsA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/addresses/-/addresses-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/assertions@6.9.0': + resolution: {integrity: sha512-FjWWD6e0in+HFsHMvU2zKCbyPfKtDW6iGXZZ9+Qg1QUYpO1AEObsya3F7hb9RkZKUueK4WwWAQnIuvEUp3A1uA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/assertions/-/assertions-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/buffer-layout@4.0.1': + resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} + engines: {node: '>=5.10'} + + '@solana/codecs-core@2.3.0': + resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs-core/-/codecs-core-2.3.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-core@6.9.0': + resolution: {integrity: sha512-F2BmLecG/1nTtnjyD509NsEc254pxJKa2bpvotymv1lL1WfEn3zchcZ9SMIiLyL4G6J8b9F3OKIq2YSZho2AOQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs-core/-/codecs-core-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/codecs-data-structures@6.9.0': + resolution: {integrity: sha512-f7GYtiHafvJDhqiwzUUSr/6AYSK4DCw6quPmA80NZGtkNiFa+g6LoJy2wbC0wp2dxvCwNpxf6x3ILCYRutAvvg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs-data-structures/-/codecs-data-structures-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/codecs-numbers@2.3.0': + resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-numbers@6.9.0': + resolution: {integrity: sha512-XMI0FOHV2h7yPAllxWCX8z+J1msidNjXzN1mRjH5KR6C+vfzyKa2xWHve0bNSV/bjVAhqqhc7dQCpBKuF4+ScQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/codecs-strings@6.9.0': + resolution: {integrity: sha512-PTqYQxMsmdfEEq29bV1AnALD4FjFEsSxOj1fYNqooOSTEQEpUoYEQtsd55/kBsnIKltXbvYwXYXBusm19n1sQA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs-strings/-/codecs-strings-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5.4.0' + peerDependenciesMeta: + fastestsmallesttextencoderdecoder: + optional: true + typescript: + optional: true + + '@solana/codecs@6.9.0': + resolution: {integrity: sha512-oWOybKa1PTGI1D/FyrvGKralADM1jmVZC2AtgEo+4JTKG0+i1p9ZbwNY2UcJqdYsDMDaGHAx0LMAid9LDCxXTQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs/-/codecs-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/errors@2.3.0': + resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/errors/-/errors-2.3.0.tgz} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.3.3' + + '@solana/errors@6.9.0': + resolution: {integrity: sha512-7i+b07KMnkbHvFlz7uWade3jvyc22UmVm8o9taxPK8YV3JNM/NkS8oQFvMac2MIaLPAlEs7I8MHyVLUal1yY4g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/errors/-/errors-6.9.0.tgz} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/fast-stable-stringify@6.9.0': + resolution: {integrity: sha512-l14zGVsURbT5Aox/kLFQywqV4VaE9/j3h2EvCu9oULVPMwzQB6yezJb1/KyiDwhm/RscooPd0gFQFIKEGQbayw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/fast-stable-stringify/-/fast-stable-stringify-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/fixed-points@6.9.0': + resolution: {integrity: sha512-0K7mbYC4jdAZFlXqXjpNanmEyZxk7K9NtXDLc1zuhGuxwH8J9guvohwdw2V7TQ9bfjCYsprY3Tp2kUVQpECGmA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/fixed-points/-/fixed-points-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/functional@6.9.0': + resolution: {integrity: sha512-sgNHOaIjETZZuziZdlwPsU5EjBVj5M0dUbwrSQTTNZe0SxX3pQ1QFVcs5KyvdS7AQcpBVdLjx4CfQjdKXk52GA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/functional/-/functional-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/instruction-plans@6.9.0': + resolution: {integrity: sha512-SxTSOetEKD+WPzvDuYRsP1+KkwUp8KqL1n7oFx9ThxjyfEY0ly0i9KdbvX5yYVDOA2TSwrltgdu14y/Pf6y3Cg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/instruction-plans/-/instruction-plans-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/instructions@6.9.0': + resolution: {integrity: sha512-LZfJx3bGdUSbGaswoOEPHygticqkCg3TusRczPJXyCmKhoQzPCcGQQ99qMzP7Wg8pEV5tWA5t7tycf8E237ydg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/instructions/-/instructions-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/keys@6.9.0': + resolution: {integrity: sha512-1g2QARiqSjNqT0EIqLDLQ5vRm7hCsbqgFwFAp5GsMV/8BTYT8s1Ct2wLHDZiJ4eAX6beTHVf8LbOBfVejtn3oQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/keys/-/keys-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/kit-plugin-instruction-plan@0.10.0': + resolution: {integrity: sha512-h99B+1Vp5QWU/M/q0UXlTxKJt781vWw5aAopnbgVCy0F3hNaSDZ/gio126Oz0/cipGOnyaJf3NnV79GvxaEqZA==} + peerDependencies: + '@solana/kit': ^6.8.0 + + '@solana/kit-plugin-rpc@0.11.1': + resolution: {integrity: sha512-NpCKBY6y3lmOOZjzm5dvk/+iZsKOH+Wc9TQx5yKZ0RzNOXC6V9i0Inn+niVdkX5ECDJOmClfa64bLcImFJWLuQ==} + peerDependencies: + '@solana/kit': ^6.8.0 + + '@solana/kit-plugin-signer@0.10.0': + resolution: {integrity: sha512-3Gw3R6nQg/2r2+4cSaUZHj5zdbtb0SuA1mkDMd6uH7B+fdH1Ouxnulv1/sN8J0VxBo7tS+YDQA5t0arxX5gj+w==} + peerDependencies: + '@solana/kit': ^6.8.0 + + '@solana/kit@6.9.0': + resolution: {integrity: sha512-k7BRz7Akfv8wiRtlCR/xUyDLfuMfYMelMR1+AC5KgwaRRJReDF0BucMLNN1In7WoI+KuWwr1OKv4na/oKpyeAQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/kit/-/kit-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/nominal-types@6.9.0': + resolution: {integrity: sha512-ouhrnY7a6nsLXRGcariwcmHDdXroCNqOuzwtdjKt2c8e8Drwao9yxPH2VoViNgpq8IGNJeQMEI1TVnoJZRn0gw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/nominal-types/-/nominal-types-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/offchain-messages@6.9.0': + resolution: {integrity: sha512-qK3tqRPb+E0kmTz5qFXZbEdF4pyzfOWRZjyVESHVGemDDeGzZ1SV3zAxcA6HBCnv4wCBnlyaDPw8t+5sryNMAw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/offchain-messages/-/offchain-messages-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/options@6.9.0': + resolution: {integrity: sha512-H5ZRWNzzLMwHU/fRU9aVx+3TaMN4gDNCUYxsZxq0h7mqiwxFy6mpy95xPsfdldthCHDYtYnUTxe2sBatGbNHig==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/options/-/options-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/plugin-core@6.9.0': + resolution: {integrity: sha512-KslLSnzY8zbGZibEBVMVUm2ZS8T2xf+cut7F65VjWPoWNAxU+p7933wsMz/az6CF7b65RI7iU3HhCr5/5QF50w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/plugin-core/-/plugin-core-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/plugin-interfaces@6.9.0': + resolution: {integrity: sha512-Qj4sk9thkM1UgnFXvWIoezd/CbqpX/2jigLBDsMB5Ed/gmFlkBSTL127LFDSY3OtzBpXl4hROs+Zqv+5xqtguA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/plugin-interfaces/-/plugin-interfaces-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/program-client-core@6.9.0': + resolution: {integrity: sha512-+iUnsddhs72QoBJoUO+/yHUXoBvYWa1sGCBRJk35zeg8j7ZXEwRkk6eX0VOrUPxhEpQbYJsIOCrIYApNIt8RFw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/programs@6.9.0': + resolution: {integrity: sha512-L9LAnQtfFFcCDLcbbnxhUtgAmu/kS4aRmrVncdnX5CFyQshlpo0/Qhrq3UA7vnhute4gjYV4pFT+64onH5qGEQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/programs/-/programs-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/promises@6.9.0': + resolution: {integrity: sha512-227PlXRi6KZX4ODYTkJitr9InSa79NTquI72slay4gzxO9VmMepgvYdMAX6kawdN5pt+VzaklKhNhWXk50Pi9g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/promises/-/promises-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-api@6.9.0': + resolution: {integrity: sha512-3KhXS6A1ie6GqTywW/KEMSXJ1VJEU66fxjhuiiqPILuJstP7kex3ycr3H6DirKydUsy6gaKaPN43rE+LfyS7OA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-api/-/rpc-api-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-parsed-types@6.9.0': + resolution: {integrity: sha512-6ThH8izY+DWDyrVOOlS40vTcFjwjCinjfqnId7zhRk8OxhkfHQ/iEj+OnGwD4Yhe8pGdVa7GNVYlrQgQgzQ3eQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-parsed-types/-/rpc-parsed-types-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-spec-types@6.9.0': + resolution: {integrity: sha512-A4fY1JRrcKqX3EfttO4Q8L97nGPqdjfekAV0eDyxN5nu9ngf5p7GKenkl7AYDoHLNr6ZX/C96cRADxXjsRJ0iA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-spec-types/-/rpc-spec-types-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-spec@6.9.0': + resolution: {integrity: sha512-3yHRoChc0IpsJbUq0/94l+ar3t9U3Ax58W0HON7eyYe7zFP10UAxpkHn7DPch9DeALyuGph8kVnvl+kXRgJlGg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-spec/-/rpc-spec-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-subscriptions-api@6.9.0': + resolution: {integrity: sha512-UA/rPQeNx6zQMUFcS8PPPuB4vzUOtSzIY/igMH0DRoP020NyES2GguIb7Zo7sqDNi4n0gkQRhoW4dPVotcNKdA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-subscriptions-api/-/rpc-subscriptions-api-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-subscriptions-channel-websocket@6.9.0': + resolution: {integrity: sha512-kT8Yne9HjJD2gooaOFNSyKrvaIfOy2GR0Ymv8OfecBCwFStdz+SPo5eYXq8ZWoZbr5E/MMpHgqsHBanqa2Ffyg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-subscriptions-channel-websocket/-/rpc-subscriptions-channel-websocket-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-subscriptions-spec@6.9.0': + resolution: {integrity: sha512-DbaG67s99vRZQxFMK80UQ7DEKkRJK6JEZeYg/U5UttD6n7ax/vct7qopxGnrt4RCkaaac2fU8Sr+fcnvWQweUg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-subscriptions-spec/-/rpc-subscriptions-spec-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-subscriptions@6.9.0': + resolution: {integrity: sha512-IMctZQaMxzvRACQ6ooW98lP+7tVoUJnRgOZtkAdzgBizldQAYPIKd3MulP0jbQPCMfdPsa2Hs0NBcUwfgonq3w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-subscriptions/-/rpc-subscriptions-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-transformers@6.9.0': + resolution: {integrity: sha512-dg4LK2wEBpaY+KRk/SJIkYvrvjdsc1AwD4bkmGY4Fp7EwVlvwBQShAQn78Qi4IP0WQ/0n9ncFyUxgcB1Y01ZuQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-transformers/-/rpc-transformers-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-transport-http@6.9.0': + resolution: {integrity: sha512-4gy30fWJcS6jrcXCoP/optFpGJ/gD9xdkE8wDbe1Ys/Y+e4XjyBt45xtTnbdmMdukvdRX+oXS3zgUIYoagpNzQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-transport-http/-/rpc-transport-http-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc-types@6.9.0': + resolution: {integrity: sha512-iFhPzZK3qiQ1lhfNTNBTI7BIs5PfWZSgRLD3enKm8ZAQggzvUklfO3KPh47jVsc/Jsr1UGPH8M3o3m17qjO1Cg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc-types/-/rpc-types-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/rpc@6.9.0': + resolution: {integrity: sha512-ny1Kt20+oq3xZErNA56+Magmb2JKYfQgHwZTsBmHKVl/9mBpv1y1+ygV+KNiiX/wWXWstLbdIo1jgPwZPbU2Vg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/rpc/-/rpc-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/signers@6.9.0': + resolution: {integrity: sha512-x7WyoRm9IORMqeSqNivZgyY+RERPkmqWxpINPD13kUH+oaZzonORIgxk2Lz+u5iPRXiJPkdRPrQ4FoFWv8i6kQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/signers/-/signers-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/subscribable@6.9.0': + resolution: {integrity: sha512-YV0/BrJNfepf10CTfLwD7kRY1kkELDHd+BbHJZhBeiuiXTY3xQTvvx1RFs3NtfFCcTHG25Uh8NpRacQJnxSSIQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/subscribable/-/subscribable-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/subscriptions@0.4.0-rc.2': + resolution: {integrity: sha512-O/luWvguVkxulS/7kPjryZAf+jhA1DyXjGRn1/m23NEPSy5SCbeIfqHjU8nF+0va1A//aYOdQ20NyyWj5J/HFA==} + peerDependencies: + '@solana/kit': ^6.4.0 + + '@solana/sysvars@6.9.0': + resolution: {integrity: sha512-e0e+QKr/th9t/O2N1oUoJmcodLghzAtWKUlGb1zyYub0/WJrPImnKqJqp/gDP4tK98mJxopPMcprCeHk4B+TQg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/sysvars/-/sysvars-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/transaction-confirmation@6.9.0': + resolution: {integrity: sha512-fzYCOih7hhtBzzNSkAnxMjeFeQ8U7e27k9i0RsgQc3/e3OCynF5HoIVNhhqZbwfIBKiaD4ginJR6slRnfqO32Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/transaction-confirmation/-/transaction-confirmation-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/transaction-messages@6.9.0': + resolution: {integrity: sha512-OWpryt0w6SHlwHx12Vd1wvx2QwSGBXAIUEHTCtkctcM3AaZRy5cIl7CAq9iD5PgahUsaOyRLBV0zlCJcC2JrJA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/transaction-messages/-/transaction-messages-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/transactions@6.9.0': + resolution: {integrity: sha512-uKPzLwHbjwChfVl82he17ntkh02PfgnMMhN7uOAC+VbkIt1O+EEw8sX87gi6kdG/EV+QBDQXm9PLAo5W0tYylw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/transactions/-/transactions-6.9.0.tgz} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + '@solana/web3.js@1.98.4': + resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} + + '@swc/helpers@0.5.21': + resolution: {integrity: sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + + '@types/ws@7.4.7': + resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.15.2: + resolution: {integrity: sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/axios/-/axios-1.15.2.tgz} + + base-x@3.0.11: + resolution: {integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bn.js@5.2.3: + resolution: {integrity: sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==} + + borsh@0.7.0: + resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} + + bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bufferutil@4.1.0: + resolution: {integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==} + engines: {node: '>=6.14.2'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + delay@5.0.0: + resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} + engines: {node: '>=10'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + + es6-promisify@5.0.0: + resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + eyes@0.1.8: + resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} + engines: {node: '> 0.1.90'} + + fast-stable-stringify@1.0.0: + resolution: {integrity: sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==} + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + fp-ts@2.16.11: + resolution: {integrity: sha512-LaI+KaX2NFkfn1ZGHoKCmcfv7yrZsC3b8NtWsTVQeHkq4F27vI5igUuO53sxqDEa2gNQMHFPmpojDw/1zmUK7w==} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.3: + resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} + engines: {node: '>= 0.4'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + io-ts@2.2.22: + resolution: {integrity: sha512-FHCCztTkHoV9mdBsHpocLpdTAfh956ZQcIkWQxxS0U5HT53vtrcuYdQneEJKH6xILaLNzXVl2Cvwtoy8XNN0AA==} + peerDependencies: + fp-ts: ^2.5.0 + + isomorphic-ws@4.0.1: + resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} + peerDependencies: + ws: '*' + + isows@1.0.7: + resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==} + peerDependencies: + ws: '*' + + jayson@4.3.0: + resolution: {integrity: sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==} + engines: {node: '>=8'} + hasBin: true + + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/mime-db/-/mime-db-1.52.0.tgz} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + + rpc-websockets@9.3.8: + resolution: {integrity: sha512-7r+fm4tSJmLf9GvZfL1DJ1SJwpagpp6AazqM0FUaeV7CA+7+NYINSk1syWa4tU/6OF2CyBicLtzENGmXRJH6wQ==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + stream-chain@2.2.5: + resolution: {integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==} + + stream-json@1.9.1: + resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==} + + superstruct@2.0.2: + resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} + engines: {node: '>=14.0.0'} + + text-encoding-utf-8@1.0.2: + resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@8.2.0: + resolution: {integrity: sha512-uciYZ5yCmf+QJb18kJw10HjquzM7K0z992vWcI+84KeBpTfXT4hfgfGJ5DQbf/mCBPACofkrjvqgcjZfuujjFA==} + + utf-8-validate@6.0.6: + resolution: {integrity: sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==} + engines: {node: '>=6.14.2'} + + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.20.1: + resolution: {integrity: sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + +snapshots: + + '@babel/runtime@7.29.2': {} + + '@dynamic-labs-wallet/core@1.0.5(@dynamic-labs-wallet/forward-mpc-client@0.10.0(@dynamic-labs-wallet/primitives@1.0.5)(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + '@dynamic-labs-wallet/forward-mpc-client': 0.10.0(@dynamic-labs-wallet/primitives@1.0.5)(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@dynamic-labs-wallet/primitives': 1.0.5 + '@dynamic-labs/sdk-api-core': 0.0.984 + axios: 1.15.2 + uuid: 11.1.0 + transitivePeerDependencies: + - debug + + '@dynamic-labs-wallet/forward-mpc-client@0.10.0(@dynamic-labs-wallet/primitives@1.0.5)(bufferutil@4.1.0)(utf-8-validate@6.0.6)': + dependencies: + '@dynamic-labs-wallet/forward-mpc-shared': 0.7.0(@dynamic-labs-wallet/primitives@1.0.5) + '@dynamic-labs-wallet/primitives': 1.0.5 + '@evervault/wasm-attestation-bindings': 0.3.1 + '@noble/hashes': 2.2.0 + eventemitter3: 5.0.4 + fp-ts: 2.16.11 + isows: 1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + ws: 8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@dynamic-labs-wallet/forward-mpc-shared@0.7.0(@dynamic-labs-wallet/primitives@1.0.5)': + dependencies: + '@dynamic-labs-wallet/primitives': 1.0.5 + '@noble/ciphers': 0.4.1 + '@noble/hashes': 2.2.0 + '@noble/post-quantum': 0.5.4 + fp-ts: 2.16.11 + io-ts: 2.2.22(fp-ts@2.16.11) + + '@dynamic-labs-wallet/node-svm@1.0.5(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)': + dependencies: + '@dynamic-labs-wallet/node': 1.0.5(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - bufferutil + - debug + - encoding + - typescript + - utf-8-validate + + '@dynamic-labs-wallet/node@1.0.5(bufferutil@4.1.0)(utf-8-validate@6.0.6)': + dependencies: + '@dynamic-labs-wallet/core': 1.0.5(@dynamic-labs-wallet/forward-mpc-client@0.10.0(@dynamic-labs-wallet/primitives@1.0.5)(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@dynamic-labs-wallet/forward-mpc-client': 0.10.0(@dynamic-labs-wallet/primitives@1.0.5)(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@dynamic-labs-wallet/primitives': 1.0.5 + '@dynamic-labs/logger': 4.84.1 + '@dynamic-labs/sdk-api-core': 0.0.984 + '@noble/hashes': 1.7.1 + uuid: 11.1.0 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + '@dynamic-labs-wallet/primitives@1.0.5': {} + + '@dynamic-labs/logger@4.84.1': + dependencies: + eventemitter3: 5.0.1 + + '@dynamic-labs/sdk-api-core@0.0.984': {} + + '@evervault/wasm-attestation-bindings@0.3.1': {} + + '@noble/ciphers@0.4.1': {} + + '@noble/curves@1.9.7': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/curves@2.0.1': + dependencies: + '@noble/hashes': 2.0.1 + + '@noble/hashes@1.7.1': {} + + '@noble/hashes@1.8.0': {} + + '@noble/hashes@2.0.1': {} + + '@noble/hashes@2.2.0': {} + + '@noble/post-quantum@0.5.4': + dependencies: + '@noble/curves': 2.0.1 + '@noble/hashes': 2.0.1 + + '@solana-program/system@0.12.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))': + dependencies: + '@solana/kit': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + + '@solana-program/token-2022@0.9.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))(@solana/sysvars@6.9.0(typescript@6.0.3))': + dependencies: + '@solana/kit': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana/sysvars': 6.9.0(typescript@6.0.3) + + '@solana-program/token@0.13.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))': + dependencies: + '@solana-program/system': 0.12.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)) + '@solana/kit': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + + '@solana/accounts@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/addresses@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/assertions': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/nominal-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/assertions@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/buffer-layout@4.0.1': + dependencies: + buffer: 6.0.3 + + '@solana/codecs-core@2.3.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 2.3.0(typescript@6.0.3) + typescript: 6.0.3 + + '@solana/codecs-core@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/codecs-data-structures@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/codecs-numbers@2.3.0(typescript@6.0.3)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@6.0.3) + '@solana/errors': 2.3.0(typescript@6.0.3) + typescript: 6.0.3 + + '@solana/codecs-numbers@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/codecs-strings@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/codecs@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-data-structures': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/fixed-points': 6.9.0(typescript@6.0.3) + '@solana/options': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/errors@2.3.0(typescript@6.0.3)': + dependencies: + chalk: 5.6.2 + commander: 14.0.3 + typescript: 6.0.3 + + '@solana/errors@6.9.0(typescript@6.0.3)': + dependencies: + chalk: 5.6.2 + commander: 14.0.3 + optionalDependencies: + typescript: 6.0.3 + + '@solana/fast-stable-stringify@6.9.0(typescript@6.0.3)': + optionalDependencies: + typescript: 6.0.3 + + '@solana/fixed-points@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/functional@6.9.0(typescript@6.0.3)': + optionalDependencies: + typescript: 6.0.3 + + '@solana/instruction-plans@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/instructions': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/promises': 6.9.0(typescript@6.0.3) + '@solana/transaction-messages': 6.9.0(typescript@6.0.3) + '@solana/transactions': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/instructions@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/keys@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/assertions': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/nominal-types': 6.9.0(typescript@6.0.3) + '@solana/promises': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/kit-plugin-instruction-plan@0.10.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))': + dependencies: + '@solana/kit': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + + '@solana/kit-plugin-rpc@0.11.1(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))': + dependencies: + '@solana/kit': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana/kit-plugin-instruction-plan': 0.10.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)) + + '@solana/kit-plugin-signer@0.10.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))': + dependencies: + '@solana/kit': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + + '@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)': + dependencies: + '@solana/accounts': 6.9.0(typescript@6.0.3) + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/functional': 6.9.0(typescript@6.0.3) + '@solana/instruction-plans': 6.9.0(typescript@6.0.3) + '@solana/instructions': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/offchain-messages': 6.9.0(typescript@6.0.3) + '@solana/plugin-core': 6.9.0(typescript@6.0.3) + '@solana/plugin-interfaces': 6.9.0(typescript@6.0.3) + '@solana/program-client-core': 6.9.0(typescript@6.0.3) + '@solana/programs': 6.9.0(typescript@6.0.3) + '@solana/rpc': 6.9.0(typescript@6.0.3) + '@solana/rpc-api': 6.9.0(typescript@6.0.3) + '@solana/rpc-parsed-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-subscriptions': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + '@solana/signers': 6.9.0(typescript@6.0.3) + '@solana/subscribable': 6.9.0(typescript@6.0.3) + '@solana/sysvars': 6.9.0(typescript@6.0.3) + '@solana/transaction-confirmation': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana/transaction-messages': 6.9.0(typescript@6.0.3) + '@solana/transactions': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - bufferutil + - fastestsmallesttextencoderdecoder + - utf-8-validate + + '@solana/nominal-types@6.9.0(typescript@6.0.3)': + optionalDependencies: + typescript: 6.0.3 + + '@solana/offchain-messages@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-data-structures': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/nominal-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/options@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-data-structures': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/plugin-core@6.9.0(typescript@6.0.3)': + optionalDependencies: + typescript: 6.0.3 + + '@solana/plugin-interfaces@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/instruction-plans': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec': 6.9.0(typescript@6.0.3) + '@solana/rpc-subscriptions-spec': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + '@solana/signers': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/program-client-core@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/accounts': 6.9.0(typescript@6.0.3) + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/instruction-plans': 6.9.0(typescript@6.0.3) + '@solana/instructions': 6.9.0(typescript@6.0.3) + '@solana/plugin-interfaces': 6.9.0(typescript@6.0.3) + '@solana/rpc-api': 6.9.0(typescript@6.0.3) + '@solana/signers': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/programs@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/promises@6.9.0(typescript@6.0.3)': + optionalDependencies: + typescript: 6.0.3 + + '@solana/rpc-api@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/rpc-parsed-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec': 6.9.0(typescript@6.0.3) + '@solana/rpc-transformers': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + '@solana/transaction-messages': 6.9.0(typescript@6.0.3) + '@solana/transactions': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-parsed-types@6.9.0(typescript@6.0.3)': + optionalDependencies: + typescript: 6.0.3 + + '@solana/rpc-spec-types@6.9.0(typescript@6.0.3)': + optionalDependencies: + typescript: 6.0.3 + + '@solana/rpc-spec@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/rpc-subscriptions-api@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/rpc-subscriptions-spec': 6.9.0(typescript@6.0.3) + '@solana/rpc-transformers': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + '@solana/transaction-messages': 6.9.0(typescript@6.0.3) + '@solana/transactions': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-subscriptions-channel-websocket@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/functional': 6.9.0(typescript@6.0.3) + '@solana/rpc-subscriptions-spec': 6.9.0(typescript@6.0.3) + '@solana/subscribable': 6.9.0(typescript@6.0.3) + ws: 8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@solana/rpc-subscriptions-spec@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/promises': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec-types': 6.9.0(typescript@6.0.3) + '@solana/subscribable': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/rpc-subscriptions@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/fast-stable-stringify': 6.9.0(typescript@6.0.3) + '@solana/functional': 6.9.0(typescript@6.0.3) + '@solana/promises': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-subscriptions-api': 6.9.0(typescript@6.0.3) + '@solana/rpc-subscriptions-channel-websocket': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana/rpc-subscriptions-spec': 6.9.0(typescript@6.0.3) + '@solana/rpc-transformers': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + '@solana/subscribable': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - bufferutil + - fastestsmallesttextencoderdecoder + - utf-8-validate + + '@solana/rpc-transformers@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/functional': 6.9.0(typescript@6.0.3) + '@solana/nominal-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-transport-http@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec-types': 6.9.0(typescript@6.0.3) + undici-types: 8.2.0 + optionalDependencies: + typescript: 6.0.3 + + '@solana/rpc-types@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/fixed-points': 6.9.0(typescript@6.0.3) + '@solana/nominal-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/fast-stable-stringify': 6.9.0(typescript@6.0.3) + '@solana/functional': 6.9.0(typescript@6.0.3) + '@solana/rpc-api': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec': 6.9.0(typescript@6.0.3) + '@solana/rpc-spec-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-transformers': 6.9.0(typescript@6.0.3) + '@solana/rpc-transport-http': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/signers@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/instructions': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/nominal-types': 6.9.0(typescript@6.0.3) + '@solana/offchain-messages': 6.9.0(typescript@6.0.3) + '@solana/transaction-messages': 6.9.0(typescript@6.0.3) + '@solana/transactions': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/subscribable@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/errors': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + + '@solana/subscriptions@0.4.0-rc.2(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))(@solana/sysvars@6.9.0(typescript@6.0.3))(typescript@6.0.3)': + dependencies: + '@solana-program/token': 0.13.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)) + '@solana-program/token-2022': 0.9.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6))(@solana/sysvars@6.9.0(typescript@6.0.3)) + '@solana/kit': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana/kit-plugin-rpc': 0.11.1(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)) + '@solana/kit-plugin-signer': 0.10.0(@solana/kit@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)) + '@solana/program-client-core': 6.9.0(typescript@6.0.3) + transitivePeerDependencies: + - '@solana/sysvars' + - fastestsmallesttextencoderdecoder + - typescript + + '@solana/sysvars@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/accounts': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-data-structures': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/transaction-confirmation@6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/promises': 6.9.0(typescript@6.0.3) + '@solana/rpc': 6.9.0(typescript@6.0.3) + '@solana/rpc-subscriptions': 6.9.0(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + '@solana/transaction-messages': 6.9.0(typescript@6.0.3) + '@solana/transactions': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - bufferutil + - fastestsmallesttextencoderdecoder + - utf-8-validate + + '@solana/transaction-messages@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-data-structures': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/functional': 6.9.0(typescript@6.0.3) + '@solana/instructions': 6.9.0(typescript@6.0.3) + '@solana/nominal-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/transactions@6.9.0(typescript@6.0.3)': + dependencies: + '@solana/addresses': 6.9.0(typescript@6.0.3) + '@solana/codecs-core': 6.9.0(typescript@6.0.3) + '@solana/codecs-data-structures': 6.9.0(typescript@6.0.3) + '@solana/codecs-numbers': 6.9.0(typescript@6.0.3) + '@solana/codecs-strings': 6.9.0(typescript@6.0.3) + '@solana/errors': 6.9.0(typescript@6.0.3) + '@solana/functional': 6.9.0(typescript@6.0.3) + '@solana/instructions': 6.9.0(typescript@6.0.3) + '@solana/keys': 6.9.0(typescript@6.0.3) + '@solana/nominal-types': 6.9.0(typescript@6.0.3) + '@solana/rpc-types': 6.9.0(typescript@6.0.3) + '@solana/transaction-messages': 6.9.0(typescript@6.0.3) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@6.0.3)(utf-8-validate@6.0.6)': + dependencies: + '@babel/runtime': 7.29.2 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@solana/buffer-layout': 4.0.1 + '@solana/codecs-numbers': 2.3.0(typescript@6.0.3) + agentkeepalive: 4.6.0 + bn.js: 5.2.3 + borsh: 0.7.0 + bs58: 4.0.1 + buffer: 6.0.3 + fast-stable-stringify: 1.0.0 + jayson: 4.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + node-fetch: 2.7.0 + rpc-websockets: 9.3.8 + superstruct: 2.0.2 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + + '@swc/helpers@0.5.21': + dependencies: + tslib: 2.8.1 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 12.20.55 + + '@types/node@12.20.55': {} + + '@types/uuid@10.0.0': {} + + '@types/ws@7.4.7': + dependencies: + '@types/node': 12.20.55 + + '@types/ws@8.18.1': + dependencies: + '@types/node': 12.20.55 + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + asynckit@0.4.0: {} + + axios@1.15.2: + dependencies: + follow-redirects: 1.16.0 + form-data: 4.0.5 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + + base-x@3.0.11: + dependencies: + safe-buffer: 5.2.1 + + base64-js@1.5.1: {} + + bn.js@5.2.3: {} + + borsh@0.7.0: + dependencies: + bn.js: 5.2.3 + bs58: 4.0.1 + text-encoding-utf-8: 1.0.2 + + bs58@4.0.1: + dependencies: + base-x: 3.0.11 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bufferutil@4.1.0: + dependencies: + node-gyp-build: 4.8.4 + optional: true + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + chalk@5.6.2: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@14.0.3: {} + + commander@2.20.3: {} + + delay@5.0.0: {} + + delayed-stream@1.0.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.3 + + es6-promise@4.2.8: {} + + es6-promisify@5.0.0: + dependencies: + es6-promise: 4.2.8 + + eventemitter3@5.0.1: {} + + eventemitter3@5.0.4: {} + + eyes@0.1.8: {} + + fast-stable-stringify@1.0.0: {} + + follow-redirects@1.16.0: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.3 + mime-types: 2.1.35 + + fp-ts@2.16.11: {} + + function-bind@1.1.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.3 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + gopd@1.2.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.3: + dependencies: + function-bind: 1.1.2 + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + ieee754@1.2.1: {} + + io-ts@2.2.22(fp-ts@2.16.11): + dependencies: + fp-ts: 2.16.11 + + isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6)): + dependencies: + ws: 7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6) + + isows@1.0.7(ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)): + dependencies: + ws: 8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + + jayson@4.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + dependencies: + '@types/connect': 3.4.38 + '@types/node': 12.20.55 + '@types/ws': 7.4.7 + commander: 2.20.3 + delay: 5.0.0 + es6-promisify: 5.0.0 + eyes: 0.1.8 + isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + json-stringify-safe: 5.0.1 + stream-json: 1.9.1 + uuid: 8.3.2 + ws: 7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + json-stringify-safe@5.0.1: {} + + math-intrinsics@1.1.0: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + ms@2.1.3: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build@4.8.4: + optional: true + + proxy-from-env@2.1.0: {} + + rpc-websockets@9.3.8: + dependencies: + '@swc/helpers': 0.5.21 + '@types/uuid': 10.0.0 + '@types/ws': 8.18.1 + buffer: 6.0.3 + eventemitter3: 5.0.4 + uuid: 11.1.0 + ws: 8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6) + optionalDependencies: + bufferutil: 4.1.0 + utf-8-validate: 6.0.6 + + safe-buffer@5.2.1: {} + + stream-chain@2.2.5: {} + + stream-json@1.9.1: + dependencies: + stream-chain: 2.2.5 + + superstruct@2.0.2: {} + + text-encoding-utf-8@1.0.2: {} + + tr46@0.0.3: {} + + tslib@2.8.1: {} + + typescript@6.0.3: {} + + undici-types@8.2.0: {} + + utf-8-validate@6.0.6: + dependencies: + node-gyp-build: 4.8.4 + optional: true + + uuid@11.1.0: {} + + uuid@8.3.2: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@6.0.6): + optionalDependencies: + bufferutil: 4.1.0 + utf-8-validate: 6.0.6 + + ws@8.20.1(bufferutil@4.1.0)(utf-8-validate@6.0.6): + optionalDependencies: + bufferutil: 4.1.0 + utf-8-validate: 6.0.6 diff --git a/subscriptions-skill.mjs b/subscriptions-skill.mjs index 064349a..13dbb8c 100644 --- a/subscriptions-skill.mjs +++ b/subscriptions-skill.mjs @@ -37,6 +37,14 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; import { resolve, dirname } from "node:path"; import { fileURLToPath } from "node:url"; +import { + randomBytes, + pbkdf2Sync, + createCipheriv, + createDecipheriv, +} from "node:crypto"; +import { execFileSync } from "node:child_process"; +import { createInterface } from "node:readline"; import { address, @@ -107,7 +115,226 @@ function writeEnv(key, value) { process.env[key] = value; } +// Blank a key's value in .env (used when moving a secret into the keychain so it +// no longer also sits in the file). Leaves the key line for documentation. +function blankEnv(key) { + if (!existsSync(ENV_PATH)) return; + const content = readFileSync(ENV_PATH, "utf-8"); + const re = new RegExp(`^${key}=.*$`, "m"); + if (re.test(content)) { + writeFileSync(ENV_PATH, content.replace(re, `${key}=`), "utf-8"); + } +} + +// ── OS keychain (macOS) for sensitive secrets ──────────────────────────────── +// +// At-rest secrets — API token, key share, backup password — are kept in the macOS +// login Keychain rather than .env, so no single file holds enough to recover/sign. +// Reads transparently fall back to process.env / .env (shell overrides, non-macOS). +// +// SUBS_KEYSTORE_PASSPHRASE is deliberately NOT in this list: it is the key that +// decrypts the share and is kept in a *separate* trust domain — supplied per +// session (env export) or prompted interactively — so a Keychain compromise alone +// cannot decrypt the share. + +const KEYCHAIN_SERVICE = "dynamic-subscriptions-skill"; +const MANAGED_SECRETS = [ + "DYNAMIC_AUTH_TOKEN", + "SOL_WALLET_KEY_SHARES", + "WALLET_BACKUP_PASSWORD", +]; + +function keychainAvailable() { + if (process.platform !== "darwin") return false; + try { + execFileSync("security", ["help"], { stdio: "ignore" }); + return true; + } catch { + return false; + } +} + +function keychainGet(name) { + if (process.platform !== "darwin") return undefined; + try { + const out = execFileSync( + "security", + ["find-generic-password", "-s", KEYCHAIN_SERVICE, "-a", name, "-w"], + { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }, + ).replace(/\n$/, ""); + return out.length ? out : undefined; + } catch { + return undefined; // item not found + } +} + +function keychainSet(name, value) { + // -U updates an existing item. NOTE: the value is passed as an argv to + // `security`, briefly visible to the same user via `ps`. Acceptable for a local + // CLI; the goal is to keep it out of files, not to hide it from your own root. + execFileSync( + "security", + ["add-generic-password", "-s", KEYCHAIN_SERVICE, "-a", name, "-w", value, "-U"], + { stdio: "ignore" }, + ); +} + +// After .env is loaded, fill any still-missing managed secret from the keychain. +// Runs before the config consts below so DYNAMIC_AUTH_TOKEN etc. resolve. +function hydrateSecretsFromKeychain() { + if (process.platform !== "darwin") return; + for (const name of MANAGED_SECRETS) { + if (!process.env[name]?.trim()) { + const v = keychainGet(name); + if (v) process.env[name] = v; + } + } +} + +// Persist a sensitive value: keychain when available (and clear it from .env so +// it isn't co-located), otherwise fall back to .env. +function writeSecret(name, value) { + if (keychainAvailable()) { + keychainSet(name, value); + blankEnv(name); + process.env[name] = value; + } else { + writeEnv(name, value); + } +} + loadEnv(); +hydrateSecretsFromKeychain(); + +// ── key-share encryption at rest ──────────────────────────────────────────── +// +// SOL_WALLET_KEY_SHARES is the client-side MPC key share for the wallet — secret +// material that must be recoverable to sign, so it is *encrypted* (not hashed) +// at rest with AES-256-GCM. The key is derived from a passphrase supplied at +// runtime via SUBS_KEYSTORE_PASSPHRASE, which is deliberately NOT persisted to +// .env: anyone who reads .env then sees only ciphertext, not the password. +// +// Stored format (single line, ':'-delimited, all parts base64): +// enc:v1:::: +// Legacy plaintext JSON shares are still read transparently for back-compat. + +const KEYSTORE_PREFIX = "enc:v1:"; +// PBKDF2-SHA256 per Fireblocks crypto policy; 600k iterations (OWASP-recommended +// floor for PBKDF2-HMAC-SHA256, well above the 100k minimum). +const PBKDF2_ITERATIONS = 600_000; +const PBKDF2_DIGEST = "sha256"; +const KEY_LEN = 32; // AES-256 +const SALT_LEN = 16; +const IV_LEN = 12; // 96-bit nonce, the GCM standard + +// ── per-session keystore passphrase ────────────────────────────────────────── +// The passphrase that decrypts the key share is never stored. It comes from +// SUBS_KEYSTORE_PASSPHRASE (export it per session) or an interactive hidden prompt. + +function envPassphrase() { + const p = process.env.SUBS_KEYSTORE_PASSPHRASE; + return p && p.trim() ? p : undefined; +} + +// Read a line from the TTY without echoing it. Rejects if there's no TTY (e.g. +// running unattended) so the caller can tell the user to export the env var. +function promptHidden(label) { + return new Promise((resolve, reject) => { + if (!process.stdin.isTTY) { + reject( + new Error( + "key share is encrypted — set SUBS_KEYSTORE_PASSPHRASE for this session " + + "(export it), or run in an interactive terminal.", + ), + ); + return; + } + const rl = createInterface({ input: process.stdin, output: process.stdout }); + process.stdout.write(label); + rl._writeToOutput = () => {}; // mute typed characters + rl.question("", (answer) => { + rl.close(); + process.stdout.write("\n"); + resolve(answer); + }); + }); +} + +// Passphrase to DECRYPT an existing encrypted share. +async function decryptionPassphrase() { + return envPassphrase() ?? (await promptHidden("Keystore passphrase: ")); +} + +// Passphrase to CREATE/encrypt a share. Env wins; otherwise prompt+confirm on a +// TTY; otherwise undefined (caller stores the share unencrypted). +async function newKeystorePassphrase() { + const env = envPassphrase(); + if (env) return env; + if (!process.stdin.isTTY) return undefined; + const p1 = await promptHidden("Set a keystore passphrase (blank = no encryption): "); + if (!p1.trim()) return undefined; + const p2 = await promptHidden("Confirm passphrase: "); + if (p1 !== p2) throw new Error("passphrases did not match — re-run."); + return p1; +} + +function isEncryptedShare(value) { + return typeof value === "string" && value.startsWith(KEYSTORE_PREFIX); +} + +/** Encrypt a plaintext string into the `enc:v1:…` envelope. */ +function encryptSecret(plaintext, passphrase) { + const salt = randomBytes(SALT_LEN); + const iv = randomBytes(IV_LEN); // unique per encryption — never reused + const key = pbkdf2Sync( + passphrase, + salt, + PBKDF2_ITERATIONS, + KEY_LEN, + PBKDF2_DIGEST, + ); + const cipher = createCipheriv("aes-256-gcm", key, iv); + const ciphertext = Buffer.concat([ + cipher.update(plaintext, "utf-8"), + cipher.final(), + ]); + const tag = cipher.getAuthTag(); + return ( + KEYSTORE_PREFIX + + [salt, iv, tag, ciphertext].map((b) => b.toString("base64")).join(":") + ); +} + +/** Decrypt an `enc:v1:…` envelope; throws on a wrong passphrase or tampering. */ +function decryptSecret(blob, passphrase) { + const parts = blob.slice(KEYSTORE_PREFIX.length).split(":"); + if (parts.length !== 4) { + throw new Error("encrypted key shares are malformed (bad envelope)."); + } + const [salt, iv, tag, ciphertext] = parts.map((p) => + Buffer.from(p, "base64"), + ); + const key = pbkdf2Sync( + passphrase, + salt, + PBKDF2_ITERATIONS, + KEY_LEN, + PBKDF2_DIGEST, + ); + const decipher = createDecipheriv("aes-256-gcm", key, iv); + decipher.setAuthTag(tag); + try { + return Buffer.concat([ + decipher.update(ciphertext), + decipher.final(), + ]).toString("utf-8"); + } catch { + // GCM auth failure: wrong passphrase or corrupted/altered ciphertext. + throw new Error( + "could not decrypt key shares — wrong SUBS_KEYSTORE_PASSPHRASE or the data was altered.", + ); + } +} // ── config ──────────────────────────────────────────────────────────────────── const BASE_URL = "https://app.dynamicauth.com/api/v0"; @@ -159,20 +386,29 @@ async function ensureWallet() { } const addr = process.env.SOL_WALLET_ADDRESS; - const sharesJson = process.env.SOL_WALLET_KEY_SHARES; - if (!addr || !sharesJson) { + const storedShares = process.env.SOL_WALLET_KEY_SHARES; + if (!addr || !storedShares) { console.error( "✗ Wallet setup did not complete. Check your credentials and re-run `setup`.", ); process.exit(1); } + + let sharesJson = storedShares; + if (isEncryptedShare(storedShares)) { + try { + sharesJson = decryptSecret(storedShares, await decryptionPassphrase()); + } catch (err) { + console.error(`✗ ${err.message}`); + process.exit(1); + } + } + let externalServerKeyShares; try { externalServerKeyShares = JSON.parse(sharesJson); } catch { - console.error( - "✗ SOL_WALLET_KEY_SHARES in .env is not valid JSON. Re-run `setup`.", - ); + console.error("✗ SOL_WALLET_KEY_SHARES is not valid JSON. Re-run `setup`."); process.exit(1); } return { address: addr, externalServerKeyShares }; @@ -406,24 +642,84 @@ async function cmdSetup() { return; } + // Resolve the backup password. With backUpToDynamic, Dynamic stores a copy of + // the key share encrypted under this password — the recovery path if the local + // share is lost. The SDK requires a non-empty password that differs from the + // environment ID. Auto-generate a strong one if the user hasn't pinned theirs. + let backupPassword = process.env.WALLET_BACKUP_PASSWORD?.trim(); + let generatedPassword = false; + if (!backupPassword) { + backupPassword = randomBytes(24).toString("base64url"); // ~192-bit + writeSecret("WALLET_BACKUP_PASSWORD", backupPassword); + generatedPassword = true; + } + if (backupPassword === ENV_ID) { + console.error( + "✗ WALLET_BACKUP_PASSWORD must not equal your DYNAMIC_ENVIRONMENT_ID.\n" + + " Pick a different value in .env and re-run `setup`.", + ); + process.exit(1); + } + console.log("Creating Dynamic WaaS Solana wallet…"); const client = await getSvmClient(); const result = await client.createWalletAccount({ thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO, + backUpToDynamic: true, + password: backupPassword, }); const accountAddress = result.walletMetadata.accountAddress; writeEnv("SOL_WALLET_ADDRESS", accountAddress); - writeEnv( + + const sharesJson = JSON.stringify(result.externalServerKeyShares); + let passphrase; + try { + passphrase = await newKeystorePassphrase(); + } catch (err) { + console.error(`✗ ${err.message}`); + process.exit(1); + } + writeSecret( "SOL_WALLET_KEY_SHARES", - JSON.stringify(result.externalServerKeyShares), + passphrase ? encryptSecret(sharesJson, passphrase) : sharesJson, ); + const inKeychain = keychainAvailable(); + const sharesLocation = inKeychain ? "the macOS Keychain" : ".env"; console.log(`✓ Wallet created: ${accountAddress}`); console.log(""); + if (passphrase) { + console.log( + `🔐 Key share encrypted (AES-256-GCM with SUBS_KEYSTORE_PASSPHRASE) and stored in ${sharesLocation}.\n` + + " Keep that passphrase safe — without it the share cannot be decrypted.", + ); + } else { + console.log( + `⚠ Key share stored in ${sharesLocation} UNENCRYPTED — no SUBS_KEYSTORE_PASSPHRASE set.\n` + + " To encrypt it, export a passphrase and run `encrypt-shares`:\n" + + " export SUBS_KEYSTORE_PASSPHRASE='…' && pnpm subs encrypt-shares", + ); + } + console.log(""); console.log( - "⚠ Key shares written to .env — keep this file secure and never commit it.", + "🛟 Key share backed up to Dynamic (encrypted with WALLET_BACKUP_PASSWORD) —\n" + + " recoverable if you lose the local share.", ); + if (generatedPassword) { + console.log( + `⚠ A random WALLET_BACKUP_PASSWORD was generated and stored in ${sharesLocation}.\n` + + " BACK IT UP somewhere safe (e.g. a password manager): without it the\n" + + " Dynamic backup cannot be decrypted and recovery is impossible.", + ); + } + if (inKeychain) { + console.log(""); + console.log( + `🔑 Sensitive values are stored in the macOS Keychain (service "${KEYCHAIN_SERVICE}"),\n` + + " not in .env. Run `pnpm subs secrets` to see what lives where.", + ); + } console.log(""); console.log("Next steps:"); console.log( @@ -434,6 +730,101 @@ async function cmdSetup() { console.log(` 3. Run: pnpm subs list-plans `); } +/** + * Encrypt a currently-unencrypted key share with a per-session passphrase. Use + * this if you created the wallet without one. The passphrase is never stored. + */ +async function cmdEncryptShares() { + const stored = process.env.SOL_WALLET_KEY_SHARES; + if (!stored) { + console.error("✗ No SOL_WALLET_KEY_SHARES found. Run `setup` first."); + process.exit(1); + } + if (isEncryptedShare(stored)) { + console.log("✓ Key share is already encrypted."); + return; + } + try { + JSON.parse(stored); + } catch { + console.error("✗ SOL_WALLET_KEY_SHARES is not valid JSON; refusing to encrypt."); + process.exit(1); + } + + let passphrase; + try { + passphrase = await newKeystorePassphrase(); + } catch (err) { + console.error(`✗ ${err.message}`); + process.exit(1); + } + if (!passphrase) { + console.error("✗ No passphrase provided — nothing changed."); + process.exit(1); + } + + writeSecret("SOL_WALLET_KEY_SHARES", encryptSecret(stored, passphrase)); + const loc = keychainAvailable() ? "the macOS Keychain" : ".env"; + console.log( + `🔐 Key share encrypted (AES-256-GCM) and stored in ${loc}.\n` + + " Provide SUBS_KEYSTORE_PASSPHRASE each session to sign.", + ); +} + +/** + * Move sensitive secrets out of .env into the macOS Keychain, and show where + * each secret currently lives. After migration .env holds only non-sensitive + * config, so a leaked .env no longer contains anything that can sign or decrypt. + */ +async function cmdSecrets() { + if (!keychainAvailable()) { + console.error( + "✗ macOS Keychain not available (needs the `security` CLI on macOS).\n" + + " On other platforms, keep secrets in environment variables / a secrets manager.", + ); + process.exit(1); + } + + // Migrate any managed secret still sitting in .env into the keychain. + const raw = existsSync(ENV_PATH) ? readFileSync(ENV_PATH, "utf-8") : ""; + const moved = []; + for (const name of MANAGED_SECRETS) { + const m = raw.match(new RegExp(`^${name}=(.+)$`, "m")); + const val = m?.[1]?.trim(); + if (val) { + keychainSet(name, val); + blankEnv(name); + moved.push(name); + } + } + + if (moved.length) { + console.log(`🔑 Moved ${moved.length} secret(s) from .env → Keychain:`); + for (const n of moved) console.log(` • ${n}`); + console.log(""); + } else { + console.log("✓ No plaintext secrets found in .env to migrate.\n"); + } + + console.log(`Secret locations (Keychain service "${KEYCHAIN_SERVICE}"):`); + for (const name of MANAGED_SECRETS) { + const inKc = Boolean(keychainGet(name)); + const inEnvFile = + new RegExp(`^${name}=.+$`, "m").test(raw) && !moved.includes(name); + const where = inKc + ? "🔑 Keychain" + : inEnvFile + ? "📄 .env (plaintext)" + : "— not set"; + console.log(` ${name.padEnd(26)} ${where}`); + } + console.log(""); + console.log( + "Tip: these are read automatically at runtime. To override per-session,\n" + + "export the variable in your shell — that takes precedence over the Keychain.", + ); +} + async function cmdBalance() { const wallet = await ensureWallet(); const rpc = createSolanaRpc(RPC_URL); @@ -741,7 +1132,7 @@ async function cmdSunsetPlan(planPda, endInMinutes) { "Setting plan to Sunset (no new subscriptions; existing ones honored)…", ); console.log(` ends at: ${new Date(Number(endTs) * 1000).toISOString()}`); - const ix = getUpdatePlanOverlayInstruction({ + const ix = await getUpdatePlanOverlayInstruction({ owner: createNoopSigner(address(wallet.address)), planPda: address(planPda), endTs, @@ -852,12 +1243,16 @@ async function cmdSubscribe(merchantAddress, planIndex) { const tokenMint = address(TOKEN_MINT); const instructions = []; - // Init SubscriptionAuthority if this is the first subscription for this wallet + // Init SubscriptionAuthority if this is the first subscription for this wallet. + // rc.1 requires expectedSubscriptionAuthorityInitId in the subscribe instruction, + // which must match the authority's on-chain initId. Since we can't read state we + // just wrote in the same tx, we send init as a separate tx first, then fetch the + // resulting initId before building the subscribe instruction. const [authorityPda] = await findSubscriptionAuthorityPda({ tokenMint, user: userAddr, }); - const maybeAuth = await fetchMaybeSubscriptionAuthority(rpc, authorityPda); + let maybeAuth = await fetchMaybeSubscriptionAuthority(rpc, authorityPda); if (!maybeAuth.exists) { console.log(" Initializing subscription authority…"); const [userAta] = await findAssociatedTokenPda({ @@ -865,15 +1260,22 @@ async function cmdSubscribe(merchantAddress, planIndex) { owner: userAddr, tokenProgram: TOKEN_PROGRAM_ADDRESS, }); - instructions.push( - await getInitSubscriptionAuthorityOverlayInstructionAsync({ - owner: noopSigner, - tokenMint, - tokenProgram: TOKEN_PROGRAM_ADDRESS, - userAta, - }), + await sendKitInstructions( + [ + await getInitSubscriptionAuthorityOverlayInstructionAsync({ + owner: noopSigner, + tokenMint, + tokenProgram: TOKEN_PROGRAM_ADDRESS, + userAta, + }), + ], + wallet.address, + wallet.externalServerKeyShares, ); + maybeAuth = await fetchMaybeSubscriptionAuthority(rpc, authorityPda); + if (!maybeAuth.exists) throw new Error("subscription authority init did not land"); } + const expectedSubscriptionAuthorityInitId = maybeAuth.data.initId; instructions.push( await getSubscribeOverlayInstructionAsync({ @@ -884,6 +1286,7 @@ async function cmdSubscribe(merchantAddress, planIndex) { expectedAmount: plan.data.data.terms.amount, expectedCreatedAt: plan.data.data.terms.createdAt, expectedPeriodHours: plan.data.data.terms.periodHours, + expectedSubscriptionAuthorityInitId, }), ); @@ -1087,6 +1490,31 @@ async function cmdCollect(planPda, subPda, delegatorAddr, amountTokens) { console.log(`✓ Collected! tx: ${sig}`); } +function cmdNetwork(networkName) { + const NETWORKS = { + devnet: "https://api.devnet.solana.com", + mainnet: "https://api.mainnet-beta.solana.com", + "mainnet-beta": "https://api.mainnet-beta.solana.com", + }; + if (!networkName) { + const label = RPC_URL.includes("devnet") ? "devnet" : "mainnet"; + console.log(`Current network: ${label} (${RPC_URL})`); + console.log("Usage: pnpm subs network "); + return; + } + const url = NETWORKS[networkName.toLowerCase()]; + if (!url) { + console.error(`✗ Unknown network "${networkName}". Use: devnet or mainnet`); + process.exit(1); + } + writeEnv("SOLANA_RPC_URL", url); + const label = url.includes("devnet") ? "devnet" : "mainnet"; + console.log(`✓ Switched to ${label}: ${url}`); + if (label === "devnet") { + console.log(" Airdrop SOL: solana airdrop 2
--url devnet"); + } +} + // ── Entry point ─────────────────────────────────────────────────────────────── const [, , cmd, ...args] = process.argv; @@ -1097,7 +1525,10 @@ Dynamic Solana Subscriptions Skill Usage: pnpm subs [args] Commands: + network [devnet|mainnet] Show or switch the active Solana network (persists to .env) 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 locations balance Check SOL and USDC balance swap Swap SOL → USDC send [SOL|USDC|] Send SOL or a token @@ -1118,6 +1549,12 @@ try { case "setup": await cmdSetup(); break; + case "encrypt-shares": + await cmdEncryptShares(); + break; + case "secrets": + await cmdSecrets(); + break; case "balance": await cmdBalance(); break; @@ -1158,6 +1595,9 @@ try { case "delete-plan": await cmdDeletePlan(args[0]); break; + case "network": + cmdNetwork(args[0]); + break; default: console.log(USAGE); if (cmd) console.error(`\nUnknown command: ${cmd}`);