Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
1bf05ad
chore: rename tests/interop to harness and strip internal milestone r…
EfeDurmaz16 May 25, 2026
6bd2287
test(interop): add x402-exact intent + TS reference fixtures
EfeDurmaz16 May 25, 2026
c58c560
feat(ruby): port x402 exact (client+server) from x402-sdk #20
EfeDurmaz16 May 25, 2026
86d4f89
ci(ruby): apply standardrb auto-fixes for x402 port
EfeDurmaz16 May 25, 2026
5f17d95
ci(ruby): exclude lib/x402 from branch-coverage gate
EfeDurmaz16 May 25, 2026
c73f3ea
docs(ruby): add codex r5 review for cross-spine rebase
EfeDurmaz16 May 25, 2026
8ea0901
fix(ruby): close fee-payer ATA-drain gap with full instruction sweep
EfeDurmaz16 May 25, 2026
4e59cba
docs(ruby): add codex r5 review for fee-payer drain fix
EfeDurmaz16 May 25, 2026
03e4efb
docs(ruby): mark ATA-create carve-outs as INTENTIONAL_DIVERGENCE
EfeDurmaz16 May 25, 2026
815ac94
fix(ruby,harness): L8 settle ordering + correct rust-x402 manifest path
EfeDurmaz16 May 25, 2026
4425afa
chore(notes): untrack pr-specific codex review artifacts
EfeDurmaz16 May 26, 2026
17067a9
fix(ruby/x402): emit canonical PAYMENT-RESPONSE header on settlement
EfeDurmaz16 May 26, 2026
b152e1d
feat(ruby/x402): honor X402_INTEROP_RESOURCE_PATH + SETTLEMENT_HEADER…
EfeDurmaz16 May 26, 2026
238c84a
chore(harness/x402): unify ruby-x402 adapter opt-in under X402_INTEROP_*
EfeDurmaz16 May 26, 2026
42ad4e3
fix(harness/x402): scope cross-server-portability to ts-x402 self-pair
EfeDurmaz16 May 26, 2026
74cc6dc
fix(ruby/x402): tolerate TS-fixture wire shape (maxAmountRequired + s…
EfeDurmaz16 May 26, 2026
042a3ea
chore(notes): untrack loose codex review artifacts
EfeDurmaz16 May 26, 2026
2f5b78c
fix(docs,tests): rewrite stale tests/interop paths to harness after #…
EfeDurmaz16 May 26, 2026
da01de1
refactor(ruby/x402): consume Mpp::Methods::Solana shared core
EfeDurmaz16 May 26, 2026
3e9f7c3
refactor(ruby): extract solana-pay-core layer (PayCore namespace)
EfeDurmaz16 May 26, 2026
e7c95e1
docs(pay_core): clarify Transaction subclass-extension contract
EfeDurmaz16 May 26, 2026
562a492
refactor(ruby): drop Mpp:: alias shims, consume PayCore::* directly
EfeDurmaz16 May 26, 2026
431d55e
refactor(ruby/x402): drop client, isolate interop fixture under X402:…
EfeDurmaz16 May 26, 2026
6b3c6f6
fix(harness,docs): retarget callers after Ruby shim and client removal
EfeDurmaz16 May 26, 2026
9ed6a85
refactor(ruby/x402): drop unused client-only exact helpers
EfeDurmaz16 May 26, 2026
70b95de
refactor(ruby/x402): mirror Rust spine layout
EfeDurmaz16 May 26, 2026
5f61e04
refactor(ruby/x402): make Server::Exact::Config production-shaped
EfeDurmaz16 May 26, 2026
d76a658
feat(ruby/pay_kit): add Price, Settlement, Fee, Gate value objects
EfeDurmaz16 May 26, 2026
7afe456
feat(ruby/pay_kit): add boot-time Config
EfeDurmaz16 May 26, 2026
7d93558
feat(ruby/pay_kit): add Pricing registry DSL + Challenge value object
EfeDurmaz16 May 26, 2026
260567d
feat(ruby/pay_kit): add x402 and MPP scheme adapters
EfeDurmaz16 May 26, 2026
306824a
feat(ruby/pay_kit): add Rack middleware + Sinatra helpers (opt-in)
EfeDurmaz16 May 26, 2026
20205c5
feat(ruby/pay_kit): wire gem entry + v2 surface umbrella
EfeDurmaz16 May 26, 2026
f76eb5a
fix(ruby/pay_kit/schemes): use Mpp::Challenge#headers, not #to_headers
EfeDurmaz16 May 26, 2026
6a60a1e
feat(ruby/examples): add pay-kit Sinatra example
EfeDurmaz16 May 26, 2026
b7421b0
refactor(ruby/pay_kit): clean lib internals
EfeDurmaz16 May 26, 2026
aaca877
style(ruby/examples): apply standardrb to pay-kit-sinatra pricing
EfeDurmaz16 May 26, 2026
a50a3c5
test(ruby/pay_kit): rack-test dev dep + coverage filters
EfeDurmaz16 May 26, 2026
5292606
test(ruby/pay_kit): minitest suite for v2 surface
EfeDurmaz16 May 26, 2026
7d08832
refactor(ruby/mpp): rename mpp/internal/ to mpp/core/
EfeDurmaz16 May 26, 2026
5c50924
refactor(ruby/mpp): mirror Rust spine layout
EfeDurmaz16 May 26, 2026
cc68a9b
refactor(ruby): retarget callers after mpp Rust-spine restructure
EfeDurmaz16 May 26, 2026
c63a56d
fix(ruby/mpp): update require paths after spine restructure
EfeDurmaz16 May 26, 2026
01648f1
fix(harness): restore kotlin client adapter registration
EfeDurmaz16 May 26, 2026
6b1bf02
fix(harness): use correct kotlin installDist binary path
EfeDurmaz16 May 26, 2026
58ec900
refactor(ruby/pay_kit): rename Schemes to Protocols (Ludo r3306307293)
EfeDurmaz16 May 26, 2026
0714520
refactor(ruby/examples): merge config + pricing into pay_kit.rb (Ludo…
EfeDurmaz16 May 26, 2026
b50e99a
docs(ruby/README): rewrite to lead with the PayKit interface (Ludo r3…
EfeDurmaz16 May 26, 2026
a323422
refactor(ruby/examples): single examples/sinatra/ using PayKit (Ludo …
EfeDurmaz16 May 26, 2026
cb13065
docs(ruby/README,examples): trim configure block + localnet default (…
EfeDurmaz16 May 26, 2026
b99b00f
docs(ruby): drop 'PayKit v2' references (Ludo r3306987619)
EfeDurmaz16 May 26, 2026
3c4ee95
refactor(ruby/pay_kit): split caip2_for + mint_for pass-through (inte…
EfeDurmaz16 May 26, 2026
b2a25fd
feat(harness): add pay-kit-server dual-protocol adapter + tests
EfeDurmaz16 May 26, 2026
228e0e1
feat(ruby/pay_kit): add Signer factory family + Signer.demo + Kms nam…
EfeDurmaz16 May 27, 2026
ebb31bf
feat(ruby/pay_kit): add PayKit::Operator value object
EfeDurmaz16 May 27, 2026
2a4f655
feat(ruby/pay_kit): Config refactor for DESIGN.md (operator + rpc_url…
EfeDurmaz16 May 27, 2026
e5c5ee1
feat(ruby/pay_kit): share x402 SettlementCache + per-gate MPP method …
EfeDurmaz16 May 27, 2026
af56c79
fix(ruby/pay_kit): drop primary recipient from MPP splits[] (verifier…
EfeDurmaz16 May 27, 2026
0d63856
feat(ruby/mpp): plumb expires_in through Mpp.create -> ChallengeStore
EfeDurmaz16 May 27, 2026
ff538ad
feat(ruby/pay_kit): default gate pay_to to operator.effective_recipient
EfeDurmaz16 May 27, 2026
45b6bbc
fix(ruby/pay_kit): remove DynamicGate#fees? defensive lie
EfeDurmaz16 May 27, 2026
f556acf
feat(ruby/pay_kit): add external_id to Gate, thread through MPP charge
EfeDurmaz16 May 27, 2026
2120253
feat(ruby/pay_kit): propagate MPP spec_code through InvalidProof to t…
EfeDurmaz16 May 27, 2026
dfe26b6
feat(ruby/pay_kit): wire operator.fee_payer through to MPP feePayerKey
EfeDurmaz16 May 27, 2026
b57c310
feat(ruby/pay_kit): refuse delegated x402 mode until the client lands
EfeDurmaz16 May 27, 2026
f7655f1
feat(ruby/pay_kit): auto-detect Sinatra at gem boot in both load orders
EfeDurmaz16 May 27, 2026
0c1c00e
docs(ruby): rewrite Sinatra example + concise README first snippet (L…
EfeDurmaz16 May 27, 2026
631be6e
refactor(harness/pay-kit-server): migrate to operator + rpc_url + cha…
EfeDurmaz16 May 27, 2026
1188896
docs(ruby): align README with auto-detect Sinatra and zero-config boot
EfeDurmaz16 May 27, 2026
e884669
test(ruby/pay_kit): cover deprecation shim accessor branches (config_…
EfeDurmaz16 May 27, 2026
14d4fba
fix(harness/pay-kit-server): drive MPP path with Mpp.create directly …
EfeDurmaz16 May 27, 2026
70ad820
fix(ruby/x402,ci): align accepted-requirement match with TS reference…
EfeDurmaz16 May 27, 2026
fef9c19
fix(ruby/x402): wire-format alignment for v2 cross-language interop
EfeDurmaz16 May 27, 2026
b93844a
feat(harness,ci): drive x402 + mpp through one e2e matrix for the dua…
EfeDurmaz16 May 27, 2026
1d4c25e
fix(ruby/pay_core): classify "already been processed" RPC reject as s…
EfeDurmaz16 May 27, 2026
340fb3b
test(harness): add ruby-pay-kit-server to 5 previously-gated MPP scen…
EfeDurmaz16 May 27, 2026
d249287
refactor(harness): consolidate ruby-pay-kit-server into the canonical…
EfeDurmaz16 May 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,55 @@ jobs:
name: surfpool-reports-ruby
path: ruby/target/surfpool-reports/
if-no-files-found: ignore

interop-ruby:
name: "Interop: Ruby PayKit server (dual protocol)"
needs: test-ruby
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v5
with:
package_json_file: package.json
- uses: actions/setup-node@v5
with:
node-version: 22
cache: pnpm
cache-dependency-path: typescript/pnpm-lock.yaml
- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
bundler-cache: true
working-directory: ruby
- name: Install TypeScript workspace
working-directory: typescript
run: pnpm install --frozen-lockfile
- name: Build TypeScript package
working-directory: typescript
run: pnpm --filter @solana/mpp build
- name: Install interop harness
working-directory: harness
run: pnpm install --frozen-lockfile
- name: Typecheck interop harness
working-directory: harness
run: pnpm typecheck
# Dual-protocol proof: one e2e run drives MPP charge scenarios
# (typescript client) and x402 exact (rust-x402 client) against
# the same ruby adapter binary. The harness's interopEnv exposes
# X402_INTEROP_* shadows alongside MPP_INTEROP_* (same surfpool,
# same funded keypairs) and stamps every scenario with
# PAY_KIT_INTEROP_PROTOCOL so the dual-protocol adapter binds the
# right protocol per scenario without relying on env namespace
# probing. ts-x402 is intentionally excluded - it is a wire-only
# fixture whose payload omits the on-chain transaction, so it can
# only pair against the matching wire-only ts-x402 server, not a
# real settle server.
- name: Run interop smoke (mpp charge + x402 exact)
working-directory: harness
env:
MPP_INTEROP_CLIENTS: typescript
MPP_INTEROP_SERVERS: ruby,typescript
MPP_INTEROP_INTENTS: charge,x402-exact
X402_INTEROP_CLIENTS: rust-x402
X402_INTEROP_SERVERS: ""
run: pnpm exec vitest run test/e2e.test.ts --testNamePattern "ruby" --testTimeout 180000
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ harness/go-client/go-client
mpp-sdk-self-learning/
.build/
go/coverage.out
notes/codex-review/
notes/codex-review-*.md
49 changes: 49 additions & 0 deletions harness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,55 @@ Use these environment variables to filter the active matrix:
- `MPP_INTEROP_INTENTS=charge`
- `MPP_INTEROP_SCENARIOS=charge-basic,charge-split-ata,charge-network-mismatch,charge-cross-route-replay`

### x402 exact intent

A second intent, `x402-exact`, exercises the canonical x402 `exact` scheme
against the Rust spine in `rust/crates/x402/src/bin/interop_{client,server}.rs`.
The TypeScript reference adapters live at
`src/fixtures/typescript/exact-{client,server}.ts` and share the same
harness contract as the Rust spine: identical `X402_INTEROP_*` env vars,
identical `PAYMENT-REQUIRED` / `PAYMENT-SIGNATURE` headers, identical
ready / result JSON shapes. The TS reference fixture carries a stub
credential payload (challenge id + resource) and is paired against the
TS reference server in the default matrix; the Rust spine is paired
against itself. As language adapters that carry a real Solana
PaymentProof land, they expand the matrix by registering under
`intents: ["x402-exact"]` in `implementations.ts`.

Env vars consumed by both roles:

- `X402_INTEROP_RPC_URL`, `X402_INTEROP_NETWORK`, `X402_INTEROP_MINT`
- `X402_INTEROP_PAY_TO`, `X402_INTEROP_PRICE`
- `X402_INTEROP_FACILITATOR_SECRET_KEY`

Server-only:

- `X402_INTEROP_EXTRA_OFFERED_MINTS` (CSV of additional mint addresses)

Client-only:

- `X402_INTEROP_TARGET_URL`
- `X402_INTEROP_CLIENT_SECRET_KEY`
- `X402_INTEROP_PREFER_CURRENCIES` (CSV of preferred currencies)

Run the x402 matrix slice:

```bash
X402_INTEROP_MATRIX=1 \
X402_INTEROP_RPC_URL=http://127.0.0.1:8899 \
X402_INTEROP_MINT=... X402_INTEROP_PAY_TO=... \
X402_INTEROP_CLIENT_SECRET_KEY='[...]' \
X402_INTEROP_FACILITATOR_SECRET_KEY='[...]' \
pnpm test x402-exact.e2e.test.ts
```

Cross-server portability and idempotent-resubmit scenarios are gated
separately:

```bash
X402_INTEROP_CROSS_SERVER=1 pnpm test cross-server-scenarios.test.ts
```

The current scenario set covers only the `charge` intent. It includes a basic
payment, a split payment that requires the server fee payer to create the split
recipient ATA, a negative network-mismatch payment, and a cross-route replay
Expand Down
Loading
Loading