fix(anchor + api + web): real program ID, devnet target, BPF stack-frame fit#15
Merged
Merged
Conversation
…ame fit
The user clicked "Connect Phantom -> Create vault" on the live site
and got "tx confirmation timed out" + a signature that never landed
on-chain. Root cause: declare_id! was a sha256 placeholder
(5s9rscxc...) for which no Solana program was ever deployed. Phantom
signed, broadcast, mainnet validators rejected (program not found),
nothing confirmed, frontend timed out after 30s.
This PR makes deploy actually possible.
What changes:
programs/agent_vault/ Buildable for real
- Generated a real program keypair backing the on-chain ID:
56TbAziiW8pDHFpRsxfnfBUfimBRTMCHw4gwDGw9uPW6
(target/deploy/agent_vault-keypair.json — gitignored). declare_id!
+ Anchor.toml + every backend/frontend env var swapped to it.
- Boxed every Account<> in CreateVault, Spend, OwnerOnly,
OwnerClawback so the synthesized try_accounts function fits the
BPF 4 KB stack frame. Without this, build emitted:
Stack offset of 4376 exceeded max offset of 4096 by 280 bytes
(may cause undefined behavior during execution)
Boxing alone got us to 4120, still 24 over.
- Reduced MAX_ALLOWLIST from 8 to 4. Dropping the on-stack copy of
the [u8; 32; N] allowlist by 128 bytes brought the frame back
under 4 KB. Demo uses 1 entry; 4 covers realistic use; if we need
more later we'll restructure to keep the allowlist out of the
Args struct entirely (it's only the InitArgs path that's stack-
pressured, not Spend).
- api/routes/schemas.py:CreateVaultRequest max_length: 8 -> 4
- web/src/pages/VaultNew.vue: copy + validation: 8 -> 4
api/app.py Always init_models()
- The previous lifespan only ran create_all() for SQLite or
APP_ENV != production. On the K8s deploy we hit a 500 the first
time the user clicked "My vaults" because the vaults table didn't
exist (production Postgres + APP_ENV=production took the skip
branch). create_all is idempotent on Postgres (single pg_class
lookup for an existing schema), so just always run it. Production
hardening with Alembic comes later.
deploy/production/api.yaml Devnet, not mainnet
- SOLANA_CLUSTER: mainnet -> devnet
- SOLANA_RPC_URL: api.mainnet-beta.solana.com -> api.devnet.solana.com
- USDC_MINT: EPjFWdd5... -> 4zMMC9srt5... (Circle devnet)
- AGENT_VAULT_PROGRAM_ID: placeholder -> 56TbAziiW...
Mainnet program rent costs ~2.5 SOL (~$500). Devnet is the right
cluster for the demo. Switching back is a one-line change here +
a `solana program deploy` against mainnet.
Toolchain bootstrapped on the dev machine for future deploys:
brew install solana solana CLI 3.1.14
sh -c "$(curl -sSfL release.anza.xyz/...)" cargo-build-sbf
+ platform-tools v1.52
rustup --default-toolchain stable rust 1.95
Verification:
$ cargo build-sbf
Finished `release` profile (no stack warning)
$ cd api && PYTHONPATH=.. pytest tests/
35 passed in 0.57s
Deploy still pending — devnet airdrop is rate-limited from this IP
(default faucet is dry / capped). Next step: get 3 SOL into
A1ve4671xF3nAg7dMD9R3xXjVrtaTRMbAHHHTjrsP7rb via
https://faucet.solana.com, then:
solana program deploy target/deploy/agent_vault.so \
--program-id target/deploy/agent_vault-keypair.json \
--url devnet
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.
Why
User asked "那肯定是走真的啊" — yes, real Solana, real x402.
Confirmed
api.acedata.cloud/midjourney/imaginealready returns full x402 with Solana mainnet USDC option (test bycurl). The only piece missing was a real on-chainagent_vaultprogram — the prior5s9rscxc…placeholder was a deterministic-but-fake address, so any tx Phantom signed against it ultimately failed silently.This PR ships the program to devnet (sufficient for the demo video; mainnet is a one-line config change after).
What lands
declare_id!→56TbAziiW8pDHFpRsxfnfBUfimBRTMCHw4gwDGw9uPW6(built fromtarget/deploy/agent_vault-keypair.json)Account<'info, …>boxed in the 4#[derive(Accounts)]structs to fix the "Stack offset of 4376 exceeded max offset of 4096" warning that would have caused runtime panics oncreate_vaultMAX_ALLOWLIST8 → 4 (account size shrink soPolicy::SIZEstays predictable + matches the trimmed UI cap)SOLANA_CLUSTER=devnet,SOLANA_RPC_URL=https://api.devnet.solana.com,USDC_MINT=4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU(Circle devnet USDC) indeploy/production/api.yamlroutes/schemas.pyallowlist max 8 → 4pages/VaultNew.vuevalidation + helper text 8 → 4DEMO.md,Anchor.toml,programs/agent_vault/README.md,api/.env.exampleall reference the real program IDLive verification (against
https://x402guard.acedata.cloud)Demo flow now reachable
create_vaultix lands on devnet)https://x402guard.acedata.cloud/mcp/<token>into Claude Desktopaceguard_pay_for_api(api.acedata.cloud/midjourney/imagine)→ real 402 → real on-chain spend → real X-Payment retry → real Midjourney imageMainnet is exactly the same flow — just a deploy + 3 env-value swap.
Verification