Skip to content

Widget Integration

Install the widget package:

Terminal window
npm install @proof-of-spend/widget
# or
bun add @proof-of-spend/widget

Import and use the widget in your React application:

import { ProofOfSpendWidget } from '@proof-of-spend/widget';
function App() {
return (
<ProofOfSpendWidget
apiUrl="https://your-oauth-server.com"
onVerified={(data) => {
console.log('Task verified:', data);
// Handle verification data
}}
/>
);
}
PropTypeRequiredDescription
apiUrlstringYesOAuth backend URL
onVerified(data: VerificationData) => voidYesCalled when task is verified
theme'light' | 'dark'NoWidget theme (default: 'light')
providersProvider[]NoAvailable providers (default: all)
classNamestringNoCustom CSS class
type Provider = 'openai' | 'anthropic' | 'google';
interface VerificationData {
taskId: string;
response: string;
provider: Provider;
cost: number;
timestamp: string;
proof: {
accessToken: string;
apiCallHash: string;
};
}

Restrict available providers:

<ProofOfSpendWidget
apiUrl="https://your-oauth-server.com"
providers={['openai', 'anthropic']}
onVerified={handleVerification}
/>

Apply custom styles:

<ProofOfSpendWidget
apiUrl="https://your-oauth-server.com"
className="my-custom-widget"
theme="dark"
onVerified={handleVerification}
/>
.my-custom-widget {
max-width: 600px;
margin: 0 auto;
border-radius: 12px;
}

Handle errors gracefully:

<ProofOfSpendWidget
apiUrl="https://your-oauth-server.com"
onVerified={handleVerification}
onError={(error) => {
console.error('Widget error:', error);
// Show user-friendly error message
}}
/>

The widget uses an internal state machine with these states:

  1. loading: Initial state, fetching configuration
  2. provider-selection: User selects OAuth provider
  3. task-ready: Task loaded and ready for user
  4. submitting: User submitted response, calling API
  5. verifying: Verifying API call proof
  6. verified: Task successfully verified
  7. error: Error occurred

For more control, use the useProofOfSpend hook:

import { useProofOfSpend } from '@proof-of-spend/widget';
function CustomWidget() {
const {
state,
task,
response,
setResponse,
selectProvider,
submitResponse,
reset,
} = useProofOfSpend({
apiUrl: 'https://your-oauth-server.com',
});
return (
<div>
{state === 'provider-selection' && (
<button onClick={() => selectProvider('openai')}>
Use OpenAI
</button>
)}
{state === 'task-ready' && (
<div>
<p>{task.prompt}</p>
<textarea
value={response}
onChange={(e) => setResponse(e.target.value)}
/>
<button onClick={submitResponse}>Submit</button>
</div>
)}
</div>
);
}

The widget includes comprehensive tests:

Terminal window
# Run widget tests
cd proof-of-spend-widget
bun test