Skip to content

feat: release 1.1.6 with stellar contract validation support - #18

Merged
akbarsaputrait merged 4 commits into
masterfrom
feat/stellar-contract-validation-support
Sep 4, 2026
Merged

feat: release 1.1.6 with stellar contract validation support#18
akbarsaputrait merged 4 commits into
masterfrom
feat/stellar-contract-validation-support

Conversation

@akbarsaputrait

Copy link
Copy Markdown
Member

No description provided.

@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
rozo-deeplink-demo Ready Ready Preview Sep 4, 2026 6:44am UTC

Request Review

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

AI review: 0 P0 / 3 P1 / 3 P2 — no blocking issues found

Labeled ai-review-passed. This is advisory; a human still merges.

P0 (blocking)

None.

P1 (should fix)

  • packages/core/src/protocols/stellar.ts:33-38 — C-address (parseStellar) returns the same result shape as a G-address, but the address field is not typed/flagged as a contract address. Downstream consumers (e.g. payment construction logic) may pass a contract address where a classic account address is expected (SEP-7 destination=, transaction signer, etc.) and produce a silent mis-routing of funds. Consider adding an addressType: "account" | "contract" discriminator to StellarParseResult so callers can gate on it.

  • packages/core/src/tests/stellar.test.ts:192 / address.test.ts:37 — No negative test for contract address in a SEP-7 destination field. If isValidStellarAddress (now accepting C-addresses) is used to validate destination in parsePayOperation, a contract address could slip through as a payment destination, which Stellar's classic payment op does not support. A test asserting that a C-address embedded as web+stellar:pay?destination=CAHF… is either accepted with a clear caveat or explicitly rejected would surface this gap.

  • QRSpec.md:149 — Example contract address CAHFUV2MVZ3N4VUNQ7RHECTI337SQ2D3QG7TRDSH37ND6M43D6NZANRR appears to be a real or plausible mainnet address with no disclaimer. If this spec is consumed by other teams, the address should be clearly marked as a test/example value, not a live contract, to prevent accidental use as a payment destination.

P2 (nice to have)

  • CLAUDE.md — Removal of chp / chs helper script documentation may quietly break onboarding for developers who relied on those commands; worth a brief note in a comment or migration guide even if the scripts are removed.

  • pnpm-lock.yaml — Several @babel/* snapshot entries were silently bumped (e.g. @babel/types 7.28.5 → 7.29.7, @babel/template 7.27.2 → 7.29.7) as a side-effect of the lockfile regeneration. While likely benign, these are unrelated to the feature and inflate the diff, making review harder. Consider a separate "lockfile bump" commit in the future.

  • packages/core/src/protocols/stellar.ts:42isValidStellarAddress now accepts C-addresses but the function name implies "address" generically. A rename to isValidStellarAddressOrContract or a JSDoc note would make the broadened semantics explicit to callers.

ai-pr-review · claude-sonnet-4-6

@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: b10ba31fc5

ℹ️ 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/core/src/protocols/stellar.ts Outdated

export function isValidStellarAddress(address: string): boolean {
return StrKey.isValidEd25519PublicKey(address);
return StrKey.isValidEd25519PublicKey(address) || StrKey.isValidContract(address);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Do not label contract addresses as payments

When parseDeeplink receives a valid C-address, it invokes parseAddress before parseStellar; this expanded validator therefore enters the Stellar branch in handlers/address.ts, which unconditionally sets operation: "pay". A Soroban contract address is not an account payment destination, so consumers that dispatch on operation can incorrectly start a Stellar payment flow for a scanned contract. Distinguish accounts from contracts in this path and omit or use a contract-specific operation for C-addresses, matching the operation-free result returned by parseStellar itself.

Useful? React with 👍 / 👎.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

AI review: 0 P0 / 3 P1 / 3 P2 — no blocking issues found

Labeled ai-review-passed. This is advisory; a human still merges.

P0 (blocking)

None.

P1 (should fix)

  • packages/core/src/protocols/stellar.ts:38-40parseStellar returns the same StellarParseResult shape for both G- and C-addresses, but the result object has no field distinguishing an account address from a contract address. Callers (and downstream payment logic) that assume every parsed Stellar address is a spendable Ed25519 account could inadvertently route payments to a contract address, which behaves differently on-chain (e.g. a contract cannot be the direct destination of a classic XLM payment without a specific Soroban invocation). The StellarParseResult type should expose an addressType: "account" | "contract" field, and callers should gate payment-initiation paths on that discriminant.

  • packages/core/src/tests/stellar.test.ts — no negative test for a C-address used inside a web+stellar:pay?destination= URL. SEP-7 pay operations define destination as a G-address; a C-address there is invalid per the spec. There is no test asserting that parseStellar("web+stellar:pay?destination=CAHFUV2MVZ3N4VUNQ7RHECTI337SQ2D3QG7TRDSH37ND6M43D6NZANRR") either rejects or is correctly flagged, leaving a behavioral gap that could silently produce malformed payment requests.

  • packages/core/src/protocols/stellar.ts:43-46isValidStellarAddress now returns true for contract addresses, but nothing in the diff shows that parsePayOperation (the SEP-7 pay path) has been updated to reject a C-address as destination. If parsePayOperation blindly accepts whatever isValidStellarAddress accepts, it will pass validation for a structurally invalid SEP-7 pay request.

P2 (nice to have)

  • packages/scan-qr/package.json — no prepublishonly script added (unlike packages/core and packages/react-native which both gained "prepublishonly": "pnpm run build"). The omission is inconsistent and could result in publishing stale build artifacts for @rozoai/deeplink-react.

  • QRSpec.md:133 — the sample C-address (CAHFUV2MVZ3N4VUNQ7RHECTI337SQ2D3QG7TRDSH37ND6M43D6NZANRR) is used verbatim across the spec and all tests. A brief comment noting this is a test/example-only address (not a real deployed contract) would prevent confusion for API consumers reading the spec.

  • pnpm-lock.yamleslint@9.39.2 is now marked deprecated in the lockfile snapshot. Not blocking, but worth scheduling an upgrade to a supported ESLint version.

ai-pr-review · claude-sonnet-4-6

@akbarsaputrait akbarsaputrait changed the title feat: release 0.1.5 with stellar contract validation support feat: release 0.1.6 with stellar contract validation support Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

AI review: 0 P0 / 4 P1 / 4 P2 — no blocking issues found

Labeled ai-review-passed. This is advisory; a human still merges.

P0 (blocking)

None.

P1 (should fix)

  • packages/core/src/protocols/stellar.ts (parseStellar, ~line 31-35): When a Stellar contract address (C address) is parsed as a "plain address", the result's operation field is not set (it remains undefined). Downstream consumers that branch on operation may mishandle contract addresses vs. G-account addresses. Consider setting a distinct operation value (e.g., "contract") or at minimum documenting the intentional omission in the type definition.

  • packages/core/src/protocols/stellar.ts (isValidStellarAddress): isValidStellarAddress now returns true for contract (C) addresses. Any caller that uses this helper to validate a payment destination (e.g., SEP-7 destination field) should only accept G addresses, not contract addresses. If this helper is used for SEP-7 destination validation elsewhere in the codebase, the broadened acceptance could silently allow invalid SEP-7 pay destinations to pass validation.

  • packages/core/src/tests/stellar.test.ts & address.test.ts: The new tests only cover the happy path (valid C address parses correctly). There are no tests for: (a) an invalid C address being rejected, (b) isValidStellarAddress returning true for a C address (regression guard), or (c) a C address being rejected as a SEP-7 destination if that validation exists.

  • packages/scan-qr/package.json: The @rozoai/deeplink-react package (packages/scan-qr/) is missing a prepublishonly build script, unlike packages/core and packages/react-native which both gained one in this PR. This risks publishing stale dist artifacts for the React package.

P2 (nice to have)

  • CLAUDE.md: Removal of the chp / chs helper script documentation with no replacement or note may silently break contributor onboarding if those scripts are used by others. Consider a brief comment that these were internal helpers or point to the replacement.

  • packages/core/README.md: Hardcoded version string (**Version**: 1.1.4) was removed — good — but the README has no pointer to package.json for the authoritative version. Minor discoverability nit.

  • QRSpec.md: The new example C address (CAHFUV2MVZ3N4VUNQ7RHECTI337SQ2D3QG7TRDSH37ND6M43D6NZANRR) appears in both the spec and tests. If this is a real deployed contract, a comment clarifying it's a test/example value (not a production contract) would improve clarity.

  • pnpm-lock.yaml: eslint@9.39.2 is now flagged as deprecated in the lockfile. Consider upgrading ESLint to a supported version in a follow-up.

ai-pr-review · claude-sonnet-4-6

@shawnmuggle shawnmuggle left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Two issues should be resolved before merge:

  1. P1 — bump the release to 1.1.7+: version 1.1.6 is already published on npm from commit b10ba31, while this PR head is 1a39836. Any follow-up fix cannot overwrite the published 1.1.6 artifacts. Please bump all three package versions and internal dependency pins, then regenerate the lockfile.

  2. P2 — do not classify Stellar contract IDs as account payments: isValidStellarAddress() now accepts C-addresses, so parseAddress() returns operation: "pay" for a Soroban contract. Consumers dispatching on operation can incorrectly start an account-payment flow. Please distinguish G- and C-addresses here and add a regression assertion that a C-address does not receive operation: "pay".

I verified the current head: 50/50 tests pass, build and type-check pass, and CI/Vercel are green. The blockers above are semantic/release issues not covered by those checks.

@akbarsaputrait akbarsaputrait changed the title feat: release 0.1.6 with stellar contract validation support feat: release 1.1.6 with stellar contract validation support Sep 4, 2026
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

AI review: 0 P0 / 5 P1 / 4 P2 — no blocking issues found

Labeled ai-review-passed. This is advisory; a human still merges.

P0 (blocking)

None.

P1 (should fix)

  • packages/core/src/handlers/address.ts (C-address branch, ~line 37-44): The new StrKey.isValidContract branch returns a result without operation: "pay" (correct), but parseStellar is no longer called here for contract addresses — it goes straight to a hand-rolled object. If parseStellar is later extended (e.g. to populate chain_id, raw, or other fields), the two code paths will silently diverge. Consider routing through parseStellar and relying on the fact that it won't set operation: "pay" for contract addresses, or at least add a comment noting the intentional bypass.

  • packages/core/src/protocols/stellar.ts (parseStellar, ~line 28-42): When a C-address is passed directly (not via web+stellar:), parseStellar now returns { type: "stellar", address: input, raw: { data: input } } — the same shape as for G-addresses — but without operation: "pay". The test covers this, but there is no test asserting that operation is absent (only that the object matches the partial). A consumer could still attempt an account-payment flow if they do not explicitly check the address type. Add an explicit expect(result).not.toHaveProperty("operation") assertion (or expect(result.operation).toBeUndefined()) in stellar.test.ts for the C-address case.

  • packages/core/src/handlers/address.ts (~line 27): isValidStellarAddress is no longer imported here after this diff (the import was removed), but the function still exists and is exported from stellar.ts. Confirm no other call site in address.ts relied on the old broader definition. The duplicate logic (StrKey calls inlined in address.ts + isValidStellarAddress in stellar.ts) now has two sources of truth for "what is a valid Stellar address." If stellar.ts's definition changes again it won't automatically be reflected in address.ts. Consider re-importing and using isValidStellarAddress for consistency, or explicitly document the intentional split.

  • packages/core/src/tests/stellar.test.ts (C-address test, ~line 177-188): The test asserts result is not null and matches { type, address } but does not assert operation is undefined. As noted above, a future regression that accidentally sets operation: "pay" on contract addresses would not be caught.

  • packages/scan-qr/package.json & packages/react-native/package.json: Both packages now have both "prepare": "pnpm run build" (existing, in scan-qr) and "prepublishOnly": "pnpm run build" (added). Running pnpm publish will trigger prepublishOnly, which is correct, but prepare also runs on npm install in some environments and on pnpm pack, meaning the build runs twice in the publish flow for scan-qr. Remove one or reconcile. prepublishOnly is the right hook for publish-time builds; prepare should be removed if it duplicates it.

P2 (nice to have)

  • CLAUDE.md: Removing the helper-script block (chp, chs find-code) is fine for cleanliness, but if those scripts are relied upon by other contributors, a note in a separate doc or the repo wiki would be courteous.

  • packages/core/README.md: Removing the hard-coded **Version**: 1.1.4 line is good practice (it was already stale), but consider auto-generating it from package.json or adding a badge instead to keep it informative.

  • QRSpec.md note on C-addresses (~line 143): The note says "parseAddress() returns … without operation: "pay"". It would be clearer to say it returns without any operation field at all (currently the wording could imply another operation is present).

  • pnpm-lock.yaml: The eslint@9.39.2 deprecation warning is now surfaced in the lockfile comment. Consider scheduling an upgrade to a supported ESLint version to avoid build-noise.

ai-pr-review · claude-sonnet-4-6

@tg-reviewer-shawnmuggle tg-reviewer-shawnmuggle 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.

Automated code review — P0=0 P1=1 P2=3

Stellar C-address (Soroban contract) parsing support plus version bumps to 1.1.7; main risk is that isValidStellarAddress now accepts contract addresses, so SEP-7 pay destinations and other consumers may treat a non-payable contract as a payment account.

  • P1 packages/core/src/protocols/stellar.ts:45 — isValidStellarAddress() now returns true for C-addresses. Any consumer (including SEP-7 pay destination validation and downstream apps like rozo-invoice) that used this helper to gate a payment flow will accept a Soroban contract address as a payment destination, sending an account payment to a non-account address — funds can be irrecoverably lost. The PR's own docs state contract addresses must not start a payment flow, but this widening contradicts that. Fix: Keep isValidStellarAddress() as account-only (Ed25519) and add a separate isValidStellarContract()/isValidStellarAddressOrContract() helper; use the explicit contract check only in parseAddress/parseStellar plain-address handling.
  • P2 packages/core/src/protocols/stellar.ts:28 — parseStellar() returns the same shape for G and C addresses, so callers cannot distinguish an account from a contract from the result alone; a wallet auto-starting a pay flow on any parsed stellar address will do so for contracts. Fix: Add a discriminating field (e.g. address_type: "account" | "contract") to StellarParseResult and set it in both parseStellar and parseAddress, and document it in the README type block.
  • P2 packages/core/src/tests/address.test.ts:32 — expect(result).not.toHaveProperty("operation", "pay") passes even if operation is absent for the wrong reason, and no test asserts chain_id is omitted for contracts; a regression re-adding operation/chain_id under a different value would go undetected. Fix: Assert explicitly that operation and chain_id are undefined for C-addresses, and add a negative test that a C-address is rejected as a SEP-7 pay destination.
  • P2 packages/core/package.json:23 — Version jumps 1.1.4 -> 1.1.7 while the PR title says 1.1.6, and the lockfile already resolves published 1.1.7 tarballs for the workspace packages — the demo app may resolve the registry copy rather than the workspace source, so the reviewed code is not what is tested. Fix: Reconcile the title/version, and use workspace:* for internal deps in apps/demo and packages so local source is exercised.

Reviewer: claude-opus-5
Approved for this exact head SHA; the PR author decides when to merge.

@akbarsaputrait
akbarsaputrait merged commit b6603fb into master Sep 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants