Skip to content

feat(morpho-sdk): add transaction plan#856

Open
prd-carapulse[bot] wants to merge 10 commits into
hermes/marketv2-action-flows-implementationfrom
hermes/transaction-plan
Open

feat(morpho-sdk): add transaction plan#856
prd-carapulse[bot] wants to merge 10 commits into
hermes/marketv2-action-flows-implementationfrom
hermes/transaction-plan

Conversation

@prd-carapulse

@prd-carapulse prd-carapulse Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Adds a first-class TransactionPlan API for app-side transaction review and execution flows, stacked on hermes/marketv2-action-flows-implementation.

Summary:

  • Adds lazy TransactionPlan, PreparedTransactionPlan, and ExecutableTransactionPlan under src/transactionPlan/.
  • Entity action-flow outputs across Vault V1, Vault V2, Blue, and Midnight return TransactionPlan instances while preserving buildTx(...) / getRequirements(...) destructuring.
  • Primary app-facing surface is now request-shaped: signatureRequests and callRequests.
  • callRequests contains viem-compatible calls in execution order and includes the final intent call when it can be previewed. After signatures, prepared.build(signatures).callRequests always includes the final intent call last.
  • Previous requirement-oriented fields remain only as deprecated aliases for compatibility.
  • Adds semantic intents (tokenApproval, operatorAuthorization, contractCall, midnightOfferRootSignature, finalTransaction), request-kind flow values (single_call, call_requests, signature_requests, mixed_requests), sequential signAll(), ordered viem-compatible calls, and missing-signature validation.
  • Supports signature-dependent final transactions whose unsigned final call cannot be previewed before signatures are collected; reading prepared.finalTx before it is available throws a typed SDK error.

Interface rationale:

  • VVRM/vaults app currently starts from raw SDK requirements, then turns them into user steps: approval txs, offchain signatures, and the final tx. At the app/UX boundary, “requirements” are not meaningful; “signature requests” and “call requests” are.
  • Markets app already models flows as SignatureRequest[] plus ordered CallRequest[]. PRs morpho-org/morpho-apps#3567 and #3568 had to adapt the SDK output into that shape manually, including appending the final call after prerequisite calls.
  • The SDK should internalize the neutral structure and metadata, not labels/callbacks/hooks/product branching. Apps still own labels, analytics, callbacks, action-flow construction, and UX policy.
  • finalTx is still exposed as a convenience/safety handle for consumers that need the semantic final action (action.type, built tx metadata, guard when not previewable), but it is no longer the main way to submit calls. The main submission surface is callRequests.

Vaults-app transaction-context sketch:

const txPlan = vault.deposit({ amount, nativeAmount, userAddress, vaultData });
const prepared = await txPlan.prepare({ requestOptions: { useSimplePermit } });

const txFlowType = prepared.flowKind === "single_call"
  ? "simple"
  : prepared.signatureRequests.length > 0
    ? "signature_required"
    : "bundled";

const stepLabels = prepared.steps.map((step) => {
  switch (step.intent.type) {
    case "tokenApproval":
      return step.intent.method === "tx"
        ? `Approve ${formatAmount(step.intent.amount, token)}`
        : `Sign ${step.intent.method === "permit2" ? "Permit2" : "permit"}`;
    case "operatorAuthorization":
      return step.intent.method === "tx" ? "Authorize operator" : "Sign authorization";
    case "contractCall":
      return actionLabels[step.intent.actionType] ?? "Review transaction";
    case "midnightOfferRootSignature":
      return "Sign offer root";
    case "finalTransaction":
      return actionLabels[step.intent.actionType] ?? "Submit transaction";
  }
});

const signatures = await prepared.signAll(walletClient, userAddress);
const callsForSimulation = prepared.build(signatures).callRequests.map((step) => step.call);

Markets-app action-flow sketch:

const txPlan = midnight.supplyCollateral(params); // already a TransactionPlan
const prepared = await txPlan.prepare();
const signatures: RequirementSignature[] = [];

const signatureRequests = prepared.signatureRequests.map((step) => ({
  label: labelStep(step),
  sign: async (client) => {
    const signature = await step.sign(client, accountAddress);
    signatures.push(signature);
    return "signature" in signature.args ? signature.args.signature : "0x";
  },
}));

const callRequests = prepared.callRequests.map((step) => ({
  label: labelStep(step),
  getCall: () => step.call,
}));

// Maker flows whose final mempool-submit call depends on the collected signature
// have no unsigned preview, so the final call is produced lazily after signing.
if (!prepared.hasFinalTxPreview) {
  callRequests.push({
    label: "Submit transaction",
    getCall: () =>
      prepared.build(signatures.length > 0 ? signatures : undefined).callRequests.at(-1)!.call,
  });
}

function labelStep(step: TransactionPlanStep) {
  switch (step.intent.type) {
    case "tokenApproval":
      return step.intent.method === "tx" ? "Approve token" : "Sign token approval";
    case "operatorAuthorization":
      return step.intent.method === "tx" ? "Authorize operator" : "Sign authorization";
    case "midnightOfferRootSignature":
      return "Sign offer root";
    case "contractCall":
      return actionLabels[step.intent.actionType] ?? "Review transaction";
    case "finalTransaction":
      return actionLabels[step.intent.actionType] ?? "Submit transaction";
  }
}

Verification:

  • pnpm --filter @morpho-org/morpho-sdk build
  • pnpm lint:ci
  • MAINNET_RPC_URL="https://rpc.morpho.dev/cache/evm/1?secret=$RPC_SECRET" pnpm exec vitest run --project morpho-sdk packages/morpho-sdk/src/transactionPlan/TransactionPlan.test.ts packages/morpho-sdk/src/entities/vaultV1/vaultV1.test.ts packages/morpho-sdk/src/entities/vaultV2/vaultV2.test.ts packages/morpho-sdk/src/entities/blue/blue.test.ts packages/morpho-sdk/src/entities/midnight/midnight.test.ts

Requested by: <@U03L0SC1JUR>


Open in Devin Review

@prd-carapulse prd-carapulse Bot requested a review from a team as a code owner July 8, 2026 08:10

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment thread packages/morpho-sdk/src/transactionPlan.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7da4dd011c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/morpho-sdk/src/transactionPlan.ts Outdated
Comment thread packages/morpho-sdk/src/transactionPlan.ts Outdated
Comment thread packages/morpho-sdk/src/transactionPlan.ts Outdated
Comment thread packages/morpho-sdk/src/transactionPlan.ts Outdated
Comment thread packages/morpho-sdk/src/transactionPlan.ts Outdated
@Rubilmax Rubilmax self-assigned this Jul 8, 2026
@Rubilmax

Rubilmax commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@codex

Comment thread packages/morpho-sdk/src/helpers/transactionPlan.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 45e79af5de

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@prd-carapulse prd-carapulse Bot force-pushed the hermes/transaction-plan branch from 56545a4 to 71e53b9 Compare July 8, 2026 13:22
Add a TransactionPlan API for semantic transaction review/execution flows on top of the Market V2 action-flow branch. Entity handlers now return lazy TransactionPlan instances while preserving buildTx/getRequirements.
@prd-carapulse prd-carapulse Bot force-pushed the hermes/transaction-plan branch from 71e53b9 to 93a73c1 Compare July 9, 2026 08:38
@prd-carapulse prd-carapulse Bot changed the base branch from main to hermes/marketv2-action-flows-implementation July 9, 2026 08:38
Make Midnight action-flow outputs first-class TransactionPlan instances, add non-previewable final transaction support for signature-dependent maker flows, and broaden plan intents to operatorAuthorization/contractCall for neutral app consumption.
Comment thread packages/morpho-sdk/src/entities/blue/blue.ts
Comment thread packages/morpho-sdk/src/entities/midnight/midnight.ts Outdated
Comment thread packages/morpho-sdk/src/transactionPlan/TransactionPlan.ts Outdated
Comment thread packages/morpho-sdk/src/transactionPlan/TransactionPlan.ts Outdated
Restore simple-permit option documentation, make TransactionPlan handler accessors prototype-backed and destructuring-safe, guard non-previewable final transaction access, and inline Midnight make-offer transaction construction into the TransactionPlan output.

@Rubilmax Rubilmax left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

almost lgtm

Comment thread packages/morpho-sdk/src/entities/blue/blue.ts Outdated
Comment thread packages/morpho-sdk/src/entities/vaultV1/vaultV1.ts Outdated
Move duplicated simple-permit and requirement aliases into transaction-plan types, inline the mixed Blue requirement union at call sites, and keep the review-comment safety changes covered by local build/lint/tests.
Comment thread packages/morpho-sdk/src/transactionPlan/types.ts Outdated
prd-carapulse Bot added 6 commits July 10, 2026 12:43
Expose signatureRequests and callRequests as the primary app-consumption surface, include the final intent call in callRequests when available, keep previous requirement-oriented fields as deprecated aliases, and rename flow-kind values around requests instead of requirements.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant