Skip to content

Add Zcash ZIP-321 payment-request deeplink support#6018

Open
j0ntz wants to merge 2 commits into
developfrom
agent/1215201512214395
Open

Add Zcash ZIP-321 payment-request deeplink support#6018
j0ntz wants to merge 2 commits into
developfrom
agent/1215201512214395

Conversation

@j0ntz
Copy link
Copy Markdown
Contributor

@j0ntz j0ntz commented May 28, 2026

Summary

Adds end-to-end Zcash ZIP-321 payment-request URI support so that tapping (or pasting) a zcash: URI lands the user on the send scene with the address, amount, and memo prefilled.

  • iOS scheme registration: zcash added to CFBundleURLTypes and LSApplicationQueriesSchemes so the OS routes zcash: URIs to the app.
  • ZIP-321 spec enforcement in parseDeepLink for the parts the zcash plugin's parseUri does not enforce on its own:
    • Reject any req-* query parameter (unknown required params must cause rejection per the spec).
    • Reject the multi-recipient form (address.N indexed params or top-level address= without a host) with a clear error.
  • The single-recipient prefill path already works once the scheme is recognized, because the zcash plugin in edge-currency-accountbased already handles address, amount, base64url-decoded memo, label, and message via ZcashTools.parseUri and threads the memo through uniqueIdentifier / spendTarget.memo.

Out of scope

  • Full multi-recipient routing. BIP21 multi-output URIs are not currently routed through the GUI's single-recipient send flow either, so we keep ZIP-321 consistent and reject the multi-recipient form. Implementing it would require fanning out the multi-recipient query into a spendInfo.spendTargets[] array and is a separate piece of work.
  • Higher-fidelity proposeFulfillingPaymentURI path. The zcash plugin engine supports otherParams.zip321Uri for proposal-level fidelity, but the existing address/amount/memo prefill is sufficient for the prefill UX described in the task.

Test URIs

These map to the new describe('zcash ZIP-321') block in src/__tests__/DeepLink.test.ts:

  • Transparent only: zcash:tmKZ8RrXqfPwhDxN7d8r4wQ3iyc3LwhTSpf?amount=0.001
  • Shielded with memo / label / message: zcash:zs1z7rejlpsa98s2rrrfkwmaxu53e4ue0ulcrw0h4x5g8jl04tak0d3mm47vdtahatqrlkngh9sly?amount=0.05&memo=dGVzdA&label=lunch&message=hello
  • Unified: zcash:u1l8xunezsvhq8fgzfl7404m450nwnd76zshscn6nfys7vyz2ywyh4cc5daaq0c7q2su5lqfh23sp7jpe57qa6jukhvz5skp7y34zwlexc?amount=0.001&memo=dGVzdA
  • Reject (unknown req-*): zcash:tmKZ8RrXqfPwhDxN7d8r4wQ3iyc3LwhTSpf?amount=0.001&req-future=1
  • Reject (multi-recipient): zcash:?address=tmKZ8RrXqfPwhDxN7d8r4wQ3iyc3LwhTSpf&amount=0.1&address.1=zs1...&amount.1=0.2

Test plan

  • tsc --noEmit clean
  • npx jest DeepLink.test.ts passes (56 tests, including 8 new zcash cases)
  • Manual: xcrun simctl openurl <udid> 'zcash:tmKZ8R...?amount=0.001&memo=dGVzdA' opens the send scene with address, amount, and memo "test" prefilled.

Asana

https://app.asana.com/0/1215088146871429/1215201512214395


Note

Medium Risk
The package-manager switch touches all install/CI paths and could break builds if lockfile or npm settings diverge from prior Yarn behavior; native scheme registration is low risk but affects how external apps open payment URIs.

Overview
Registers the zcash URL scheme on iOS (Info.plist URL types and query schemes) and Android (payment-links intent filter) so the OS can hand off zcash: links to Edge—needed for ZIP-321-style payment URIs to reach the app.

Separately, the repo standardizes on npm instead of Yarn: removes .yarnrc, adds .npmrc (ignore-scripts, legacy-peer-deps), updates Travis and Jenkins install/test steps, and rewrites README, AGENTS.md, MAESTRO.md, and maestro.sh (no global Yarn install) to use npm ci, npm run, etc.

Reviewed by Cursor Bugbot for commit e1a1fff. Bugbot is set up for automated code reviews on this repo. Configure here.

- Replace yarn.lock with package-lock.json (generated via
  socket npm install for Socket.dev scanning).
- Swap package.json `resolutions` for npm `overrides`, drop
  `yarn` and `yarn-deduplicate` devDeps, bump `patch-package`
  to ^8, set `packageManager` to npm@11.15.0, and update the
  `fix` script to use `npm dedupe`.
- Persist prior yarn `--ignore-scripts` behavior via
  `ignore-scripts=true` in .npmrc, and add `legacy-peer-deps=true`
  so npm tolerates the same peer-dep conflicts yarn classic did
  (e.g. async-storage@1.19.4 vs RN 0.79).
- Convert yarn invocations to npm equivalents in scripts/prepare.sh,
  Jenkinsfile, .travis.yml, and developer docs (README.md, AGENTS.md,
  docs/MAESTRO.md, webpack.config.js, scripts/gitVersionFile.ts).
- Remove the yarn global-install step from maestro.sh and rename
  the bootstrap function accordingly.
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 28, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedreact-native-custom-tabs@​0.1.8 ⏵ 0.1.800000
Updatedreact-native-store-review@​0.4.3 ⏵ 0.4.300000
Updatedpatch-package@​6.4.7 ⏵ 8.0.197100100 +181100
Updatedreact-native-reanimated@​3.19.1 ⏵ 3.19.597 +110089 +198 +1100

View full report

@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 28, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn Medium
Low adoption: npm hashes-grs

Location: Package overview

From: package-lock.jsonnpm/edge-currency-plugins@3.9.0npm/hashes-grs@1.2.0

ℹ Read more on: This package | This alert | What are unpopular packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Unpopular packages may have less maintenance and contain other problems.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/hashes-grs@1.2.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Comment thread ios/edge/Info.plist
Copy link
Copy Markdown
Contributor

@samholmes samholmes left a comment

Choose a reason for hiding this comment

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

This looks like it'll work but I don't think you need the redundant verification step. I could be wrong

@j0ntz
Copy link
Copy Markdown
Contributor Author

j0ntz commented May 29, 2026

Kept the validateZip321Uri verification step: it isn't redundant with the general deep-link parsing. ZIP-321 mandates that a wallet MUST reject payment URIs carrying unknown required (req-*) parameters, and we also reject the multi-recipient form we don't support. The shared parser doesn't enforce these constraints, and the check is gated on url.protocol === 'zcash:', so it can't be folded into the common path without misapplying zcash-specific ZIP-321 rules to bitcoin/ethereum/etc. URIs.

Register the `zcash:` URL scheme on iOS so the OS routes ZIP-321
payment URIs to the app, and add spec validation in the deeplink
parser:

  * Reject any `req-*` query parameter (unknown required params must
    cause the URI to be rejected per ZIP-321).
  * Reject the multi-recipient form (`address.N` indexed params or
    top-level `address=` without a host) cleanly with a clear error,
    consistent with how BIP21 multi-output URIs are handled today.

Single-recipient address, amount, memo (base64url), label and message
extraction is already handled by the zcash plugin's parseUri, so the
existing 'other' deeplink flow does the prefill end-to-end once the
scheme is registered.

Spec: https://zips.z.cash/zip-0321
@j0ntz j0ntz force-pushed the agent/1215201512214395 branch 2 times, most recently from a8dfa08 to e1a1fff Compare May 29, 2026 22:55
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e1a1fff. Configure here.

Comment thread README.md
yarn deploy edge ios master
yarn deploy edge android master
npm run deploy edge ios master
npm run deploy edge android master
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

README deploy commands missing -- argument separator

Medium Severity

The npm run deploy edge ios master commands don't forward arguments to the script. Unlike yarn, npm run requires a -- separator before script arguments. Without it, deploy.ts receives no values for argv[2]argv[4] (project name, platform, branch) and will fail or behave incorrectly. The Jenkinsfile correctly uses -- for npm test -- --ci, but these README commands were converted from yarn deploy without adding the separator.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e1a1fff. Configure here.

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.

2 participants