Repository navigation
Release v0.1.3 - #121
Open
Kevin-Chen0 wants to merge 23 commits into
Open
Release v0.1.3#121Kevin-Chen0 wants to merge 23 commits into
Kevin-Chen0 wants to merge 23 commits into
Conversation
CI asserts the declared version follows the release branch, so the branch opens with every version declaration at 0.1.3: package.json, the lockfile, the plugin's package.json and manifests, and the marketplace entry. The documentation's install pins stay on 0.1.2, the published version, until this cycle's release pull request moves them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
Dependabot opens against the default branch, and setting target-branch would exclude the config from security updates. A workflow now moves each Dependabot pull request to the newest release branch when it opens or is recreated, and moves the ones still open when a new release branch is cut. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
…ate a concurrent move Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
…t 2E) and (Test 2F) Both vaults are Morpho Vault V2 over USDC with 18-decimal shares, open to any account, and each is the default on its chain; Base stays the default chain. Every registry value was read on chain on 2026-10-11 and registry:check reconciles both rows through the public endpoints. Each chain reads only its own variables: TREASURY_RPC_ETHEREUM / ETHEREUM_RPC_URL / TREASURY_LOGS_RPC_ETHEREUM, falling back to ethereum.reth.rs, and TREASURY_RPC_MONAD / MONAD_RPC_URL / TREASURY_LOGS_RPC_MONAD, falling back to rpc.monad.xyz. Measured: the Ethereum endpoint serves 100,000-block eth_getLogs ranges and past state; Monad's serves 100 blocks per request, so a history scan there needs the logs variable, and the docs, the registry note and the scan's own message say so. The scan learns a provider's window from its error. The Ethereum endpoint words it "query exceeds max block range 100000", which was not recognised and would have failed every scan once the vault was older than the window; it is now read as a window. The earn skill lists all five chains when it asks, and says Ethereum gas is far higher before a small deposit there. Explorer links are Etherscan and MonadScan; the connect page accepts both chains. Refs #62 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
…ault Solana is not an EVM chain, so it is not a row of the chain table: a Solana vault is its own registry entry (`solanaVaults`, `family: "solana"`), read and built with @solana/kit, and every earn and connect command branches on the vault's family. Base stays the default chain. The kVault deposit and withdraw instructions and the VaultState and Reserve decoders are hand-written and pinned byte for byte to Kamino's own SDK by committed fixtures (vendor/kamino/, written by generate-fixtures.mjs from a committed mainnet snapshot); that SDK is not a dependency. What differs from EVM, by design: - A prepared deposit or withdrawal is ONE unsigned transaction that names a recent blockhash and expires in about a minute; it is simulated before it is returned. The connect page asks for it when the operator presses Confirm, so it is never stale there. - The receiver is always the account: the program mints shares to the signer and pays a withdrawal to the account whose shares burn. - Quotes and positions are read from simulated post-state. Measured on mainnet: each withdrawal keeps 0.001 USDC in the vault while the vault's own penalty settings read 0; `receives` is net of it. - No event history: entry basis and yield read unknown on Solana. connect: `connect wallet --chain solana` signs in a Solana wallet (ed25519, checked locally) and keeps it apart from the EVM connection. The acknowledgement covers the intent (account, vault, action, amount), and a gate admits only a transaction whose every instruction is a compute-unit limit, the account's own token-account creation, or this vault's deposit or withdrawal for the connected account. The page uses Privy's Solana wallets less WalletConnect, which this page does not ship, and Privy's own Solana RPC. registry:check reconciles the Solana row against the vault state; the live tier covers Solana when TREASURY_RPC_SOLANA is set. Refs #62, #64 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
…osed, gate pins the vault's PDAs
- ci.yml: `connect wallet` now takes `--chain`, so its pinned flag set is {"chain"}.
- The 0.001 USDC is Kamino's GLOBAL withdrawal penalty (the program's
global config holds withdrawalPenaltyLamports = 1000), not this vault's
setting, and Kamino can change it. Measured by simulation: it is charged
per withdraw instruction (2,000,000 shares kept 1,000 as one instruction,
1,929 as two), and a withdrawal worth 0.001 USDC or less is refused
(error 7049). Disclosed in the registry note, docs, risks, README, skill
and changelog; quotes stay exact because they are simulated.
- Kamino's program can require a co-signer on every deposit and every
withdrawal of a vault. Disclosed, and the builders now refuse while one
is set (unset today), with a test.
- Who can change the terms on Solana, with no timelock: the vault admin
(fees, the vault's own penalty) and the vault admin or Kamino's global
admin (crank fee, minimum amounts). Reserve liquidity limits each
withdrawal leg; said so.
- A leg asking for more than it can pay is capped, not reverted: the
landing check now calls that a partial withdrawal.
- The gate also pins the vault's token vault and authority PDAs and the
second vault state a withdrawal names, with tests; its header says what
stays with the program's own constraints.
- Wording: the approve/proxy note is EVM-only; `depositable` includes the
Kamino vault; compute numbers re-measured; stale counts in titles and
descriptions. Removes a scratch script committed by mistake.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
…e changelog's chain count Wording only: docs/tools.md now says what every other page says, and the Ethereum/Monad changelog entry no longer counts the chains. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
ci: keep Dependabot pull requests on the newest release branch
earn: Ethereum and Monad, with Cash Plus USDC (Test 2E) and (Test 2F)
The fork tier ran a deposit and redeem only against one vault on Base and one on Arbitrum One. It now round-trips every vault the registry marks depositable, on every EVM chain whose RPC variable is set: Base (Test 2 and Test 2B), Arbitrum One (2C), Robinhood Chain (2D, USDG), Ethereum (2E) and Monad (2F). The vault list comes from the registry, not the test, so a new vault is covered when it is added. Each chain gets an impersonated holder of its deposit asset (Morpho Blue on Ethereum; the largest recent holder on Monad and Robinhood Chain, probed 2026-10-11) and amounts use the asset's own decimals. The test logs which exit each vault took, so a quote that refused the full redeem cannot pass silently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
A deposit and withdrawal on the Solana vault now land for real, on a local Surfpool fork of mainnet-beta, through the transactions this package builds: - deposit through `earn prepare_deposit`, which the connect gate must also admit; - a partial withdrawal through the confirm page's builder (read, build, gate, simulate); - the rest through `earn prepare_withdraw` with the exact share string `earn balance` reports. Each is signed by a key generated for the run (funded on the fork only) and checked by `verifySolanaLanded`, which must report `matched`. The round trip's cost is bounded by Kamino's charge per withdraw instruction, counted from the transactions sent (2 USDC cost 0.001939 USDC over two withdraw instructions). `npm run test:fork` runs it when `TREASURY_RPC_SOLANA` is set and `surfpool` is on PATH. A send the fork refuses because its upstream dropped an account fetch is resent with the same signed bytes, at most three times. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
tests: fork round trip on every depositable EVM vault
Brings in the EVM fork round trips (#128). The one conflicting sentence, in AGENTS.md and CONTRIBUTING.md, now says the fork tier covers every chain: anvil for the EVM chains, Surfpool for Solana. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
A Kamino vault takes only the assets that back the shares it mints, so at some share prices a 2 USDC deposit debits 1,999,999 base units. The test asserted exact equality and failed there before any withdrawal ran. It now bounds the debit: never more than the amount, at most 10 units less. Also: a missing `surfpool` binary is reported by name instead of as an unhandled ENOENT, and AGENTS.md names Surfpool beside Foundry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
earn and connect on Solana, with Cash Plus USDC (Test 2G)
The registry and the package version were read from files beside the module at run time. A library re-bundled into another application looked for registry/vaults.json beside the consumer's own bundle and read whatever was there. src/registry.ts and src/version.ts now import registry/vaults.json and package.json with JSON import attributes, so tsup and a consumer's bundler inline them. treasury --version reports the version the bundle was built from, and a registry change now rebuilds the bundle. - The boundary audit allows exactly these two JSON imports, by importing file and specifier; any other JSON import, or either of these from another file, still fails. - The broken-registry tests build the CLI from source with the registry import pointed at a broken copy, instead of swapping a file beside the bundle. - New tests run the committed bundle alone in a folder, with decoy registry and package.json files beside it, and a consumer's re-bundle of dist/index.js with a decoy registry beside that. - The comments that described the run-time read are corrected. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
Importing package.json inlined its scripts and devDependencies into
dist/treasury.mjs, so a dev-only dependency bump (which Dependabot makes
without rebuilding) would have made the committed bundle stale.
tsup.config.ts now serves the root package.json to the bundler as
{ version }. The broken-registry test builds use the same plugin. A new
test checks the bundle carries no devDependency name and no script text.
The changelog notes the ExperimentalWarning that Node 22.0 to 22.11 print
when the library is imported.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
Importing package.json for its version inlined the whole manifest into
dist/treasury.mjs, scripts and devDependencies included, so any edit to
package.json (a dev-dependency bump) made the committed bundle stale and
failed the bundle check. An esbuild plugin in tsup.config.ts now serves
the root package.json to the bundle as { version } only.
A test holds the committed bundle to that: it contains the version, no
devDependencies, and no package.json script. Measured: a dev-dependency
and script edit leaves the bundle byte-identical; a version change still
reaches `treasury --version`.
The CHANGELOG also notes Node's ExperimentalWarning for JSON modules when
the library is imported unbundled on Node 22.0 to 22.11.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
Embed the registry and the version in the bundle (#107)
An agent that runs treasury without the plugin never sees the rules the Earn skill carries. Measured on 0.1.2, such an agent read a guide 0 times in 9 when it was only in the package, and 9 times in 9 when treasury --help named it; with the guide it showed all of the first-deposit terms instead of about a third. - llms.txt is built by scripts/llms-txt.ts from the Earn skill's body and the command descriptions that `--help` prints. The skill's text changes in four exact places (the plugin's launch line becomes the plain command, and the sentences about the plugin's permission prompt go); the script stops if the skill no longer contains them. - `treasury --help` and `treasury <skill> --help` carry a `guide` field: an instruction to read it first, the file's path when it sits beside the CLI, and the public URL. - npm run build writes it and copies it into plugin/; CI fails when the committed file differs from what the sources produce. It ships in the npm package. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
The plugin's Earn skill is the text llms.txt is built from and is already loaded, so a pointer in the plugin's --help sent every plugin user to re-read it. guidePointer() now returns nothing when the plugin's manifest sits beside the CLI's parent folder (Claude Code or Codex), and llms.txt is no longer copied into plugin/. A test runs the plugin copy's help at all three levels and a bundle laid out as either host's plugin. prepack also checks that llms.txt is committed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Kevin Chen <13785749+Kevin-Chen0@users.noreply.github.com>
Add a generated llms.txt and point to it from --help (#106)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release v0.1.3:
release/v0.1.3intomain. The cycle opens from the v0.1.2 release commit onmain(tagv0.1.2), with every version declaration at 0.1.3; the install pins stay on 0.1.2, the published version, until this pull request moves them before release.Pull requests for this cycle target
release/v0.1.3, notmain.In queue
docs/design-embed-registry-and-version.md).llms.txtfor agents that run the CLI without the plugin, named by--help.earnskill.connect-page/(chore(deps-dev): Bump typescript from 5.9.3 to 7.0.2 in /connect-page #118). With it, npm leaves out the@solana/*packages the Privy sign-in code imports, so the page does not build; it needs its own change.Longer-running
#62 (more chains), #64 (Solana design), #31 (delegated agent wallet), #80 (an MCP server alongside the CLI, on demand).
🤖 Generated with Claude Code