Jaspers Hub

jaspers / alpaca

pluginOfficialReviewed★ 0↓ 0

Alpaca: Alpaca brokerage plugin: stock/option market data, account, positions, orders, and order placement/cancellation, with watchlist, account, and blotter views.

2.6 KB
1import { useBridge, useData } from '@jaspers-ai/sdk'
2import { useState } from 'react'
3import { LIVE_ORDER_LIVE_KEY, type PendingLiveOrder } from '../actions'
4
5export function LiveOrderGate() {
6 const bridge = useBridge()
7 const pending = useData(`live/${LIVE_ORDER_LIVE_KEY}`) as PendingLiveOrder | null | undefined
8 const [submitting, setSubmitting] = useState(false)
9
10 if (!pending || typeof pending !== 'object' || !pending.id) return null
11
12 const decide = (approved: boolean) => {
13 if (submitting) return
14 setSubmitting(true)
15 void bridge
16 .runSource('alpaca/confirm-live-order', { id: pending.id, approved }, { fresh: true })
17 .finally(() => setSubmitting(false))
18 }
19
20 return (
21 <div className="al-gate" role="alertdialog" aria-label="First live trade approval">
22 <div className="al-gate-head">
23 <span className="al-badge al-badge-live">LIVE ORDER APPROVAL</span>
24 <strong>Confirm first live trade on this connection</strong>
25 </div>
26 <div className="al-gate-grid">
27 <div>
28 <span className="al-card-label">Symbol</span>
29 <div className="al-card-value">{pending.symbol}</div>
30 </div>
31 <div>
32 <span className="al-card-label">Side</span>
33 <div className={`al-card-value ${pending.side === 'buy' ? 'al-up' : 'al-down'}`}>{pending.side}</div>
34 </div>
35 <div>
36 <span className="al-card-label">Quantity</span>
37 <div className="al-card-value">{pending.quantity}</div>
38 </div>
39 <div>
40 <span className="al-card-label">Order type</span>
41 <div className="al-card-value">{pending.orderType}</div>
42 </div>
43 <div>
44 <span className="al-card-label">Estimated value</span>
45 <div className="al-card-value">{pending.estimatedValue}</div>
46 </div>
47 </div>
48 <p className="al-gate-disclaimer">
49 Live order on your brokerage account. This is your trade, at your risk — see{' '}
50 <button
51 type="button"
52 className="al-link"
53 onClick={() => void bridge.openLink('https://jsprai.com/terms')}
54 >
55 jsprai.com/terms
56 </button>{' '}
57 §7.
58 </p>
59 <div className="al-gate-actions">
60 <button
61 type="button"
62 className="al-btn al-btn-danger"
63 disabled={submitting}
64 onClick={() => decide(true)}
65 >
66 Approve live order
67 </button>
68 <button
69 type="button"
70 className="al-btn"
71 disabled={submitting}
72 onClick={() => decide(false)}
73 >
74 Decline
75 </button>
76 </div>
77 </div>
78 )
79}