Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions typescript/packages/x402-axios/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
* @param axiosClient - The Axios instance to add the interceptor to
* @param walletClient - A wallet client that can sign transactions and create payment headers
* @param paymentRequirementsSelector - A function that selects the payment requirements from the response
* @param config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @param x402Config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @returns The modified Axios instance with the payment interceptor
*
* @example
Expand All @@ -44,7 +44,7 @@ import {
* axios.create(),
* signer,
* undefined,
* { svmConfig: { rpcUrl: "http://localhost:8899" } }
* svmConfig: { "solana-devnet": { rpcUrl: "http://localhost:8899"} }
* );
*
* // The client will automatically handle 402 responses
Expand All @@ -55,7 +55,7 @@ export function withPaymentInterceptor(
axiosClient: AxiosInstance,
walletClient: Signer | MultiNetworkSigner,
paymentRequirementsSelector: PaymentRequirementsSelector = selectPaymentRequirements,
config?: X402Config,
x402Config?: X402Config,
) {
axiosClient.interceptors.response.use(
response => response,
Expand Down Expand Up @@ -93,7 +93,7 @@ export function withPaymentInterceptor(
walletClient,
x402Version,
selectedPaymentRequirements,
config,
x402Config,
);

(originalConfig as { __is402Retry?: boolean }).__is402Retry = true;
Expand Down
8 changes: 4 additions & 4 deletions typescript/packages/x402-fetch/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
* @param walletClient - The wallet client used to sign payment messages
* @param maxValue - The maximum allowed payment amount in base units (defaults to 0.1 USDC)
* @param paymentRequirementsSelector - A function that selects the payment requirements from the response
* @param config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @param x402Config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @returns A wrapped fetch function that handles 402 responses automatically
*
* @example
Expand All @@ -40,7 +40,7 @@ import {
*
* // With custom RPC configuration
* const fetchWithPay = wrapFetchWithPayment(fetch, wallet, undefined, undefined, {
* svmConfig: { rpcUrl: "http://localhost:8899" }
* svmConfig: { "solana-devnet": { rpcUrl: "http://localhost:8899"} }
* });
*
* // Make a request that may require payment
Expand All @@ -57,7 +57,7 @@ export function wrapFetchWithPayment(
walletClient: Signer | MultiNetworkSigner,
maxValue: bigint = BigInt(0.1 * 10 ** 6), // Default to 0.10 USDC
paymentRequirementsSelector: PaymentRequirementsSelector = selectPaymentRequirements,
config?: X402Config,
x402Config?: X402Config,
) {
return async (input: RequestInfo, init?: RequestInit) => {
const response = await fetch(input, init);
Expand Down Expand Up @@ -94,7 +94,7 @@ export function wrapFetchWithPayment(
walletClient,
x402Version,
selectedPaymentRequirements,
config,
x402Config,
);

if (!init) {
Expand Down
13 changes: 7 additions & 6 deletions typescript/packages/x402/src/client/createPaymentHeader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { generateKeyPairSigner, type TransactionSigner } from "@solana/kit";
import { createPaymentHeader } from "./createPaymentHeader";
import { PaymentRequirements } from "../types/verify";
import * as exactSvmClient from "../schemes/exact/svm/client";
import { X402Config } from "../types";

vi.mock("../schemes/exact/svm/client", () => ({
createPaymentHeader: vi.fn(),
Expand Down Expand Up @@ -37,18 +38,18 @@ describe("createPaymentHeader", () => {
it("should propagate config to exact SVM client", async () => {
// Arrange
const customRpcUrl = "http://localhost:8899";
const config = { svmConfig: { rpcUrl: customRpcUrl } };
const x402Config: X402Config = { svmConfig: { "solana-devnet": { rpcUrl: customRpcUrl } } };
vi.mocked(exactSvmClient.createPaymentHeader).mockResolvedValue("mock_payment_header");

// Act
await createPaymentHeader(svmSigner, 1, paymentRequirements, config);
await createPaymentHeader(svmSigner, 1, paymentRequirements, x402Config);

// Assert
expect(exactSvmClient.createPaymentHeader).toHaveBeenCalledWith(
svmSigner,
1,
paymentRequirements,
config,
x402Config,
);
});

Expand All @@ -70,18 +71,18 @@ describe("createPaymentHeader", () => {

it("should call exact SVM client with empty config object", async () => {
// Arrange
const config = {};
const x402Config: X402Config = {};
vi.mocked(exactSvmClient.createPaymentHeader).mockResolvedValue("mock_payment_header");

// Act
await createPaymentHeader(svmSigner, 1, paymentRequirements, config);
await createPaymentHeader(svmSigner, 1, paymentRequirements, x402Config);

// Assert
expect(exactSvmClient.createPaymentHeader).toHaveBeenCalledWith(
svmSigner,
1,
paymentRequirements,
config,
x402Config,
);
});
});
Expand Down
6 changes: 3 additions & 3 deletions typescript/packages/x402/src/client/createPaymentHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import { X402Config } from "../types/config";
* @param client - The signer wallet instance used to create the payment header
* @param x402Version - The version of the X402 protocol to use
* @param paymentRequirements - The payment requirements containing scheme and network information
* @param config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @param x402Config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @returns A promise that resolves to the created payment header string
*/
export async function createPaymentHeader(
client: Signer | MultiNetworkSigner,
x402Version: number,
paymentRequirements: PaymentRequirements,
config?: X402Config,
x402Config?: X402Config,
): Promise<string> {
// exact scheme
if (paymentRequirements.scheme === "exact") {
Expand Down Expand Up @@ -46,7 +46,7 @@ export async function createPaymentHeader(
svmClient,
x402Version,
paymentRequirements,
config,
x402Config,
);
}
throw new Error("Unsupported network");
Expand Down
12 changes: 6 additions & 6 deletions typescript/packages/x402/src/facilitator/facilitator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { TransactionSigner } from "@solana/kit";
* @param client - The public client used for blockchain interactions
* @param payload - The signed payment payload containing transfer parameters and signature
* @param paymentRequirements - The payment requirements that the payload must satisfy
* @param config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @param x402Config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @returns A ValidPaymentRequest indicating if the payment is valid and any invalidation reason
*/
export async function verify<
Expand All @@ -35,7 +35,7 @@ export async function verify<
client: ConnectedClient | Signer,
payload: PaymentPayload,
paymentRequirements: PaymentRequirements,
config?: X402Config,
x402Config?: X402Config,
): Promise<VerifyResponse> {
// exact scheme
if (paymentRequirements.scheme === "exact") {
Expand All @@ -54,7 +54,7 @@ export async function verify<
client as TransactionSigner,
payload,
paymentRequirements,
config,
x402Config,
);
}
}
Expand All @@ -76,14 +76,14 @@ export async function verify<
* @param client - The signer wallet used for blockchain interactions
* @param payload - The signed payment payload containing transfer parameters and signature
* @param paymentRequirements - The payment requirements that the payload must satisfy
* @param config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @param x402Config - Optional configuration for X402 operations (e.g., custom RPC URLs)
* @returns A SettleResponse indicating if the payment is settled and any settlement reason
*/
export async function settle<transport extends Transport, chain extends Chain>(
client: Signer,
payload: PaymentPayload,
paymentRequirements: PaymentRequirements,
config?: X402Config,
x402Config?: X402Config,
): Promise<SettleResponse> {
// exact scheme
if (paymentRequirements.scheme === "exact") {
Expand All @@ -102,7 +102,7 @@ export async function settle<transport extends Transport, chain extends Chain>(
client as TransactionSigner,
payload,
paymentRequirements,
config,
x402Config,
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion typescript/packages/x402/src/paywall/gen/template.ts

Large diffs are not rendered by default.

17 changes: 9 additions & 8 deletions typescript/packages/x402/src/schemes/exact/svm/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as paymentUtils from "../../utils";
import { PaymentRequirements } from "../../../types/verify";
import * as rpc from "../../../shared/svm/rpc";
import { createAndSignPayment, createPaymentHeader } from "./client";
import { X402Config } from "../../../types";

// Mocking dependencies
vi.mock("../../../shared/svm/rpc");
Expand Down Expand Up @@ -359,11 +360,11 @@ describe("SVM Client", () => {
it("should use custom RPC URL from config for devnet", async () => {
// Arrange
const customRpcUrl = "http://localhost:8899";
const config = { svmConfig: { rpcUrl: customRpcUrl } };
const x402Config: X402Config = { svmConfig: { "solana-devnet": { rpcUrl: customRpcUrl } } };
const getRpcClientSpy = vi.spyOn(rpc, "getRpcClient");

// Act
await createAndSignPayment(clientSigner, 1, paymentRequirements, config);
await createAndSignPayment(clientSigner, 1, paymentRequirements, x402Config);

// Assert
expect(getRpcClientSpy).toHaveBeenCalledWith("solana-devnet", customRpcUrl);
Expand All @@ -372,12 +373,12 @@ describe("SVM Client", () => {
it("should use custom RPC URL from config for mainnet", async () => {
// Arrange
const customRpcUrl = "https://custom-mainnet.com";
const config = { svmConfig: { rpcUrl: customRpcUrl } };
const x402Config: X402Config = { svmConfig: { solana: { rpcUrl: customRpcUrl } } };
const mainnetRequirements = { ...paymentRequirements, network: "solana" as const };
const getRpcClientSpy = vi.spyOn(rpc, "getRpcClient");

// Act
await createAndSignPayment(clientSigner, 1, mainnetRequirements, config);
await createAndSignPayment(clientSigner, 1, mainnetRequirements, x402Config);

// Assert
expect(getRpcClientSpy).toHaveBeenCalledWith("solana", customRpcUrl);
Expand All @@ -396,11 +397,11 @@ describe("SVM Client", () => {

it("should use default RPC when svmConfig is undefined", async () => {
// Arrange
const config = {}; // Empty config object
const x402Config: X402Config = {}; // Empty config object
const getRpcClientSpy = vi.spyOn(rpc, "getRpcClient");

// Act
await createAndSignPayment(clientSigner, 1, paymentRequirements, config);
await createAndSignPayment(clientSigner, 1, paymentRequirements, x402Config);

// Assert
expect(getRpcClientSpy).toHaveBeenCalledWith("solana-devnet", undefined);
Expand All @@ -409,12 +410,12 @@ describe("SVM Client", () => {
it("should propagate config through createPaymentHeader → createAndSignPayment", async () => {
// Arrange
const customRpcUrl = "http://localhost:8899";
const config = { svmConfig: { rpcUrl: customRpcUrl } };
const x402Config: X402Config = { svmConfig: { "solana-devnet": { rpcUrl: customRpcUrl } } };
const getRpcClientSpy = vi.spyOn(rpc, "getRpcClient");
vi.mocked(paymentUtils.encodePayment).mockReturnValue("encoded_header");

// Act
await createPaymentHeader(clientSigner, 1, paymentRequirements, config);
await createPaymentHeader(clientSigner, 1, paymentRequirements, x402Config);

// Assert - verify config was passed all the way through
expect(getRpcClientSpy).toHaveBeenCalledWith("solana-devnet", customRpcUrl);
Expand Down
Loading