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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ NEXT_PUBLIC_REOWN_PROJECT_ID=""
WEBHOOK_SECRET=""
CRYPTO_TO_FIAT_PAYEE_ADDRESS=""

FEE_PERCENTAGE_FOR_PAYMENT=""
FEE_ADDRESS_FOR_PAYMENT=""

# Optional
# NEXT_PUBLIC_GTM_ID=""
# NEXT_PUBLIC_CRYPTO_TO_FIAT_TRUSTED_ORIGINS=""
Expand Down
12 changes: 12 additions & 0 deletions src/components/payment-route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ interface PaymentRouteProps {
onClick?: () => void;
variant?: "default" | "selected";
routeType?: RouteTypeInfo;
platformFee?: {
percentage: number;
address: string;
};
}

export function PaymentRoute({
Expand All @@ -22,6 +26,7 @@ export function PaymentRoute({
onClick,
variant = "default",
routeType,
platformFee,
}: PaymentRouteProps) {
const isDirectPayment =
routeType?.type === "direct" ||
Expand Down Expand Up @@ -120,6 +125,13 @@ export function PaymentRoute({
<div className="text-sm text-zinc-600">
{typeof route.speed === "number" ? `~${route.speed}s` : "Fast"}
</div>
{platformFee?.percentage && platformFee?.percentage > 0 && (
<div className="text-sm text-zinc-600 mt-1">
<span className="text-purple-600">
{platformFee?.percentage}% {route.token} platform fee
</span>
</div>
)}
</div>
</div>
</button>
Expand Down
7 changes: 6 additions & 1 deletion src/components/payment-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export function PaymentSection({ invoice }: PaymentSectionProps) {
const { mutateAsync: sendPaymentIntent } =
api.invoice.sendPaymentIntent.useMutation();
const {
data: paymentRoutes,
data: paymentRoutesData,
refetch,
isLoading: isLoadingPaymentRoutes,
} = api.invoice.getPaymentRoutes.useQuery(
Expand All @@ -134,6 +134,9 @@ export function PaymentSection({ invoice }: PaymentSectionProps) {
},
);

const paymentRoutes = paymentRoutesData?.routes;
const platformFee = paymentRoutesData?.platformFee;

// Extract the chain from invoice currency
const invoiceChain = getCurrencyChain(invoice.paymentCurrency);

Expand Down Expand Up @@ -587,6 +590,7 @@ export function PaymentSection({ invoice }: PaymentSectionProps) {
selectedRoute,
invoiceChain,
)}
platformFee={platformFee}
/>
)}

Expand All @@ -603,6 +607,7 @@ export function PaymentSection({ invoice }: PaymentSectionProps) {
isSelected={selectedRoute?.id === route.id}
onClick={() => setSelectedRoute(route)}
routeType={getRouteType(route, invoiceChain)}
platformFee={platformFee}
/>
))}
</div>
Expand Down
1 change: 1 addition & 0 deletions src/lib/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export interface PaymentRoute {
chain: string;
token: string;
isCryptoToFiat?: boolean;
platformFee?: number;
}
14 changes: 12 additions & 2 deletions src/server/routers/invoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,13 @@ export const invoiceRouter = router({
params.append("token", input.token);
}

if (process.env.FEE_PERCENTAGE_FOR_PAYMENT) {
params.append("feePercentage", process.env.FEE_PERCENTAGE_FOR_PAYMENT);
}
if (process.env.FEE_ADDRESS_FOR_PAYMENT) {
params.append("feeAddress", process.env.FEE_ADDRESS_FOR_PAYMENT);
}

const paymentEndpoint = `/v2/request/${invoice.requestId}/pay?${params.toString()}`;

const response = await apiClient.get(paymentEndpoint);
Expand Down Expand Up @@ -398,7 +405,7 @@ export const invoiceRouter = router({
const { requestId, walletAddress } = input;

const response = await apiClient.get(
`/v2/request/${requestId}/routes?wallet=${walletAddress}`,
`/v2/request/${requestId}/routes?wallet=${walletAddress}&feePercentage=${process.env.FEE_PERCENTAGE_FOR_PAYMENT}&feeAddress=${process.env.FEE_ADDRESS_FOR_PAYMENT}`,
);

if (response.status !== 200) {
Expand All @@ -408,7 +415,10 @@ export const invoiceRouter = router({
});
}

return response.data.routes;
return {
routes: response.data.routes,
platformFee: response.data.platformFee,
};
}),
sendPaymentIntent: publicProcedure
.input(
Expand Down
11 changes: 11 additions & 0 deletions src/server/routers/payment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,20 @@ export const paymentRouter = router({
});
}

const feePercentage = process.env.FEE_PERCENTAGE_FOR_PAYMENT;
const feeAddress = process.env.FEE_ADDRESS_FOR_PAYMENT;

const response = await apiClient.post("v2/payouts", {
amount: input.amount.toString(),
payee: input.payee,
invoiceCurrency: input.invoiceCurrency,
paymentCurrency: input.paymentCurrency,
...(feePercentage && feeAddress
? {
feePercentage: feePercentage,
feeAddress: feeAddress,
}
: {}),
});

if (response.status !== 201) {
Expand Down Expand Up @@ -65,6 +74,8 @@ export const paymentRouter = router({
payee: payout.payee,
invoiceCurrency: payout.invoiceCurrency,
paymentCurrency: payout.paymentCurrency,
feePercentage: process.env.FEE_PERCENTAGE_FOR_PAYMENT,
feeAddress: process.env.FEE_ADDRESS_FOR_PAYMENT,
}))
: undefined,
requestIds: input.requestIds,
Expand Down