feat(near): port NEAR Intents preset (decode + render) and merge converters - #428
Draft
shahan-khatchadourian-anchorage wants to merge 1 commit into
Conversation
…erters Ports the NEAR Intents protocol decoder into chain_parsers/visualsign-near/src/presets/intents/: envelope parsing, all 11 intent renderers, execute_intents dispatch, and the pre-signature single-intent render. crate:: references become super:: since the module moves from a standalone crate root into a nested presets::intents module. near_env_shim.rs does not carry over -- this session's earlier investigation found near-sdk 5.27+ (what this workspace resolves) already fixes the native-linking gap it worked around, so visualsign-near keeps the workspace's unsafe_code = "forbid" with no carve-out. verify.rs ports only its core functions (verify_and_extract, the secp256k1 recovery-id guard), since render.rs calls them directly to compile; dedicated signed-vector test coverage for verification is scoped to the next PR in the stack. The converter merge (the one non-mechanical step): tx.rs's NearTransaction becomes an enum, OnChain(Transaction) or Intent(String), discriminating borsh-vs-JSON input -- borsh decode attempted first, falling through to DefusePayload JSON validation only on failure, input that is neither rejected. This replaces two separate converters (one per input format, each its own custom chain) with one type. convert.rs re-adds the execute_intents decode branch A2 omitted, now calling the real preset, plus a new branch rendering the Intent variant. Security review of this port found a signing-integrity gap: FtWithdraw/NftWithdraw/MtWithdraw carry an optional storage_deposit (an unconditional, unrefundable wNEAR debit alongside the withdraw) and msg (switches the call into its _transfer_call form) that were never surfaced -- a user could sign a withdraw and see only the nominal amount while authorizing an invisible additional debit. Fixed here: both fields now render on all three withdraw variants, with regression tests covering presence and absence. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
shahan-khatchadourian-anchorage
force-pushed
the
shahankhatchadourian/near-a3-intents
branch
from
July 30, 2026 20:25
1c0b792 to
6b0daff
Compare
Copilot started reviewing on behalf of
shahan-khatchadourian-anchorage
July 30, 2026 22:59
View session
Contributor
There was a problem hiding this comment.
Pull request overview
Adds NEAR Intents support to visualsign-near by introducing an intents “preset” (decode + render) and merging the crate’s previously separate input-format handling into a single NearTransaction enum that discriminates between on-chain borsh transactions and pre-signature intents JSON envelopes.
Changes:
- Introduces
presets::intentswith JSON args decoding, token metadata/formatting, rendering for supported intent variants, and partial signature verification plumbing. - Merges NEAR parsing into
NearTransaction::{OnChain, Intent}and updates the converter to dispatch/render accordingly (includingexecute_intentsdecoding forintents.near). - Adds crate feature wiring for diagnostics passthrough (
visualsign/diagnostics) and updates tests to cover the new paths.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/chain_parsers/visualsign-near/src/tx.rs | Parses either borsh NEAR transactions or validates/stores DefusePayload JSON for intent signing flows. |
| src/chain_parsers/visualsign-near/src/convert.rs | Dispatches conversion based on NearTransaction variant and decodes/renders execute_intents calls. |
| src/chain_parsers/visualsign-near/src/lib.rs | Exposes the new presets module. |
| src/chain_parsers/visualsign-near/src/presets/mod.rs | Adds the presets module root and exports intents. |
| src/chain_parsers/visualsign-near/src/presets/intents/mod.rs | Defines the intents preset API, registry types, errors, and integration tests. |
| src/chain_parsers/visualsign-near/src/presets/intents/args.rs | Deserializes execute_intents JSON args into MultiPayload list. |
| src/chain_parsers/visualsign-near/src/presets/intents/render.rs | Renders intents, envelope fields, and signature status into VisualSign fields. |
| src/chain_parsers/visualsign-near/src/presets/intents/tokens.rs | Provides seeded NEP-141 token metadata and unit formatting helpers. |
| src/chain_parsers/visualsign-near/src/presets/intents/verify.rs | Adds signature verification + payload extraction helpers (partial, used by rendering). |
| src/chain_parsers/visualsign-near/Cargo.toml | Adds thiserror and introduces a diagnostics feature wired to visualsign/diagnostics. |
| src/Cargo.lock | Pulls in thiserror resolution for the NEAR crate. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+19
to
+21
| pub enum NearIntentsError { | ||
| #[error("execute_intents args were not valid JSON: {0}")] | ||
| ArgsNotJson(String), |
Comment on lines
+103
to
+106
| fields.extend(render_signature(standard_name(mp), &check)?); | ||
| if let Some(payload) = &extracted { | ||
| fields.extend(render_single(payload, registry)?); | ||
| } |
This was referenced Jul 31, 2026
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.
Third PR of the NEAR-consolidation stack (stacked on #426). Adds the NEAR Intents preset -- decode + render for the signed-envelope and pre-signature flows -- and merges the crate's two input-format handlers into one.
Stack: A1 (#425) -> A2 (#426) -> A3 (this) -> A4 (signature verification) -> B (identity + wiring) -> C (docs site).
What this PR does
Adds
chain_parsers/visualsign-near/src/presets/intents/:mod.rs: entry points (try_decode_execute_intents,try_render_single_intent),NearIntentsError,NearTokenRegistry/TokenMeta.args.rs: JSON deserialization ofexecute_intentsargs.tokens.rs: seeded NEP-141 token table + amount formatting.render.rs: renders all 11 intent variants (TokenDiff, Transfer, FtWithdraw, NftWithdraw, MtWithdraw, NativeWithdraw, AddPublicKey, RemovePublicKey, SetAuthByPredecessorId, StorageDeposit, AuthCall) plus the signature-status section.verify.rs: partial -- onlyverify_and_extractand the secp256k1 recovery-id guard (render.rscalls these directly to compile). The dedicated signed-vector test module is scoped to A4 (signature verification specifically), since it needs fixture files and dev-dependencies (k256,bs58) not yet added.near_env_shim.rsdoes not carry over -- a prior investigation this session found near-sdk 5.27+ (what this workspace resolves) already fixes the native-linking gap that module worked around, sovisualsign-nearkeeps the workspace'sunsafe_code = "forbid"outright, no carve-out.The converter merge (the one non-mechanical step)
tx.rs'sNearTransactionbecomes an enum:from_stringtries borsh decode first (via the existing hex/base64 detection); on failure, it validates the input as aDefusePayloadJSON envelope. Input that is neither is rejected. This replaces two separate converters -- one per input format, each registered under its own custom chain name -- with a single type discriminating by format, matching the target design (one chain identity, format-discriminated).convert.rsdispatches on the enum:OnChainrenders as before (A2's baseline fields) plus theexecute_intentsdecode branch A2 deliberately omitted, now calling the real preset when the action is a FunctionCall tointents.near/execute_intents;Intentrenders viatry_render_single_intent, titled "NEAR Intent", with no signature section (nothing is signed yet at that stage).Security fix folded in
Self-review of this port surfaced a signing-integrity gap:
FtWithdraw/NftWithdraw/MtWithdraw(verified against the pinneddefuse-coresource) carry an optionalstorage_depositfield -- an unconditional, unrefundable wNEAR debit alongside the withdraw -- and an optionalmsgfield that switches the call into its_transfer_callform. Neither was rendered: a user signing "withdraw 1 wNEAR" could be authorizing an additional, invisible debit of arbitrary size with zero indication.Fixed: both fields now render on all three withdraw renderers via a shared helper, with new regression tests (
*_renders_storage_deposit_and_message,ft_withdraw_omits_message_and_storage_deposit_when_absent) covering both presence and absence.Verification
cargo test -p visualsign-near-- 45/45 pass, under both default and--features diagnostics.cargo clippy -p visualsign-near --all-targets -- -D warnings,cargo fmt --check-- clean.cargo check/clippy -p parser_app --no-default-features --features near-- clean (narrow-build variant).make -C src lint,make -C src test-- clean (default features; stock builds unaffected).