Skip to content

Rebase on main + regenerate READMEs (1 squashed commit, all 9 CI jobs pass locally)#1

Open
0xultravioleta wants to merge 74 commits into
soumyacodes007:feature/stellar-integrationfrom
0xultravioleta:stellar/rebase-single-commit
Open

Rebase on main + regenerate READMEs (1 squashed commit, all 9 CI jobs pass locally)#1
0xultravioleta wants to merge 74 commits into
soumyacodes007:feature/stellar-integrationfrom
0xultravioleta:stellar/rebase-single-commit

Conversation

@0xultravioleta
Copy link
Copy Markdown

Hi @soumyacodes007 — as discussed in #181 comment, rebased your branch onto current main (post NEAR + Spark merges) so the upstream PR is mergeable again.

Squash strategy

Your three commits (03edec5, 4160e9e, 4b5c554) are squashed into a single commit on top of main, with you preserved as the primary author (0xrick <rickbhowmik4@gmail.com>) via git commit --author. I added myself + Claude as Co-Authored-By. The single-commit form mirrors how @njdawn merged the NEAR PR last night.

Conflicts resolved during the rebase

Main moved with the NEAR + Spark merge so most conflicts were "combine NEAR/Nano arms with Stellar arms":

  • ows-core/src/chain.rsChainType::Stellar added alongside Nano + Near; ALL_CHAIN_TYPES is now [13]; KNOWN_CHAINS gains stellar + stellar-testnet; namespace/coin_type/from_namespace/Display/FromStr/serde tests extended
  • ows-signer/src/chains/mod.rs — Stellar arm joined the chain match
  • ows-lib/src/key_ops.rs, src/ops.rssigner_for_chain_info import merged alongside signer_for_chain; broadcast_stellar joined the dispatch
  • ows-lib/Cargo.tomlstellar-xdr dev-dep kept, ows-signer pinned to current workspace version =1.3.2
  • All 7 generated READMEs regenerated via ./readme/generate.sh (this is the gate that failed on the original CI before, now passes)
  • docs/07-supported-chains.md + readme/templates/ows.md + readme/partials/supported-chains.md — Stellar appended after NEAR everywhere
  • bindings/{node,python} tests — universal wallet count 12 → 13, stellar:* assertion added

CI gates verified locally on the new commit

cargo fmt --all --check                                    clean
cargo clippy --workspace --all-targets -- -D warnings      clean
cargo test --workspace                                     640 passed, 0 failed
./readme/generate.sh --check                               clean

What this gets you

When you merge this PR into your feature/stellar-integration branch, it propagates to upstream PR open-wallet-standard#181 as a single rebased commit on top of main. The readme job that's been silently failing will pass, and open-wallet-standard#181 becomes mergeable. @njdawn should then be able to merge it directly.

If you'd rather a different squash policy (e.g., keep your 3 commits + my rebase fix as a 4th), let me know and I'll restructure.

Two community members (including @0xsnackbaker) are pinging on open-wallet-standard#181 asking about the merge timeline — this should unblock it.

daiwikmh and others added 30 commits March 25, 2026 17:52
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the core EIP-712 typed data signing function for API key
(agent) mode. Gates on EVM-only, parses typed data JSON before policy
evaluation to populate TypedDataContext, and calls EvmSigner::sign_typed_data.
Includes 6 integration tests covering happy path, non-EVM rejection,
wrong contract denial, malformed JSON, expired key, and wallet scope.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove hard-blocks in ops.rs and sign_message.rs that rejected API key
usage for typed data signing. Wire up the dispatcher to delegate to
sign_typed_data_with_api_key, and handle the new AllowedTypedDataContracts
policy rule in the CLI policy display.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t bypass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix Node.js and Python binding tests: the denied-chain test case
  used typed data with chainId=8453 but chain="ethereum", which now
  correctly triggers the new chain mismatch check instead of AllowedChains.
  Updated tests to use matching chainId so AllowedChains is exercised.
- Run cargo fmt to satisfy CI formatting checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…efactor

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add raw 32-byte hash signing (secp256k1 chains) and EIP-7702
authorization signing (EVM chains) across Rust core, Node, and
Python bindings. Both paths support owner-mode and API-key-mode
with full policy evaluation.

Refactors key_ops to share policy enforcement via
enforce_policy_and_decrypt_key_with_raw_hex, eliminating
duplicated boilerplate across sign_with_api_key,
sign_message_with_api_key, and the new sign_hash_with_api_key.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
parse_quantity_bytes now checks the decimal string length against
a conservative upper bound (3 * max_len + 1 digits) before entering
the O(n·m) byte-conversion loop. Prevents CPU abuse from million-digit
nonce or chain_id strings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge the two separate `use ows_signer` statements into a single
import block, resolving the CI cargo fmt check failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deduplicate the chainId parsing logic that was repeated in the domain
validation (step 5b) and TypedDataContext construction (step 6) of
sign_typed_data_with_api_key.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verify that an empty contracts list [] in AllowedTypedDataContracts
denies all typed data signing, confirming no accidental allow-all
behavior when no contracts are specified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use consistent terminology across the codebase — the rest of OWS
uses 'allowlist', so the AllowedTypedDataContracts docs should too.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the `import copy` statement from inside the function body to
the module-level imports where it belongs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use a shared EVM chain-id helper instead of ad hoc parsing in typed-data and x402 flows.

Stop reusing transaction.raw_hex for typed-data JSON bytes and validate the executable policy path against typed_data.raw_json instead.

Add Node and Python binding coverage for AllowedTypedDataContracts.
Separate packages for framework-specific adapters:

- @open-wallet-standard/viem — owsToViemAccount() creates a viem
  Account with signing delegated to OWS (key never leaves vault)
- @open-wallet-standard/solana — owsToSolanaKeypair() creates a
  @solana/web3.js Keypair from an OWS wallet (32→64 byte key
  expansion via @noble/curves ed25519)

Tests: 10 viem + 6 solana, all passing locally.
CI: two new jobs (node-viem, node-solana) depending on node build.
Single package with subpath exports:
- @open-wallet-standard/adapters/viem → owsToViemAccount()
- @open-wallet-standard/adapters/solana → owsToSolanaKeypair()

Peer deps (viem, @solana/web3.js) are optional — only needed
if importing the corresponding adapter.

16 tests passing (10 viem, 6 solana).

Addresses review feedback: single package is easier to extend
with ethers, CosmJS, wagmi, Sui adapters later.
- Fix raw hex message signing: handle 0x-prefixed hex strings correctly
  instead of treating them as UTF-8
- Lazy-load adapters in barrel export so solana-only users don't crash
  from missing viem peer dep (and vice versa)
- signTransaction: serialize TransactionSerializable objects via viem's
  serializeTransaction() instead of JSON.stringify
- package.json exports: use "default" condition instead of "require" so
  ESM import works
- solana adapter: narrow try-catch to only JSON.parse, surface missing
  ed25519 key as a distinct error
viem's toAccount expects signTransaction to return an RLP-encoded signed
transaction (sendRawTransaction-ready). Previously returned just the raw
ECDSA signature bytes.

Now: serialize tx → keccak256 → sign → re-serialize with r/s/v attached.
Test updated to verify EIP-1559 prefix and length.
EIP-1559/2930 transactions need yParity (0 or 1), not legacy v (27/28).
Pass raw recovery byte as yParity to serializeTransaction.
OWS sign_transaction already applies keccak256 internally. Pass raw
serialized tx bytes instead of pre-hashing, which was producing
keccak256(keccak256(tx)) — invalid signatures.
Use result.recovery_id from OWS SignResult for yParity, with fallback
to parsing from signature bytes if not present.
viem's toAccount always passes TransactionSerializable objects, never
raw strings. Remove the string branch that would silently produce
corrupt output by serializing an empty object.
ggonzalez94 and others added 28 commits April 6, 2026 15:01
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…m-account

feat: add @open-wallet-standard/adapters (viem + solana)
…istake_x402

fix: printing mistake while executing x402 payments
…712-api-key-signing

feat: EIP-712 typed data signing via API key
Register Tempo (eip155:4217) and Hyperliquid (eip155:999) as known EVM
chains with friendly name aliases and default RPC endpoints.
…eip7702

# Conflicts:
#	bindings/node/__test__/index.spec.mjs
#	bindings/python/tests/test_bindings.py
#	ows/crates/ows-lib/src/key_ops.rs
…/nj/wdk-integration

feat: native wdk integration with ows
No behavioral changes. Applies rustfmt to bindings/node/src/lib.rs
and bindings/python/src/lib.rs.
…chain-alias

feat: add Tempo and Hyperliquid chain aliases
…n-hash-and-eip7702

feat: add signHash and signAuthorization
…/chore/bump-version-1.3.0

chore: bump version to 1.3.0
…formatting

style: run cargo fmt on node and python SDK bindings
…/nj/publish-npm-adaptors-package

feat: publish npm adaptors package
…/chore/bump-version-1.3.1

chore: bump version to 1.3.1
…/nj/add-adapters-readme

Nj/add adapters readme
…/chore/bump-version-1.3.2

chore: bump version to 1.3.2
Closes open-wallet-standard#219

Adds NEAR Protocol as a supported chain in OWS. Ed25519 over canonical
Borsh transactions, with SHA-256 pre-hash before signing. Genesis-agnostic
signer (network binding lives in Transaction.block_hash, same model
Algorand uses for `gh`).

## Chain spec

  ChainType:                 Near
  CAIP-2:                    near:mainnet, near:testnet
  BIP-44 coin type:          397 (SLIP-44)
  Curve:                     Ed25519 (existing Curve::Ed25519)
  Default derivation path:   m/44'/397'/{index}' (NEAR Foundation, hardened)
  Address (implicit):        64-char lowercase hex of the ed25519 pubkey
  TX serialization:          Borsh
  TX signing preimage:       Ed25519(SHA-256(borsh(Transaction)))
  encode_signed_transaction: borsh(Transaction) || 0x00 || sig64
  signMessage (V1):          raw ed25519 over message bytes (parity with
                             Solana). NEP-413 follow-up tracked.
  Default RPC:               https://rpc.{mainnet,testnet}.near.org

## Files (23 changed, +702 / -50)

Core implementation:
- ows-signer/src/chains/near.rs (new) — NearSigner, 15 inline tests
- ows-signer/src/chains/mod.rs — module + factory registration
- ows-core/src/chain.rs — ChainType::Near, KNOWN_CHAINS rows, namespace,
  coin_type, FromStr, Display, serde tests, parse_chain test. Also fixes
  pre-existing Spark omission from ALL_CHAIN_TYPES (was [10] now [12]).
- ows-core/src/config.rs — default RPC URLs
- ows-lib/src/near_rpc.rs (new) — broadcast_tx_commit JSON-RPC helper.
  Sanitized error messages: never embeds raw RPC response payload in
  Display output (would leak operational data — tx details, account
  identifiers — into logs/UI).
- ows-lib/src/lib.rs, ops.rs — module export, broadcast dispatch,
  3 integration-test loops include "near".
- ows-pay/src/discovery.rs — format_near() with yoctoNEAR divisor
  (10^24 = 1 NEAR), wired into format_price(). 6 unit tests.

Bindings tests:
- bindings/node/__test__/index.spec.mjs — "near" in chain coverage,
  account count 10 -> 12 (Spark omission fix), spark:* assertion.
- bindings/python/tests/test_bindings.py — same pattern, also fixes
  pre-existing missing "xrpl" in derive-all loop.

Documentation (DUAL — docs/ AND website-docs/md/ kept in sync):
- 07-supported-chains.md: chain families table, non-EVM networks,
  shorthand aliases, HD derivation tree.
- 02-signing-interface.md: chain-specific signMessage / signTransaction
  semantics for NEAR.

README normalization:
- ows/README.md, bindings/{node,python}/README.md,
  readme/templates/{ows,node,python}.md,
  readme/partials/{supported-chains,why-ows}.md,
  skills/ows/SKILL.md — chain enumerations now consistently include
  Spark, Nano, NEAR (also fixed pre-existing Nano omissions).

## Why these design choices

- No new dependencies. ed25519-dalek, sha2, hex, bs58, base64 are
  already in the workspace. We do NOT pull near-primitives (heavy:
  tokio + dozens of transitive crates). NearSigner is ~330 LoC.
- Implicit account, not named. derive_address returns the implicit
  account ID (hex(pubkey)). Named accounts (alice.near) require
  on-chain registration and are out of scope for a stateless signer.
- HD derivation reuses existing SLIP-10. NEAR's hardened-only path
  works through the existing ed25519 SLIP-10 implementation in hd.rs.
  No new HD machinery (in contrast to Algorand PR open-wallet-standard#124 which needed
  BIP32-Ed25519 with Peikert).
- Stateless signing. block_hash inside the Transaction binds it to a
  network, so the signer doesn't need a network parameter at signing
  time. Same model Algorand PR open-wallet-standard#124 uses.

## Production reference

A production x402 facilitator with full NEAR support runs at
facilitator.ultravioletadao.xyz, source at UltravioletaDAO/x402-rs
(Rust, ~600 LoC NEAR implementation). It uses NEP-366 SignedDelegateAction
for gasless meta-transactions on the facilitator side; this PR provides
the underlying signer primitives. Meta-tx wrapping belongs in ows-pay
as a follow-up.

## Test strategy

- 15 unit tests inline in chains/near.rs covering trait properties,
  derivation, RFC 8032 vector 1 implicit address, sign/verify roundtrip,
  determinism, sign_message parity, invalid key length, sha256 prehash
  semantics, encode_signed layout, sig length rejection, empty input
  rejection, full extract -> sign -> encode pipeline.
- Byte-parity test against near-api-js test/unit/transactions/data/
  transaction1.json: hard-coded canonical Transaction borsh hex (transfer
  test.near -> whatever.near, nonce=1). Verifies extract_signable_bytes
  is identity AND encode_signed_transaction emits exactly
  tx_bytes || 0x00 || sig64 matching near-api-js's borsh(SignedTransaction)
  layout.
- 6 format_near unit tests: whole / fractional / zero / one yoctoNEAR /
  typical NEP-141 storage deposit / non-numeric input.
- 3 ops.rs integration loops include "near" (derive_address_all_chains,
  mnemonic_wallet_sign_message_all_chains, mnemonic_wallet_sign_tx_all_chains).

CI gates verified locally:
  cargo fmt --all --check                                    clean
  cargo clippy --workspace --all-targets -- -D warnings      clean
  cargo test --workspace                                     604 passed
  .githooks/pre-commit                                       pass

## Out of scope (tracked as follow-ups)

- NEP-413 prefixed message signing (V1 sign_message is raw ed25519
  for parity with Solana; NEP-413 is a structurally distinct flow).
- NEP-366 SignedDelegateAction (belongs in ows-pay, not the signer).
- Named-account resolution (alice.near -> AccountId requires RPC).
- Live testnet broadcast smoke test (Nano open-wallet-standard#109 didn't include one
  either; can be added behind #[ignore] later).

References:
- near-api-js: https://github.com/near/near-api-js
- NEP-413: https://github.com/near/NEPs/blob/master/neps/nep-0413.md
- NEP-366: https://github.com/near/NEPs/blob/master/neps/nep-0366.md
- SLIP-44 coin type 397: https://github.com/satoshilabs/slips/blob/master/slip-0044.md
- Nano PR open-wallet-standard#109 (merged) — closest structural template
- Algorand PR open-wallet-standard#124 (open) — sibling ed25519 chain addition

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…near-chain-support

feat: add NEAR Protocol chain support (Ed25519 + Borsh + NEP-413)
…enerated

This is a rebase of open-wallet-standard#181 (soumyacodes007/feature/stellar-integration) onto
current main (post NEAR + Spark merges). All three of soumyacodes007's
original commits (03edec5, 4160e9e, 4b5c554) are squashed here to keep the
PR a single clean commit on top of the latest main.

Original Stellar work:
  - Ed25519 signing with hardened SEP-0005 derivation m/44'/148'/{index}'
  - StrKey Base32 address encoding (G...) — 56 chars
  - Canonical TransactionSignaturePayload XDR signing (handles TxV0, Tx,
    TxFeeBump variants)
  - encode_signed_transaction wraps the signature as DecoratedSignature
    inside a TransactionEnvelope, broadcastable to Horizon
  - testnet/mainnet network passphrase isolation via
    signer_for_chain_id(chain_type, chain_id) — addresses @njdawn's
    original review finding
  - Stellar broadcast helper (Horizon submit-transaction), Friendbot
    testnet faucet support in ows fund
  - Stellar fixture for the cross-chain sign_transaction integration test

Conflicts resolved during the rebase:
  - ows-core/src/{chain.rs, config.rs}: ChainType::Stellar added alongside
    Nano + Near; ALL_CHAIN_TYPES bumped to [13]; KNOWN_CHAINS gains
    stellar/stellar-testnet; namespace/coin_type/from_namespace/Display/
    FromStr/serde tests extended with stellar
  - ows-signer/src/chains/mod.rs: Stellar arm joined the Nano + Near arms
    in the chain match
  - ows-lib/src/key_ops.rs, src/ops.rs: imports merged
    (signer_for_chain_info now exported alongside signer_for_chain),
    broadcast_stellar joined the broadcast dispatch alongside
    broadcast_nano + broadcast_tx_commit for NEAR
  - ows-lib/Cargo.toml: stellar-xdr dev-dependency kept; ows-signer pinned
    to =1.3.2 (current workspace version)
  - All 7 generated READMEs (bindings/{node,python}/README.md, ows/README.md,
    and the 4 ows/crates/*/README.md files) regenerated via
    ./readme/generate.sh — readme job verified locally with --check
  - bindings/{node,python} tests: universal wallet count 12 -> 13;
    stellar:* startswith assertion added; "stellar" added to the
    derive-all chain coverage loop
  - docs/07-supported-chains.md: chain families table + non-EVM networks
    + shorthand aliases + HD derivation tree all gain Stellar entries
  - readme/templates/ows.md, readme/partials/supported-chains.md:
    Stellar appended after NEAR

CI gates verified locally after rebase:
  - cargo fmt --all --check                                    clean
  - cargo clippy --workspace --all-targets -- -D warnings      clean
  - cargo test --workspace                                     640 passed, 0 failed
  - ./readme/generate.sh --check                               clean

Original PR: open-wallet-standard#181
Closes review feedback: @njdawn 2026-04-04

Co-Authored-By: 0xultravioleta <0xultravioleta@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5021ce2d-f6bf-4fbd-9410-11e3ed9979df

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

9 participants