feat: Fixing payment stuff

This commit is contained in:
arafatkatze
2025-07-30 08:49:22 -07:00
parent de30ce7fc5
commit 9b222296cb
8 changed files with 92 additions and 18 deletions
+10 -1
View File
@@ -26,10 +26,19 @@ export async function getUserCredits(controller: Controller, request: EmptyReque
throw new Error("Failed to fetch user credits data")
}
const packedPaymentTransactions = (paymentTransactions || []).map((tx) => {
return {
paidAt: JSON.stringify(tx),
creatorId: tx.id,
amountCents: tx.amountCents,
credits: tx.credits,
}
})
return UserCreditsData.create({
balance: balance ? { currentBalance: balance.balance / 100 } : { currentBalance: 0 },
usageTransactions: usageTransactions,
paymentTransactions: paymentTransactions,
paymentTransactions: packedPaymentTransactions,
})
} catch (error) {
console.error(`Failed to fetch user credits data: ${error}`)
@@ -78,7 +78,7 @@ export async function refreshGroqModels(controller: Controller, request: EmptyRe
inputPrice: staticModelInfo?.inputPrice || 0,
outputPrice: staticModelInfo?.outputPrice || 0,
cacheWritesPrice: (staticModelInfo as any)?.cacheWritesPrice || 0,
cacheReadsPrice: (staticModelInfo as any).cacheReadsPrice || 0,
cacheReadsPrice: (staticModelInfo as any)?.cacheReadsPrice || 0,
description: generateModelDescription(rawModel, staticModelInfo),
}
+2 -4
View File
@@ -129,10 +129,8 @@ export class ClineAccountService {
console.error("Failed to fetch user ID for usage transactions")
return undefined
}
const data = await this.authenticatedRequest<{ paymentTransactions: PaymentTransaction[] }>(
`/api/v1/users/${me.id}/payments`,
)
return data.paymentTransactions
const data = await this.authenticatedRequest<{ items: PaymentTransaction[] }>(`/api/v1/users/${me.id}/payments`)
return data.items
} catch (error) {
console.error("Failed to fetch payment transactions (RPC):", error)
return undefined
+16 -2
View File
@@ -43,10 +43,24 @@ export interface UsageTransaction {
}
export interface PaymentTransaction {
paidAt: string
creatorId: string
id: string
transactionId: string
userId: string
amountCents: number
credits: number
type: string
status: string
providerReference: string
metadata: {
customer_id: string
event_id: string
payment_id: string
provider: string
subscription_id: string
}
createdAt: string
updatedAt: string
completedAt: string
}
export interface OrganizationBalanceResponse {
@@ -11,7 +11,7 @@ import VSCodeButtonLink from "../common/VSCodeButtonLink"
import { AccountWelcomeView } from "./AccountWelcomeView"
import { CreditBalance } from "./CreditBalance"
import CreditsHistoryTable from "./CreditsHistoryTable"
import { convertProtoUsageTransactions, getClineUris, getMainRole } from "./helpers"
import { convertProtoPaymentTransactions, convertProtoUsageTransactions, getClineUris, getMainRole } from "./helpers"
type AccountViewProps = {
clineUser: ClineUser | null
@@ -112,7 +112,7 @@ export const ClineAccountView = ({ clineUser, userOrganizations, activeOrganizat
setBalance(newBalance ?? null)
const newUsage = convertProtoUsageTransactions(response.usageTransactions)
setUsageData((prev) => (deepEqual(newUsage, prev) ? prev : newUsage))
const newPaymentsData = response.paymentTransactions
const newPaymentsData = convertProtoPaymentTransactions(response.paymentTransactions)
setPaymentsData((prev) => (deepEqual(newPaymentsData, prev) ? prev : newPaymentsData))
} catch (error) {
console.error("Failed to fetch user credit:", error)
@@ -1,4 +1,4 @@
import type { PaymentTransaction, UsageTransaction } from "@shared/ClineAccount"
import type { PaymentTransaction as ClinePaymentTransaction, UsageTransaction } from "@shared/ClineAccount"
import { VSCodeDataGrid, VSCodeDataGridCell, VSCodeDataGridRow } from "@vscode/webview-ui-toolkit/react"
import { useState } from "react"
import { formatDollars, formatTimestamp } from "@/utils/format"
@@ -7,7 +7,7 @@ import { TabButton } from "../mcp/configuration/McpConfigurationView"
interface CreditsHistoryTableProps {
isLoading: boolean
usageData: UsageTransaction[]
paymentsData: PaymentTransaction[]
paymentsData: ClinePaymentTransaction[]
showPayments?: boolean
}
@@ -93,7 +93,7 @@ const CreditsHistoryTable = ({ isLoading, usageData, paymentsData, showPayments
{paymentsData.map((row, index) => (
<VSCodeDataGridRow key={index}>
<VSCodeDataGridCell grid-column="1">
{formatTimestamp(row.paidAt)}
{formatTimestamp(row.completedAt)}
</VSCodeDataGridCell>
<VSCodeDataGridCell grid-column="2">{`$${formatDollars(row.amountCents)}`}</VSCodeDataGridCell>
<VSCodeDataGridCell grid-column="3">{`${row.credits}`}</VSCodeDataGridCell>
+43 -2
View File
@@ -1,5 +1,11 @@
import type { UsageTransaction as ClineAccountUsageTransaction } from "@shared/ClineAccount"
import type { UsageTransaction as ProtoUsageTransaction } from "@shared/proto/cline/account"
import type {
PaymentTransaction as ClineAccountPaymentTransaction,
UsageTransaction as ClineAccountUsageTransaction,
} from "@shared/ClineAccount"
import type {
PaymentTransaction as ProtoPaymentTransaction,
UsageTransaction as ProtoUsageTransaction,
} from "@shared/proto/cline/account"
export const getMainRole = (roles?: string[]) => {
if (!roles) return undefined
@@ -45,3 +51,38 @@ export function convertProtoUsageTransaction(protoTransaction: ProtoUsageTransac
export function convertProtoUsageTransactions(protoTransactions: ProtoUsageTransaction[]): ClineAccountUsageTransaction[] {
return protoTransactions.map(convertProtoUsageTransaction)
}
/**
* Converts a protobuf PaymentTransaction to a ClineAccount PaymentTransaction
* This is a temporary workaround for the fact that the protobuf definition is out of sync with the API response.
*/
export function convertProtoPaymentTransaction(protoTransaction: ProtoPaymentTransaction): ClineAccountPaymentTransaction {
try {
const unpackedData = JSON.parse(protoTransaction.paidAt)
return unpackedData as ClineAccountPaymentTransaction
} catch (error) {
console.error("Failed to parse packed payment transaction:", error)
// Return a default/empty object that won't crash the UI
return {
id: "",
transactionId: "",
userId: "",
amountCents: 0,
credits: 0,
type: "",
status: "",
providerReference: "",
metadata: {},
createdAt: "",
updatedAt: "",
completedAt: "",
} as unknown as ClineAccountPaymentTransaction
}
}
/**
* Converts an array of protobuf PaymentTransactions to ClineAccount PaymentTransactions
*/
export function convertProtoPaymentTransactions(protoTransactions: ProtoPaymentTransaction[]): ClineAccountPaymentTransaction[] {
return protoTransactions.map(convertProtoPaymentTransaction)
}
@@ -1,7 +1,6 @@
import { useEffect } from "react"
import { ClineMessage, ClineSayTool } from "@shared/ExtensionMessage"
import { ChatState } from "../types/chatTypes"
import { useDeepCompareEffect } from "react-use"
/**
* Custom hook for managing button state based on messages
@@ -19,7 +18,7 @@ export function useButtonState(messages: ClineMessage[], chatState: ChatState) {
} = chatState
// Update button state based on last message
useDeepCompareEffect(() => {
useEffect(() => {
if (lastMessage) {
switch (lastMessage.type) {
case "ask":
@@ -146,7 +145,20 @@ export function useButtonState(messages: ClineMessage[], chatState: ChatState) {
break
}
}
}, [lastMessage, secondLastMessage])
}, [
lastMessage?.type,
lastMessage?.partial,
lastMessage?.ask,
lastMessage?.text,
lastMessage?.say,
secondLastMessage?.ask,
setSendingDisabled,
setEnableButtons,
setPrimaryButtonText,
setSecondaryButtonText,
setDidClickCancel,
chatState,
])
// Reset button state when no messages
useEffect(() => {