Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/ten-donuts-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

Fix waitUntil facilitator param not being respected
19 changes: 19 additions & 0 deletions .github/workflows/auto-assign.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Auto Author Assign

on:
pull_request:
types: [opened, reopened, ready_for_review]

permissions:
pull-requests: write

jobs:
assign-author:
runs-on: ubuntu-latest
if: |
github.event.pull_request.author_association == 'MEMBER' ||
github.event.pull_request.author_association == 'OWNER' ||
github.event.pull_request.author_association == 'COLLABORATOR' ||
github.event.pull_request.author_association == 'CONTRIBUTOR'
steps:
- uses: toshimaru/auto-author-assign@16f0022cf3d7970c106d8d1105f75a1165edb516 # v2.1.1
90 changes: 85 additions & 5 deletions apps/playground-web/src/app/api/paywall/route.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,90 @@
import { NextResponse } from "next/server";
import { type NextRequest, NextResponse } from "next/server";
import { createThirdwebClient, defineChain } from "thirdweb";
import { toUnits } from "thirdweb/utils";
import { facilitator, settlePayment } from "thirdweb/x402";
import { token } from "../../payments/x402/components/constants";

// Allow streaming responses up to 5 minutes
export const maxDuration = 300;

export async function GET(_req: Request) {
return NextResponse.json({
success: true,
message: "Payment successful. You have accessed the protected route.",
export async function GET(request: NextRequest) {
const client = createThirdwebClient({
secretKey: process.env.THIRDWEB_SECRET_KEY as string,
});

const BACKEND_WALLET_ADDRESS = process.env.ENGINE_BACKEND_WALLET as string;
// const BACKEND_WALLET_ADDRESS = process.env.ENGINE_BACKEND_SMART_WALLET as string;
const ENGINE_VAULT_ACCESS_TOKEN = process.env
.ENGINE_VAULT_ACCESS_TOKEN as string;
const API_URL = `https://${process.env.NEXT_PUBLIC_API_URL || "api.thirdweb.com"}`;

const twFacilitator = facilitator({
baseUrl: `${API_URL}/v1/payments/x402`,
client,
serverWalletAddress: BACKEND_WALLET_ADDRESS,
vaultAccessToken: ENGINE_VAULT_ACCESS_TOKEN,
});

const paymentData = request.headers.get("X-PAYMENT");
const queryParams = request.nextUrl.searchParams;

const chainId = queryParams.get("chainId");

if (!chainId) {
return NextResponse.json(
{ error: "Missing required parameters" },
{ status: 400 },
);
}

const amount = queryParams.get("amount") || "0.01";
const tokenAddress = queryParams.get("tokenAddress") || token.address;
const decimals = queryParams.get("decimals") || token.decimals.toString();
const waitUntil =
(queryParams.get("waitUntil") as "simulated" | "submitted" | "confirmed") ||
"simulated";

const result = await settlePayment({
resourceUrl: "https://playground-web.thirdweb.com/api/paywall",
method: "GET",
paymentData,
network: defineChain(Number(chainId)),
price: {
amount: toUnits(amount, parseInt(decimals)).toString(),
asset: {
address: tokenAddress as `0x${string}`,
decimals: decimals ? parseInt(decimals) : token.decimals,
},
},
routeConfig: {
description: "Access to paid content",
},
waitUntil,
facilitator: twFacilitator,
});

if (result.status === 200) {
// payment successful, execute the request
return NextResponse.json(
{
success: true,
message: "Payment successful. You have accessed the protected route.",
payment: {
amount,
tokenAddress,
},
receipt: result.paymentReceipt,
},
{
status: 200,
headers: result.responseHeaders,
},
);
}

// otherwise, request payment
return NextResponse.json(result.responseBody, {
status: result.status,
headers: result.responseHeaders,
});
}
85 changes: 0 additions & 85 deletions apps/playground-web/src/middleware.ts

This file was deleted.

10 changes: 5 additions & 5 deletions packages/thirdweb/src/x402/facilitator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type WaitUntil = "simulated" | "submitted" | "confirmed";
export type ThirdwebX402FacilitatorConfig = {
client: ThirdwebClient;
serverWalletAddress: string;
waitUtil?: WaitUntil;
waitUntil?: WaitUntil;
vaultAccessToken?: string;
baseUrl?: string;
};
Expand All @@ -40,7 +40,7 @@ export type ThirdwebX402Facilitator = {
settle: (
payload: RequestedPaymentPayload,
paymentRequirements: RequestedPaymentRequirements,
waitUtil?: WaitUntil,
waitUntil?: WaitUntil,
) => Promise<FacilitatorSettleResponse>;
supported: (filters?: {
chainId: number;
Expand Down Expand Up @@ -185,14 +185,14 @@ export function facilitator(
async settle(
payload: RequestedPaymentPayload,
paymentRequirements: RequestedPaymentRequirements,
waitUtil?: WaitUntil,
waitUntil?: WaitUntil,
): Promise<FacilitatorSettleResponse> {
const url = config.baseUrl ?? DEFAULT_BASE_URL;

let headers = { "Content-Type": "application/json" };
const authHeaders = await facilitator.createAuthHeaders();
headers = { ...headers, ...authHeaders.settle };
const waitUtilParam = waitUtil || config.waitUtil;
const waitUntilParam = waitUntil || config.waitUntil;

const res = await fetch(`${url}/settle`, {
method: "POST",
Expand All @@ -201,7 +201,7 @@ export function facilitator(
x402Version: payload.x402Version,
paymentPayload: payload,
paymentRequirements: paymentRequirements,
...(waitUtilParam ? { waitUtil: waitUtilParam } : {}),
...(waitUntilParam ? { waitUntil: waitUntilParam } : {}),
}),
});

Expand Down
Loading