Add bridge-then-deploy action provider - #3
Conversation
Composes an Across bridge with a destination lending/vault supply so an agent can express "move this capital to chain X and put it to work" as one intent. Honest about the EOA constraint: Across destination execution only reaches a handler contract, never an EOA, so the flow is two-step and non-atomic (bridge -> poll status -> supply on arrival). Actions: - bridge_and_deploy: initiates the Across deposit and records the pending destination supply; never claims the supply has happened. - bridge_deploy_status: polls the Across deposit-status API and auto-runs the recorded supply once the bridge is filled. - deploy_on_destination: supplies an already-bridged token into Compound or Morpho on Base, with a balance preflight so it is safe to retry. Destination deploy is gated to Base; origin can be any EVM chain Across supports. Includes unit tests (mocked wallet + Across SDK), README documenting the non-atomic semantics, and a changeset. https://claude.ai/code/session_013rnmDYrKDMctusY33uneiy
zaryab2000
commented
Jun 6, 2026
@claude start review |
Claude finished @zaryab2000's task in 2m 59s —— View job Code Review — |
| Rule | Status |
|---|---|
All actions return Promise<string>; errors returned not thrown | ✅ |
Zod v4 schemas with .describe() on every field; no .strip() | ✅ |
supportsNetwork is an arrow-function property | ✅ |
Factory bridgeDeployActionProvider exported and re-exported from index.ts | ✅ |
README.md present | ✅ |
pnpm run changeset — patch, past tense, correct package | ✅ |
| Tests present and mocking wallet provider | ✅ |
super("bridgeDeploy", []) constructor call | ✅ |
Network.chainId compared as string | ✅ |
Summary: The implementation is clean and well-documented. The two blocking issues before upstream merge are the Compound supplyTo vs supply recipient bug (#2) and the in-memory state loss documentation (#1). The URL encoding (#4) and slippage arithmetic (#6) are simple one-liners to fix. The missing test coverage (#5) should be added before the PR goes out.
- Compound: use supplyTo(dst, asset, amount) so the position is credited to the recipient instead of msg.sender (silent divergence from Morpho). - Auto-deploy: supply the amount that actually landed when a fill comes in under the quoted output, instead of failing the stale-quote preflight; deploy_on_destination stays strict for explicit calls. - getDepositStatus: build the status URL with URLSearchParams. - Slippage check now uses bigint arithmetic to avoid float rounding. - Document the in-memory pending-deploy state (lost on re-instantiation) in the README and on the field; clarify token is an address (not symbol) for deploy_on_destination. - Add tests for the filled-without-pending-record and supply-fails-retry paths. https://claude.ai/code/session_013rnmDYrKDMctusY33uneiy
zaryab2000
commented
Jun 6, 2026
Thanks for the review — addressed in Fixed
Intentionally deferred (with rationale)
Generated by Claude Code |
zaryab2000
commented
Jun 11, 2026
@claude conduct final review and confirm if the PR is accurate now? |
Claude finished @zaryab2000's task in 1m 38s —— View job Final Review — |
| # | Issue | Status | Evidence |
|---|---|---|---|
| #2 | Compound supplyTo recipient | ✅ Fixed | COMET_SUPPLY_ABI in constants.ts now includes supplyTo(address dst, address asset, uint256 amount); utils.ts:358–362 uses supplyTo with [params.recipient, token, atomicAmount] |
| #3 | Quoted vs actual fill | ✅ Fixed | deployToProtocol takes allowPartial = false; auto-deploy path (bridge_deploy_status) passes true; supplies balance when partial; standalone deploy_on_destination stays strict (false) |
| #4 | URL encoding | ✅ Fixed | utils.ts:256–259 uses new URL(ACROSS_DEPOSIT_STATUS_API) + url.searchParams.set(...) |
| #6 | Bigint slippage arithmetic | ✅ Fixed | utils.ts:183–185: ((inputAmount - outputAmount) * 10000n) / inputAmount — no float conversion |
| #1 | In-memory state documented | ✅ Fixed | JSDoc on #pendingDeploys (bridgeDeployActionProvider.ts:47–56) and a dedicated "README.md:23–40 both clearly state the instance-local constraint |
| coinbase#9 | Token address vs symbol warning | ✅ Fixed | deploy_on_destination action description says "NOT the token symbol"; README.md:74–76 also distinguishes bridge_and_deploy (symbol) from deploy_on_destination (address) |
| #5 | Missing test coverage | ✅ Fixed | test.ts:216–236 covers filled with no pending record; test.ts:238–270 covers supply-fails-on-filled retry retention |
Intentionally deferred (confirmed reasonable)
- Add Hyperliquid action provider (HyperEVM perps) #7 — dead
if (!account)guard: harmless defensive parity with the in-treeacrossprovider. - fix: github workflow for documentation generation and publishing to pages coinbase/agentkit#8 —
http()with no RPC URL: matches every other provider; acceptable for v1.
One minor observation (non-blocking)
COMET_SUPPLY_ABI in constants.ts still includes the supply(address asset, uint256 amount) entry, but the code now always calls supplyTo. The supply entry is dead code in the execution path. The comment justifies its presence for documentation purposes, and since it cannot cause a runtime error, this is harmless — just worth noting for cleanliness.
Conventions checklist
| Rule | Status |
|---|---|
All actions return Promise<string>; errors returned not thrown | ✅ |
Zod v4 schemas with .describe() on every field; no .strip() | ✅ |
supportsNetwork is an arrow-function property | ✅ |
Factory bridgeDeployActionProvider exported and re-exported from index.ts | ✅ |
README.md present and documents EOA/two-step semantics | ✅ |
Changeset — @coinbase/agentkit, patch, past tense | ✅ |
| Tests present, mocked wallet, 13 provider tests | ✅ |
super("bridgeDeploy", []) constructor call | ✅ |
Network.chainId compared as string | ✅ |
The PR is accurate. All blocking issues from the previous review have been correctly addressed. The one remaining item (supply ABI entry being unused) is non-blocking cosmetic cleanup. The implementation is clean, well-documented, and matches AgentKit conventions.
zaryab2000
commented
Jun 11, 2026
Final review — confirmed accurate ✅Re-reviewed the full provider on head Correctness — verified in code
CI — green on head
Local
One honest limitation worth recording (not a blocker, by design): Minor / optional: the PR description is slightly stale vs the latest commits — it still says "875 tests" and "Compound (Comet Still intentionally deferred:#7 (dead Net: the PR is accurate and merge-ready into Generated by Claude Code |
The Compound path always uses supplyTo to honor the recipient, so the supply(asset, amount) entry was dead code. Drop it from COMET_SUPPLY_ABI. https://claude.ai/code/session_013rnmDYrKDMctusY33uneiy
zaryab2000
commented
Jun 11, 2026
Addressed the one new observation from the final review in No functional change; the dead-code path is gone. Verified: 13 provider tests + full agentkit suite green, No other new bugs were reported in the latest review (it confirmed all 7 prior fixes as correct). PR remains accurate and merge-ready into Generated by Claude Code |
Summary
Adds a new bridge-then-deploy ActionProvider (
bridgeDeploy) that composes an Across bridge with a destination lending/vault supply, letting an agent express "move this capital to chain X and put it to work" as a single intent.Central design constraint (honest by design)
Across destination-side execution only delivers to a deployed handler contract that implements
handleV3AcrossMessage(...)— never to a plain EOA. Agent wallets are EOAs, so this flow is deliberately two-step and non-atomic: bridge → poll status → supply on arrival. The provider never claims the supply has happened before the bridge fills.Actions
bridge_and_deploy— initiates the Across deposit and records the pending destination supply; returns adepositIdandstatus: "bridging". Does not supply yet.bridge_deploy_status— polls the Across deposit-status API; oncefilled, auto-runs the recorded destination supply and returns the deploy tx hash. Reportspending/refundedotherwise.deploy_on_destination— supplies an already-bridged token into Compound (Cometsupply) or Morpho (vaultdeposit) on Base. Performs a balance preflight, so it is safe to retry to recover from a partial failure.Scope
8453/84532); origin can be any EVM chain Across supports.Conventions
Promise<string>; errors are returned, not thrown..describe()on every field; no.strip().approveutil and mirrors the in-treeacrossprovider's SDK wiring (privateKeyconstructor config, fully mocked in tests).src/action-providers/index.ts.Checks
pnpm test— full agentkit suite green (875 tests, incl. 11 new for this provider, mocked wallet + Across SDK).pnpm run lint,pnpm run format,pnpm build— all clean.@coinbase/agentkit, patch, past tense).https://claude.ai/code/session_013rnmDYrKDMctusY33uneiy
Generated by Claude Code