Skip to content

feat(pay): add HTTP provider for browser/Node.js environments#7132

Open
ganchoradkov wants to merge 7 commits intov2.0from
feat/pay-http-provider
Open

feat(pay): add HTTP provider for browser/Node.js environments#7132
ganchoradkov wants to merge 7 commits intov2.0from
feat/pay-http-provider

Conversation

@ganchoradkov
Copy link
Copy Markdown
Member

@ganchoradkov ganchoradkov commented Jan 16, 2026

Summary

  • Add HttpProvider that makes direct HTTP calls to the Pay API, enabling the SDK to work in any JavaScript environment with fetch support (browsers, Node.js 18+, etc.)
  • This removes the dependency on native/WASM modules for web environments

Changes

  • New HttpProvider (src/providers/http.ts)

    • Direct HTTP calls to Pay API endpoints
    • Payment ID extraction from various link formats (URLs, WalletConnect URIs, query params)
    • Action caching from getPaymentOptions for efficient getRequiredPaymentActions calls
    • Automatic resolution of "build" actions via /fetch endpoint
    • Automatic polling for final payment status in confirmPayment
  • Updated provider detection (src/providers/index.ts)

    • Auto-detection order: native → http → wasm
    • HTTP provider selected when fetch is available and native module isn't
  • Updated types (src/types/provider.ts)

    • Added "http" to PayProviderType

Test plan

  • Added comprehensive test suite with 30 tests (test/http-provider.spec.ts)
  • All 71 tests pass (41 existing + 30 new)
  • Manual testing in browser environment
  • Manual testing in Node.js environment

Usage

import { WalletConnectPay } from "@walletconnect/pay";

// Auto-detects HTTP provider in browser/Node.js environments
const pay = new WalletConnectPay({
  projectId: "your-project-id",
  apiKey: "your-api-key",
});

// Or explicitly use HTTP provider
import { createHttpProvider } from "@walletconnect/pay";
const httpProvider = createHttpProvider(config);

🚧 Work in Progress - Ready for initial review

🤖 Generated with Claude Code


Note

Enables Pay SDK to run in any JS environment with fetch by adding a direct-API HTTP provider and integrating it into provider auto-detection.

  • New HttpProvider (src/providers/http.ts): direct Pay API calls, payment ID parsing from multiple link formats (URLs, wc: URIs, query params), caching of option actions, resolving build actions via /fetch, and polling in confirmPayment
  • Provider detection update (src/providers/index.ts): prefer native, then http when fetch is available; exports HTTP provider; updated error message
  • Types (src/types/provider.ts): adds "http" to PayProviderType
  • Version (src/constants/client.ts): bump SDK_VERSION to 1.0.2
  • Tests (test/http-provider.spec.ts): comprehensive suite covering headers, parsing, action resolution, polling, and errors

Written by Cursor Bugbot for commit ad3db68. This will update automatically on new commits. Configure here.

ganchoradkov and others added 2 commits January 16, 2026 10:45
Add HttpProvider that makes direct HTTP calls to the Pay API,
enabling the Pay SDK to work in any JavaScript environment with
fetch support (browsers, Node.js 18+, etc.).

Changes:
- Add HttpProvider implementation with full API support
- Add payment ID extraction from various link formats
- Add action caching and build action resolution
- Add automatic polling for payment status
- Update provider detection to use HTTP when native unavailable
- Add comprehensive test suite with 30 tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ganchoradkov ganchoradkov force-pushed the feat/pay-http-provider branch from 14babd8 to 2c7572c Compare January 16, 2026 08:50
@ganchoradkov ganchoradkov marked this pull request as ready for review January 16, 2026 08:51
Copilot AI review requested due to automatic review settings January 16, 2026 08:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an HTTP provider that enables the WalletConnect Pay SDK to work in browser and Node.js environments by making direct HTTP calls to the Pay API, removing the dependency on native/WASM modules for web environments.

Changes:

  • Added HttpProvider class that uses fetch API for all payment operations
  • Updated provider auto-detection to prioritize native → HTTP → WASM
  • Extended PayProviderType to include "http" option

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/pay/src/providers/http.ts New HTTP provider implementation with payment ID extraction, action caching, and automatic polling
packages/pay/src/providers/index.ts Updated provider detection to include HTTP provider as second priority
packages/pay/src/types/provider.ts Added "http" to PayProviderType union
packages/pay/test/http-provider.spec.ts Comprehensive test suite with 30 tests covering all HTTP provider functionality
packages/react-native-compat/android/build.gradle Updated yttrium-wcpay dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

export class HttpProvider implements PayProvider {
private readonly baseUrl: string;
private readonly headers: Record<string, string>;
private cachedOptions: CachedPaymentOption[] = [];
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The cachedOptions array is shared across multiple payment flows and could lead to incorrect behavior if the same HttpProvider instance is used for multiple different payments simultaneously. Consider keying the cache by paymentId (e.g., Map<string, CachedPaymentOption[]>) to isolate cache entries per payment.

Copilot uses AI. Check for mistakes.
);

// Cache the raw options for use by getRequiredPaymentActions
this.cachedOptions = response.options.map((o) => ({
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The cache is completely replaced on each getPaymentOptions call, which means if a user calls getPaymentOptions for payment A, then for payment B, the cached actions for payment A are lost. This breaks the caching mechanism if multiple payments are handled with the same provider instance. The cache should be keyed by paymentId to avoid this issue.

Suggested change
this.cachedOptions = response.options.map((o) => ({
this.cachedOptions[paymentId] = response.options.map((o) => ({

Copilot uses AI. Check for mistakes.
Comment on lines +411 to +413
while (!result.isFinal) {
const delay = result.pollInMs ?? 1000;
await new Promise((resolve) => setTimeout(resolve, delay));
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The infinite polling loop has no timeout or maximum retry limit, which could cause the function to hang indefinitely if the server never returns isFinal: true. Consider adding a maximum retry count or total timeout to prevent infinite loops.

Copilot uses AI. Check for mistakes.
const cached = this.cachedOptions.find((o) => o.optionId === params.optionId);

let rawActions: RawAction[];
if (cached && cached.actions.length > 0) {
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The condition cached.actions.length > 0 excludes valid cached options that have zero actions. If an option legitimately has no actions, it should still be served from cache rather than making an unnecessary API call. Consider removing the length check or explicitly checking for null/undefined.

Suggested change
if (cached && cached.actions.length > 0) {
if (cached && Array.isArray(cached.actions)) {

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +144
throw new PayError(
"UNKNOWN",
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

All HTTP errors are categorized as 'UNKNOWN' error code. Consider mapping HTTP error responses to more specific error codes (e.g., 404 → PAYMENT_OPTIONS, 422 → CONFIRM_PAYMENT) to provide more meaningful error information to SDK consumers.

Suggested change
throw new PayError(
"UNKNOWN",
// Map HTTP status codes to more specific PayError codes where possible
let errorCode: string;
switch (response.status) {
case 404:
errorCode = "PAYMENT_OPTIONS";
break;
case 422:
errorCode = "CONFIRM_PAYMENT";
break;
default:
errorCode = "UNKNOWN";
break;
}
throw new PayError(
errorCode,

Copilot uses AI. Check for mistakes.
Comment on lines +238 to +250
expect(mockFetch).toHaveBeenCalledWith(
expect.stringContaining("/v1/gateway/payment/pay_headers/options"),
expect.objectContaining({
method: "POST",
headers: expect.objectContaining({
"Content-Type": "application/json",
"Api-Key": "test-api-key",
"Sdk-Name": "test-sdk",
"Sdk-Version": "1.0.0",
"Sdk-Platform": "test",
}),
}),
);
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The test validates that headers are sent but doesn't verify that the bundleId from the config is included in any header or request. If bundleId should be sent (which is part of PayProviderConfig), this should be tested, or if it's intentionally not used by HttpProvider, this should be documented.

Copilot uses AI. Check for mistakes.
cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

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.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

ganchoradkov and others added 3 commits January 21, 2026 11:11
- Update SDK_VERSION to 1.0.2 to match package.json
- Add missing account field to RawPaymentOption and transformPaymentOption
- Support both apiKey and appId for authentication headers
- Fix linting issues in test file
Extract nested functions to class methods, add type guards for action
types, and create helper methods for transformations. Improves code
organization without changing functionality.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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