@elizaos/plugin-steward-app 2.0.3-beta.5 → 2.0.3-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ApprovalQueue.d.ts +18 -0
- package/dist/ApprovalQueue.d.ts.map +1 -0
- package/dist/ApprovalQueue.js +420 -0
- package/dist/ApprovalQueue.js.map +1 -0
- package/dist/StewardLogo.d.ts +11 -0
- package/dist/StewardLogo.d.ts.map +1 -0
- package/dist/StewardLogo.js +36 -0
- package/dist/StewardLogo.js.map +1 -0
- package/dist/StewardView.d.ts +13 -0
- package/dist/StewardView.d.ts.map +1 -0
- package/dist/StewardView.helpers.d.ts +15 -0
- package/dist/StewardView.helpers.d.ts.map +1 -0
- package/dist/StewardView.helpers.js +45 -0
- package/dist/StewardView.helpers.js.map +1 -0
- package/dist/StewardView.interact.d.ts +2 -0
- package/dist/StewardView.interact.d.ts.map +1 -0
- package/dist/StewardView.interact.js +54 -0
- package/dist/StewardView.interact.js.map +1 -0
- package/dist/StewardView.js +249 -0
- package/dist/StewardView.js.map +1 -0
- package/dist/TransactionHistory.d.ts +22 -0
- package/dist/TransactionHistory.d.ts.map +1 -0
- package/dist/TransactionHistory.js +361 -0
- package/dist/TransactionHistory.js.map +1 -0
- package/dist/__fixtures__/steward-sdk-fixtures.d.ts +10 -0
- package/dist/__fixtures__/steward-sdk-fixtures.d.ts.map +1 -0
- package/dist/__fixtures__/steward-sdk-fixtures.js +60 -0
- package/dist/__fixtures__/steward-sdk-fixtures.js.map +1 -0
- package/dist/actions/wallet-action-shared.d.ts +15 -0
- package/dist/actions/wallet-action-shared.d.ts.map +1 -0
- package/dist/actions/wallet-action-shared.js +16 -0
- package/dist/actions/wallet-action-shared.js.map +1 -0
- package/dist/api/binance-skill-helpers.d.ts +21 -0
- package/dist/api/binance-skill-helpers.d.ts.map +1 -0
- package/dist/api/binance-skill-helpers.js +790 -0
- package/dist/api/binance-skill-helpers.js.map +1 -0
- package/dist/api/bsc-trade.d.ts +36 -0
- package/dist/api/bsc-trade.d.ts.map +1 -0
- package/dist/api/bsc-trade.js +796 -0
- package/dist/api/bsc-trade.js.map +1 -0
- package/dist/api/trade-safety.d.ts +35 -0
- package/dist/api/trade-safety.d.ts.map +1 -0
- package/dist/api/trade-safety.js +56 -0
- package/dist/api/trade-safety.js.map +1 -0
- package/dist/api/tx-service.d.ts +53 -0
- package/dist/api/tx-service.d.ts.map +1 -0
- package/dist/api/tx-service.js +206 -0
- package/dist/api/tx-service.js.map +1 -0
- package/dist/api/wallet-bsc-routes.d.ts +63 -0
- package/dist/api/wallet-bsc-routes.d.ts.map +1 -0
- package/dist/api/wallet-bsc-routes.js +337 -0
- package/dist/api/wallet-bsc-routes.js.map +1 -0
- package/dist/api/wallet-capability.d.ts +2 -0
- package/dist/api/wallet-capability.d.ts.map +1 -0
- package/dist/api/wallet-capability.js +15 -0
- package/dist/api/wallet-capability.js.map +1 -0
- package/dist/api/wallet-dex-prices.d.ts +43 -0
- package/dist/api/wallet-dex-prices.d.ts.map +1 -0
- package/dist/api/wallet-dex-prices.js +132 -0
- package/dist/api/wallet-dex-prices.js.map +1 -0
- package/dist/api/wallet-evm-balance.d.ts +72 -0
- package/dist/api/wallet-evm-balance.d.ts.map +1 -0
- package/dist/api/wallet-evm-balance.js +697 -0
- package/dist/api/wallet-evm-balance.js.map +1 -0
- package/dist/api/wallet-routes.d.ts +27 -0
- package/dist/api/wallet-routes.d.ts.map +1 -0
- package/dist/api/wallet-routes.js +556 -0
- package/dist/api/wallet-routes.js.map +1 -0
- package/dist/api/wallet-rpc.d.ts +73 -0
- package/dist/api/wallet-rpc.d.ts.map +1 -0
- package/dist/api/wallet-rpc.js +460 -0
- package/dist/api/wallet-rpc.js.map +1 -0
- package/dist/api/wallet-trade-routes.d.ts +104 -0
- package/dist/api/wallet-trade-routes.d.ts.map +1 -0
- package/dist/api/wallet-trade-routes.js +353 -0
- package/dist/api/wallet-trade-routes.js.map +1 -0
- package/dist/api/wallet-trading-profile.d.ts +31 -0
- package/dist/api/wallet-trading-profile.d.ts.map +1 -0
- package/dist/api/wallet-trading-profile.js +500 -0
- package/dist/api/wallet-trading-profile.js.map +1 -0
- package/dist/api/wallet.d.ts +60 -0
- package/dist/api/wallet.d.ts.map +1 -0
- package/dist/api/wallet.js +617 -0
- package/dist/api/wallet.js.map +1 -0
- package/dist/chain-utils.d.ts +10 -0
- package/dist/chain-utils.d.ts.map +1 -0
- package/dist/chain-utils.js +81 -0
- package/dist/chain-utils.js.map +1 -0
- package/dist/components/StewardSpatialView.d.ts +74 -0
- package/dist/components/StewardSpatialView.d.ts.map +1 -0
- package/dist/components/StewardSpatialView.js +309 -0
- package/dist/components/StewardSpatialView.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +21 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +319 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers/steward-balance.d.ts +12 -0
- package/dist/providers/steward-balance.d.ts.map +1 -0
- package/dist/providers/steward-balance.js +85 -0
- package/dist/providers/steward-balance.js.map +1 -0
- package/dist/providers/steward-receive-address.d.ts +12 -0
- package/dist/providers/steward-receive-address.d.ts.map +1 -0
- package/dist/providers/steward-receive-address.js +47 -0
- package/dist/providers/steward-receive-address.js.map +1 -0
- package/dist/register-routes.d.ts +2 -0
- package/dist/register-routes.d.ts.map +1 -0
- package/dist/register-routes.js +6 -0
- package/dist/register-routes.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +34 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/routes/steward-bridge.d.ts +202 -0
- package/dist/routes/steward-bridge.d.ts.map +1 -0
- package/dist/routes/steward-bridge.js +776 -0
- package/dist/routes/steward-bridge.js.map +1 -0
- package/dist/routes/steward-compat-routes.d.ts +21 -0
- package/dist/routes/steward-compat-routes.d.ts.map +1 -0
- package/dist/routes/steward-compat-routes.js +350 -0
- package/dist/routes/steward-compat-routes.js.map +1 -0
- package/dist/routes/wallet-browser-compat-routes.d.ts +6 -0
- package/dist/routes/wallet-browser-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-browser-compat-routes.js +402 -0
- package/dist/routes/wallet-browser-compat-routes.js.map +1 -0
- package/dist/routes/wallet-bsc-core-routes.d.ts +15 -0
- package/dist/routes/wallet-bsc-core-routes.d.ts.map +1 -0
- package/dist/routes/wallet-bsc-core-routes.js +59 -0
- package/dist/routes/wallet-bsc-core-routes.js.map +1 -0
- package/dist/routes/wallet-compat-routes.d.ts +13 -0
- package/dist/routes/wallet-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-compat-routes.js +206 -0
- package/dist/routes/wallet-compat-routes.js.map +1 -0
- package/dist/routes/wallet-core-routes.d.ts +16 -0
- package/dist/routes/wallet-core-routes.d.ts.map +1 -0
- package/dist/routes/wallet-core-routes.js +48 -0
- package/dist/routes/wallet-core-routes.js.map +1 -0
- package/dist/routes/wallet-trade-compat-routes.d.ts +11 -0
- package/dist/routes/wallet-trade-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-trade-compat-routes.js +570 -0
- package/dist/routes/wallet-trade-compat-routes.js.map +1 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.d.ts +7 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.d.ts.map +1 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.js +43 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.js.map +1 -0
- package/dist/security/wallet-os-store-actions.d.ts +14 -0
- package/dist/security/wallet-os-store-actions.d.ts.map +1 -0
- package/dist/security/wallet-os-store-actions.js +63 -0
- package/dist/security/wallet-os-store-actions.js.map +1 -0
- package/dist/services/steward-credentials.d.ts +2 -0
- package/dist/services/steward-credentials.d.ts.map +1 -0
- package/dist/services/steward-credentials.js +2 -0
- package/dist/services/steward-credentials.js.map +1 -0
- package/dist/services/steward-evm-account.d.ts +75 -0
- package/dist/services/steward-evm-account.d.ts.map +1 -0
- package/dist/services/steward-evm-account.js +279 -0
- package/dist/services/steward-evm-account.js.map +1 -0
- package/dist/services/steward-evm-bridge.d.ts +36 -0
- package/dist/services/steward-evm-bridge.d.ts.map +1 -0
- package/dist/services/steward-evm-bridge.js +78 -0
- package/dist/services/steward-evm-bridge.js.map +1 -0
- package/dist/services/steward-sidecar/health-check.d.ts +2 -0
- package/dist/services/steward-sidecar/health-check.d.ts.map +1 -0
- package/dist/services/steward-sidecar/health-check.js +2 -0
- package/dist/services/steward-sidecar/health-check.js.map +1 -0
- package/dist/services/steward-sidecar/helpers.d.ts +2 -0
- package/dist/services/steward-sidecar/helpers.d.ts.map +1 -0
- package/dist/services/steward-sidecar/helpers.js +2 -0
- package/dist/services/steward-sidecar/helpers.js.map +1 -0
- package/dist/services/steward-sidecar/process-management.d.ts +2 -0
- package/dist/services/steward-sidecar/process-management.d.ts.map +1 -0
- package/dist/services/steward-sidecar/process-management.js +2 -0
- package/dist/services/steward-sidecar/process-management.js.map +1 -0
- package/dist/services/steward-sidecar/types.d.ts +2 -0
- package/dist/services/steward-sidecar/types.d.ts.map +1 -0
- package/dist/services/steward-sidecar/types.js +2 -0
- package/dist/services/steward-sidecar/types.js.map +1 -0
- package/dist/services/steward-sidecar/wallet-setup.d.ts +2 -0
- package/dist/services/steward-sidecar/wallet-setup.d.ts.map +1 -0
- package/dist/services/steward-sidecar/wallet-setup.js +2 -0
- package/dist/services/steward-sidecar/wallet-setup.js.map +1 -0
- package/dist/services/steward-sidecar.d.ts +2 -0
- package/dist/services/steward-sidecar.d.ts.map +1 -0
- package/dist/services/steward-sidecar.js +2 -0
- package/dist/services/steward-sidecar.js.map +1 -0
- package/dist/services/steward-wallet.d.ts +25 -0
- package/dist/services/steward-wallet.d.ts.map +1 -0
- package/dist/services/steward-wallet.js +333 -0
- package/dist/services/steward-wallet.js.map +1 -0
- package/dist/steward-ui-state.d.ts +14 -0
- package/dist/steward-ui-state.d.ts.map +1 -0
- package/dist/steward-ui-state.js +46 -0
- package/dist/steward-ui-state.js.map +1 -0
- package/dist/steward-view-bundle.d.ts +3 -0
- package/dist/steward-view-bundle.d.ts.map +1 -0
- package/dist/steward-view-bundle.js +7 -0
- package/dist/steward-view-bundle.js.map +1 -0
- package/dist/types/bsc-trade.d.ts +180 -0
- package/dist/types/bsc-trade.d.ts.map +1 -0
- package/dist/types/bsc-trade.js +1 -0
- package/dist/types/bsc-trade.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/steward.d.ts +83 -0
- package/dist/types/steward.d.ts.map +1 -0
- package/dist/types/steward.js +1 -0
- package/dist/types/steward.js.map +1 -0
- package/dist/ui.d.ts +7 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +7 -0
- package/dist/ui.js.map +1 -0
- package/dist/views/bundle.js +601 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval queue — shows pending transactions that need manual approval.
|
|
3
|
+
* Polls every 10 seconds for new items.
|
|
4
|
+
*/
|
|
5
|
+
import type { StewardApprovalActionResponse, StewardPendingApproval } from "./types/steward.js";
|
|
6
|
+
interface ApprovalQueueProps {
|
|
7
|
+
getStewardPending: () => Promise<StewardPendingApproval[]>;
|
|
8
|
+
approveStewardTx: (txId: string) => Promise<StewardApprovalActionResponse>;
|
|
9
|
+
rejectStewardTx: (txId: string, reason?: string) => Promise<StewardApprovalActionResponse>;
|
|
10
|
+
copyToClipboard: (text: string) => Promise<void>;
|
|
11
|
+
setActionNotice: (text: string, tone?: "info" | "success" | "error", ttlMs?: number) => void;
|
|
12
|
+
onPendingCountChange?: (count: number) => void;
|
|
13
|
+
embedded?: boolean;
|
|
14
|
+
refreshKey?: number | string;
|
|
15
|
+
}
|
|
16
|
+
export declare function ApprovalQueue({ getStewardPending, approveStewardTx, rejectStewardTx, copyToClipboard, setActionNotice, onPendingCountChange, embedded, refreshKey, }: ApprovalQueueProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=ApprovalQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprovalQueue.d.ts","sourceRoot":"","sources":["../src/ApprovalQueue.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EACV,6BAA6B,EAC7B,sBAAsB,EAEvB,MAAM,iBAAiB,CAAC;AAEzB,UAAU,kBAAkB;IAC1B,iBAAiB,EAAE,MAAM,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAAC;IAC3D,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,6BAA6B,CAAC,CAAC;IAC3E,eAAe,EAAE,CACf,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,KACZ,OAAO,CAAC,6BAA6B,CAAC,CAAC;IAC5C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,eAAe,EAAE,CACf,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,EACnC,KAAK,CAAC,EAAE,MAAM,KACX,IAAI,CAAC;IACV,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AAsLD,wBAAgB,aAAa,CAAC,EAC5B,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,QAAgB,EAChB,UAAU,GACX,EAAE,kBAAkB,2CA8RpB"}
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, PagePanel, Spinner } from "@elizaos/ui";
|
|
3
|
+
import { useAgentElement } from "@elizaos/ui/agent-surface";
|
|
4
|
+
import { Check, Clock, Copy, X } from "lucide-react";
|
|
5
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { formatWeiValue, getChainName, truncateAddress } from "./chain-utils.js";
|
|
7
|
+
const POLL_INTERVAL_MS = 1e4;
|
|
8
|
+
function PendingApprovalActions({
|
|
9
|
+
txId,
|
|
10
|
+
onApprove,
|
|
11
|
+
onReject
|
|
12
|
+
}) {
|
|
13
|
+
const approveElement = useAgentElement({
|
|
14
|
+
id: `action-approve-${txId}`,
|
|
15
|
+
role: "button",
|
|
16
|
+
label: `Approve transaction ${txId}`,
|
|
17
|
+
group: "approval-actions",
|
|
18
|
+
description: "Approve this pending transaction"
|
|
19
|
+
});
|
|
20
|
+
const rejectElement = useAgentElement({
|
|
21
|
+
id: `action-reject-${txId}`,
|
|
22
|
+
role: "button",
|
|
23
|
+
label: `Reject transaction ${txId}`,
|
|
24
|
+
group: "approval-actions",
|
|
25
|
+
description: "Reject this pending transaction"
|
|
26
|
+
});
|
|
27
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
28
|
+
/* @__PURE__ */ jsxs(
|
|
29
|
+
Button,
|
|
30
|
+
{
|
|
31
|
+
ref: approveElement.ref,
|
|
32
|
+
...approveElement.agentProps,
|
|
33
|
+
variant: "default",
|
|
34
|
+
size: "sm",
|
|
35
|
+
className: "h-9 rounded-md bg-accent px-4 text-xs font-semibold text-accent-fg hover:bg-accent/90",
|
|
36
|
+
onClick: () => onApprove(txId),
|
|
37
|
+
"aria-label": `Approve transaction ${txId}`,
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5" }),
|
|
40
|
+
"Approve"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
/* @__PURE__ */ jsxs(
|
|
45
|
+
Button,
|
|
46
|
+
{
|
|
47
|
+
ref: rejectElement.ref,
|
|
48
|
+
...rejectElement.agentProps,
|
|
49
|
+
variant: "outline",
|
|
50
|
+
size: "sm",
|
|
51
|
+
className: "h-9 rounded-md border-status-danger/30 px-4 text-xs font-semibold text-status-danger hover:bg-status-danger-bg hover:text-status-danger",
|
|
52
|
+
onClick: () => onReject(txId),
|
|
53
|
+
"aria-label": `Reject transaction ${txId}`,
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" }),
|
|
56
|
+
"Reject"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
function RejectReasonInput({
|
|
63
|
+
txId,
|
|
64
|
+
inputId,
|
|
65
|
+
value,
|
|
66
|
+
onChange
|
|
67
|
+
}) {
|
|
68
|
+
const { ref, agentProps } = useAgentElement({
|
|
69
|
+
id: `input-reject-reason-${txId}`,
|
|
70
|
+
role: "text-input",
|
|
71
|
+
label: "Rejection reason",
|
|
72
|
+
group: "approval-actions",
|
|
73
|
+
description: "Optional reason for rejecting the transaction",
|
|
74
|
+
getValue: () => value,
|
|
75
|
+
onFill: onChange
|
|
76
|
+
});
|
|
77
|
+
return /* @__PURE__ */ jsx(
|
|
78
|
+
"input",
|
|
79
|
+
{
|
|
80
|
+
id: inputId,
|
|
81
|
+
ref,
|
|
82
|
+
...agentProps,
|
|
83
|
+
type: "text",
|
|
84
|
+
value,
|
|
85
|
+
onChange: (e) => onChange(e.target.value),
|
|
86
|
+
placeholder: "e.g., Unauthorized recipient",
|
|
87
|
+
"aria-label": "Rejection reason",
|
|
88
|
+
className: "mt-1 h-9 w-full rounded-md border border-border/40 bg-transparent px-3 text-sm text-txt placeholder:text-muted/40 focus:border-accent/40 focus:outline-none"
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
function ApprovalAddressButton({
|
|
93
|
+
txId,
|
|
94
|
+
address,
|
|
95
|
+
onCopy
|
|
96
|
+
}) {
|
|
97
|
+
const { ref, agentProps } = useAgentElement({
|
|
98
|
+
id: `copy-address-${txId}`,
|
|
99
|
+
role: "button",
|
|
100
|
+
label: `Copy recipient address for transaction ${txId}`,
|
|
101
|
+
group: "approval-details",
|
|
102
|
+
description: "Copy the destination address to the clipboard",
|
|
103
|
+
onActivate: onCopy
|
|
104
|
+
});
|
|
105
|
+
return /* @__PURE__ */ jsxs(
|
|
106
|
+
"button",
|
|
107
|
+
{
|
|
108
|
+
ref,
|
|
109
|
+
...agentProps,
|
|
110
|
+
type: "button",
|
|
111
|
+
className: "flex items-center gap-1 font-mono text-sm text-txt hover:text-accent transition-colors cursor-pointer",
|
|
112
|
+
onClick: onCopy,
|
|
113
|
+
title: address,
|
|
114
|
+
children: [
|
|
115
|
+
truncateAddress(address),
|
|
116
|
+
/* @__PURE__ */ jsx(Copy, { className: "h-3 w-3 opacity-40" })
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
function ConfirmRejectButton({
|
|
122
|
+
txId,
|
|
123
|
+
onConfirm
|
|
124
|
+
}) {
|
|
125
|
+
const { ref, agentProps } = useAgentElement({
|
|
126
|
+
id: `action-confirm-reject-${txId}`,
|
|
127
|
+
role: "button",
|
|
128
|
+
label: `Confirm rejection of transaction ${txId}`,
|
|
129
|
+
group: "approval-actions",
|
|
130
|
+
description: "Confirm rejecting this transaction with the given reason",
|
|
131
|
+
onActivate: onConfirm
|
|
132
|
+
});
|
|
133
|
+
return /* @__PURE__ */ jsx(
|
|
134
|
+
Button,
|
|
135
|
+
{
|
|
136
|
+
ref,
|
|
137
|
+
...agentProps,
|
|
138
|
+
variant: "outline",
|
|
139
|
+
size: "sm",
|
|
140
|
+
className: "h-9 rounded-lg border-status-danger/30 px-3 text-xs text-status-danger hover:bg-status-danger-bg",
|
|
141
|
+
onClick: onConfirm,
|
|
142
|
+
children: "Confirm Reject"
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
function CancelRejectButton({
|
|
147
|
+
txId,
|
|
148
|
+
onCancel
|
|
149
|
+
}) {
|
|
150
|
+
const { ref, agentProps } = useAgentElement({
|
|
151
|
+
id: `action-cancel-reject-${txId}`,
|
|
152
|
+
role: "button",
|
|
153
|
+
label: `Cancel rejection of transaction ${txId}`,
|
|
154
|
+
group: "approval-actions",
|
|
155
|
+
description: "Close the rejection dialog without rejecting",
|
|
156
|
+
onActivate: onCancel
|
|
157
|
+
});
|
|
158
|
+
return /* @__PURE__ */ jsx(
|
|
159
|
+
Button,
|
|
160
|
+
{
|
|
161
|
+
ref,
|
|
162
|
+
...agentProps,
|
|
163
|
+
variant: "ghost",
|
|
164
|
+
size: "sm",
|
|
165
|
+
className: "h-9 rounded-lg px-3 text-xs text-muted",
|
|
166
|
+
onClick: onCancel,
|
|
167
|
+
children: "Cancel"
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
function ApprovalQueue({
|
|
172
|
+
getStewardPending,
|
|
173
|
+
approveStewardTx,
|
|
174
|
+
rejectStewardTx,
|
|
175
|
+
copyToClipboard,
|
|
176
|
+
setActionNotice,
|
|
177
|
+
onPendingCountChange,
|
|
178
|
+
embedded = false,
|
|
179
|
+
refreshKey
|
|
180
|
+
}) {
|
|
181
|
+
const [items, setItems] = useState([]);
|
|
182
|
+
const [loading, setLoading] = useState(true);
|
|
183
|
+
const [error, setError] = useState(null);
|
|
184
|
+
const [actionInFlight, setActionInFlight] = useState(null);
|
|
185
|
+
const [rejectDialogTxId, setRejectDialogTxId] = useState(null);
|
|
186
|
+
const [rejectReason, setRejectReason] = useState("");
|
|
187
|
+
const prevCountRef = useRef(0);
|
|
188
|
+
const loadData = useCallback(async () => {
|
|
189
|
+
try {
|
|
190
|
+
const data = await getStewardPending();
|
|
191
|
+
const pending = Array.isArray(data) ? data : [];
|
|
192
|
+
setItems(pending);
|
|
193
|
+
setError(null);
|
|
194
|
+
const prevCount = prevCountRef.current;
|
|
195
|
+
if (pending.length > prevCount && prevCount > 0) {
|
|
196
|
+
setActionNotice(
|
|
197
|
+
`${pending.length - prevCount} new approval${pending.length - prevCount > 1 ? "s" : ""} pending`,
|
|
198
|
+
"info",
|
|
199
|
+
3e3
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
if (pending.length !== prevCount) {
|
|
203
|
+
prevCountRef.current = pending.length;
|
|
204
|
+
onPendingCountChange?.(pending.length);
|
|
205
|
+
}
|
|
206
|
+
} catch (err) {
|
|
207
|
+
setError(err instanceof Error ? err.message : "Failed to load approvals");
|
|
208
|
+
} finally {
|
|
209
|
+
setLoading(false);
|
|
210
|
+
}
|
|
211
|
+
}, [getStewardPending, onPendingCountChange, setActionNotice]);
|
|
212
|
+
useEffect(() => {
|
|
213
|
+
void loadData();
|
|
214
|
+
const interval = setInterval(() => void loadData(), POLL_INTERVAL_MS);
|
|
215
|
+
return () => clearInterval(interval);
|
|
216
|
+
}, [loadData]);
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
if (typeof refreshKey === "undefined") {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
setLoading(true);
|
|
222
|
+
void loadData();
|
|
223
|
+
}, [loadData, refreshKey]);
|
|
224
|
+
const handleApprove = useCallback(
|
|
225
|
+
async (txId) => {
|
|
226
|
+
setActionInFlight(txId);
|
|
227
|
+
try {
|
|
228
|
+
const result = await approveStewardTx(txId);
|
|
229
|
+
if (result.ok !== false) {
|
|
230
|
+
setActionNotice("Transaction approved", "success", 3e3);
|
|
231
|
+
setItems(
|
|
232
|
+
(prev) => prev.filter((item) => item.transaction.id !== txId)
|
|
233
|
+
);
|
|
234
|
+
onPendingCountChange?.(items.length - 1);
|
|
235
|
+
} else {
|
|
236
|
+
setActionNotice(result.error ?? "Approval failed", "error", 4e3);
|
|
237
|
+
}
|
|
238
|
+
} catch (err) {
|
|
239
|
+
setActionNotice(
|
|
240
|
+
err instanceof Error ? err.message : "Approval failed",
|
|
241
|
+
"error",
|
|
242
|
+
4e3
|
|
243
|
+
);
|
|
244
|
+
} finally {
|
|
245
|
+
setActionInFlight(null);
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
[approveStewardTx, setActionNotice, onPendingCountChange, items.length]
|
|
249
|
+
);
|
|
250
|
+
const handleReject = useCallback(
|
|
251
|
+
async (txId, reason) => {
|
|
252
|
+
setActionInFlight(txId);
|
|
253
|
+
try {
|
|
254
|
+
const result = await rejectStewardTx(txId, reason);
|
|
255
|
+
if (result.ok !== false) {
|
|
256
|
+
setActionNotice("Transaction rejected", "info", 3e3);
|
|
257
|
+
setItems(
|
|
258
|
+
(prev) => prev.filter((item) => item.transaction.id !== txId)
|
|
259
|
+
);
|
|
260
|
+
onPendingCountChange?.(items.length - 1);
|
|
261
|
+
} else {
|
|
262
|
+
setActionNotice(result.error ?? "Rejection failed", "error", 4e3);
|
|
263
|
+
}
|
|
264
|
+
} catch (err) {
|
|
265
|
+
setActionNotice(
|
|
266
|
+
err instanceof Error ? err.message : "Rejection failed",
|
|
267
|
+
"error",
|
|
268
|
+
4e3
|
|
269
|
+
);
|
|
270
|
+
} finally {
|
|
271
|
+
setActionInFlight(null);
|
|
272
|
+
setRejectDialogTxId(null);
|
|
273
|
+
setRejectReason("");
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
[rejectStewardTx, setActionNotice, onPendingCountChange, items.length]
|
|
277
|
+
);
|
|
278
|
+
const handleCopy = useCallback(
|
|
279
|
+
async (text, label) => {
|
|
280
|
+
await copyToClipboard(text);
|
|
281
|
+
setActionNotice(`${label} copied`, "success", 2e3);
|
|
282
|
+
},
|
|
283
|
+
[copyToClipboard, setActionNotice]
|
|
284
|
+
);
|
|
285
|
+
const formatTime = (dateStr) => {
|
|
286
|
+
try {
|
|
287
|
+
const d = new Date(dateStr);
|
|
288
|
+
const now = /* @__PURE__ */ new Date();
|
|
289
|
+
const diff = now.getTime() - d.getTime();
|
|
290
|
+
const mins = Math.floor(diff / 6e4);
|
|
291
|
+
if (mins < 1) return "just now";
|
|
292
|
+
if (mins < 60) return `${mins}m ago`;
|
|
293
|
+
const hours = Math.floor(mins / 60);
|
|
294
|
+
if (hours < 24) return `${hours}h ago`;
|
|
295
|
+
return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
296
|
+
} catch {
|
|
297
|
+
return dateStr;
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
const getPolicyReasons = (policyResults) => {
|
|
301
|
+
if (!Array.isArray(policyResults)) return [];
|
|
302
|
+
return policyResults.filter(
|
|
303
|
+
(r) => r.reason && (r.status === "rejected" || r.status === "pending")
|
|
304
|
+
).map((r) => r.reason).filter(Boolean);
|
|
305
|
+
};
|
|
306
|
+
return /* @__PURE__ */ jsxs("div", { className: embedded ? "flex min-h-0 flex-1 flex-col" : "space-y-4", children: [
|
|
307
|
+
error ? /* @__PURE__ */ jsx(PagePanel.Notice, { tone: "danger", children: error }) : null,
|
|
308
|
+
loading && items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 items-center justify-center px-6 py-12", children: [
|
|
309
|
+
/* @__PURE__ */ jsx(Spinner, { className: "h-5 w-5 text-muted" }),
|
|
310
|
+
/* @__PURE__ */ jsx("span", { className: "ml-3 text-sm text-muted", children: "Checking for pending approvals\u2026" })
|
|
311
|
+
] }) : null,
|
|
312
|
+
!loading && items.length === 0 && !error ? /* @__PURE__ */ jsx(
|
|
313
|
+
PagePanel.Empty,
|
|
314
|
+
{
|
|
315
|
+
variant: embedded ? "workspace" : "panel",
|
|
316
|
+
title: "None"
|
|
317
|
+
}
|
|
318
|
+
) : null,
|
|
319
|
+
items.length > 0 ? /* @__PURE__ */ jsx(PagePanel.Toolbar, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
320
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-txt", children: "Pending" }),
|
|
321
|
+
/* @__PURE__ */ jsx("span", { className: "text-2xs font-bold text-muted", children: items.length })
|
|
322
|
+
] }) }) : null,
|
|
323
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: items.map((item) => {
|
|
324
|
+
const tx = item.transaction;
|
|
325
|
+
const reasons = getPolicyReasons(tx.policyResults ?? []);
|
|
326
|
+
const isProcessing = actionInFlight === tx.id;
|
|
327
|
+
return /* @__PURE__ */ jsxs(
|
|
328
|
+
"div",
|
|
329
|
+
{
|
|
330
|
+
className: `px-1 py-4 transition-opacity ${isProcessing ? "opacity-60 pointer-events-none" : ""}`,
|
|
331
|
+
children: [
|
|
332
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
333
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [
|
|
334
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted", children: [
|
|
335
|
+
/* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
|
|
336
|
+
/* @__PURE__ */ jsx("span", { children: formatTime(item.requestedAt) }),
|
|
337
|
+
/* @__PURE__ */ jsx("span", { className: "text-2xs font-medium", children: getChainName(tx.request?.chainId ?? 0) })
|
|
338
|
+
] }),
|
|
339
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-3 gap-y-1", children: [
|
|
340
|
+
/* @__PURE__ */ jsx("div", { className: "text-base font-semibold text-txt", children: formatWeiValue(
|
|
341
|
+
tx.request?.value ?? "0",
|
|
342
|
+
tx.request?.chainId ?? 8453
|
|
343
|
+
) }),
|
|
344
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted", children: "\u2192" }),
|
|
345
|
+
/* @__PURE__ */ jsx(
|
|
346
|
+
ApprovalAddressButton,
|
|
347
|
+
{
|
|
348
|
+
txId: tx.id,
|
|
349
|
+
address: tx.request?.to ?? "",
|
|
350
|
+
onCopy: () => void handleCopy(tx.request?.to ?? "", "Address")
|
|
351
|
+
}
|
|
352
|
+
)
|
|
353
|
+
] }),
|
|
354
|
+
reasons.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-1", children: reasons.map((reason) => /* @__PURE__ */ jsx(
|
|
355
|
+
"div",
|
|
356
|
+
{
|
|
357
|
+
className: "rounded-lg bg-status-warning-bg px-2.5 py-1.5 text-xs text-status-warning",
|
|
358
|
+
children: reason
|
|
359
|
+
},
|
|
360
|
+
reason
|
|
361
|
+
)) })
|
|
362
|
+
] }),
|
|
363
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 sm:flex-col sm:items-end", children: isProcessing ? /* @__PURE__ */ jsx(Spinner, { className: "h-5 w-5 text-muted" }) : /* @__PURE__ */ jsx(
|
|
364
|
+
PendingApprovalActions,
|
|
365
|
+
{
|
|
366
|
+
txId: tx.id,
|
|
367
|
+
onApprove: (id) => void handleApprove(id),
|
|
368
|
+
onReject: (id) => setRejectDialogTxId(id)
|
|
369
|
+
}
|
|
370
|
+
) })
|
|
371
|
+
] }),
|
|
372
|
+
rejectDialogTxId === tx.id && /* @__PURE__ */ jsxs("div", { className: "mt-3 flex items-end gap-2 pt-3", children: [
|
|
373
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxs(
|
|
374
|
+
"label",
|
|
375
|
+
{
|
|
376
|
+
className: "block text-2xs font-medium text-muted mb-1",
|
|
377
|
+
htmlFor: `reject-reason-${tx.id}`,
|
|
378
|
+
children: [
|
|
379
|
+
"Rejection reason (optional)",
|
|
380
|
+
/* @__PURE__ */ jsx(
|
|
381
|
+
RejectReasonInput,
|
|
382
|
+
{
|
|
383
|
+
inputId: `reject-reason-${tx.id}`,
|
|
384
|
+
txId: tx.id,
|
|
385
|
+
value: rejectReason,
|
|
386
|
+
onChange: setRejectReason
|
|
387
|
+
}
|
|
388
|
+
)
|
|
389
|
+
]
|
|
390
|
+
}
|
|
391
|
+
) }),
|
|
392
|
+
/* @__PURE__ */ jsx(
|
|
393
|
+
ConfirmRejectButton,
|
|
394
|
+
{
|
|
395
|
+
txId: tx.id,
|
|
396
|
+
onConfirm: () => void handleReject(tx.id, rejectReason || void 0)
|
|
397
|
+
}
|
|
398
|
+
),
|
|
399
|
+
/* @__PURE__ */ jsx(
|
|
400
|
+
CancelRejectButton,
|
|
401
|
+
{
|
|
402
|
+
txId: tx.id,
|
|
403
|
+
onCancel: () => {
|
|
404
|
+
setRejectDialogTxId(null);
|
|
405
|
+
setRejectReason("");
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
)
|
|
409
|
+
] })
|
|
410
|
+
]
|
|
411
|
+
},
|
|
412
|
+
item.queueId
|
|
413
|
+
);
|
|
414
|
+
}) })
|
|
415
|
+
] });
|
|
416
|
+
}
|
|
417
|
+
export {
|
|
418
|
+
ApprovalQueue
|
|
419
|
+
};
|
|
420
|
+
//# sourceMappingURL=ApprovalQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ApprovalQueue.tsx"],"sourcesContent":["/**\n * Approval queue — shows pending transactions that need manual approval.\n * Polls every 10 seconds for new items.\n */\n\nimport { Button, PagePanel, Spinner } from \"@elizaos/ui\";\nimport { useAgentElement } from \"@elizaos/ui/agent-surface\";\nimport { Check, Clock, Copy, X } from \"lucide-react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { formatWeiValue, getChainName, truncateAddress } from \"./chain-utils.js\";\nimport type {\n StewardApprovalActionResponse,\n StewardPendingApproval,\n StewardPolicyResult,\n} from \"./types/steward.js\";\n\ninterface ApprovalQueueProps {\n getStewardPending: () => Promise<StewardPendingApproval[]>;\n approveStewardTx: (txId: string) => Promise<StewardApprovalActionResponse>;\n rejectStewardTx: (\n txId: string,\n reason?: string,\n ) => Promise<StewardApprovalActionResponse>;\n copyToClipboard: (text: string) => Promise<void>;\n setActionNotice: (\n text: string,\n tone?: \"info\" | \"success\" | \"error\",\n ttlMs?: number,\n ) => void;\n onPendingCountChange?: (count: number) => void;\n embedded?: boolean;\n refreshKey?: number | string;\n}\n\nconst POLL_INTERVAL_MS = 10_000;\n\nfunction PendingApprovalActions({\n txId,\n onApprove,\n onReject,\n}: {\n txId: string;\n onApprove: (txId: string) => void;\n onReject: (txId: string) => void;\n}) {\n const approveElement = useAgentElement<HTMLButtonElement>({\n id: `action-approve-${txId}`,\n role: \"button\",\n label: `Approve transaction ${txId}`,\n group: \"approval-actions\",\n description: \"Approve this pending transaction\",\n });\n const rejectElement = useAgentElement<HTMLButtonElement>({\n id: `action-reject-${txId}`,\n role: \"button\",\n label: `Reject transaction ${txId}`,\n group: \"approval-actions\",\n description: \"Reject this pending transaction\",\n });\n return (\n <>\n <Button\n ref={approveElement.ref}\n {...approveElement.agentProps}\n variant=\"default\"\n size=\"sm\"\n className=\"h-9 rounded-md bg-accent px-4 text-xs font-semibold text-accent-fg hover:bg-accent/90\"\n onClick={() => onApprove(txId)}\n aria-label={`Approve transaction ${txId}`}\n >\n <Check className=\"h-3.5 w-3.5\" />\n Approve\n </Button>\n <Button\n ref={rejectElement.ref}\n {...rejectElement.agentProps}\n variant=\"outline\"\n size=\"sm\"\n className=\"h-9 rounded-md border-status-danger/30 px-4 text-xs font-semibold text-status-danger hover:bg-status-danger-bg hover:text-status-danger\"\n onClick={() => onReject(txId)}\n aria-label={`Reject transaction ${txId}`}\n >\n <X className=\"h-3.5 w-3.5\" />\n Reject\n </Button>\n </>\n );\n}\n\nfunction RejectReasonInput({\n txId,\n inputId,\n value,\n onChange,\n}: {\n txId: string;\n inputId: string;\n value: string;\n onChange: (value: string) => void;\n}) {\n const { ref, agentProps } = useAgentElement<HTMLInputElement>({\n id: `input-reject-reason-${txId}`,\n role: \"text-input\",\n label: \"Rejection reason\",\n group: \"approval-actions\",\n description: \"Optional reason for rejecting the transaction\",\n getValue: () => value,\n onFill: onChange,\n });\n return (\n <input\n id={inputId}\n ref={ref}\n {...agentProps}\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder=\"e.g., Unauthorized recipient\"\n aria-label=\"Rejection reason\"\n className=\"mt-1 h-9 w-full rounded-md border border-border/40 bg-transparent px-3 text-sm text-txt placeholder:text-muted/40 focus:border-accent/40 focus:outline-none\"\n />\n );\n}\n\nfunction ApprovalAddressButton({\n txId,\n address,\n onCopy,\n}: {\n txId: string;\n address: string;\n onCopy: () => void;\n}) {\n const { ref, agentProps } = useAgentElement<HTMLButtonElement>({\n id: `copy-address-${txId}`,\n role: \"button\",\n label: `Copy recipient address for transaction ${txId}`,\n group: \"approval-details\",\n description: \"Copy the destination address to the clipboard\",\n onActivate: onCopy,\n });\n return (\n <button\n ref={ref}\n {...agentProps}\n type=\"button\"\n className=\"flex items-center gap-1 font-mono text-sm text-txt hover:text-accent transition-colors cursor-pointer\"\n onClick={onCopy}\n title={address}\n >\n {truncateAddress(address)}\n <Copy className=\"h-3 w-3 opacity-40\" />\n </button>\n );\n}\n\nfunction ConfirmRejectButton({\n txId,\n onConfirm,\n}: {\n txId: string;\n onConfirm: () => void;\n}) {\n const { ref, agentProps } = useAgentElement<HTMLButtonElement>({\n id: `action-confirm-reject-${txId}`,\n role: \"button\",\n label: `Confirm rejection of transaction ${txId}`,\n group: \"approval-actions\",\n description: \"Confirm rejecting this transaction with the given reason\",\n onActivate: onConfirm,\n });\n return (\n <Button\n ref={ref}\n {...agentProps}\n variant=\"outline\"\n size=\"sm\"\n className=\"h-9 rounded-lg border-status-danger/30 px-3 text-xs text-status-danger hover:bg-status-danger-bg\"\n onClick={onConfirm}\n >\n Confirm Reject\n </Button>\n );\n}\n\nfunction CancelRejectButton({\n txId,\n onCancel,\n}: {\n txId: string;\n onCancel: () => void;\n}) {\n const { ref, agentProps } = useAgentElement<HTMLButtonElement>({\n id: `action-cancel-reject-${txId}`,\n role: \"button\",\n label: `Cancel rejection of transaction ${txId}`,\n group: \"approval-actions\",\n description: \"Close the rejection dialog without rejecting\",\n onActivate: onCancel,\n });\n return (\n <Button\n ref={ref}\n {...agentProps}\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-9 rounded-lg px-3 text-xs text-muted\"\n onClick={onCancel}\n >\n Cancel\n </Button>\n );\n}\n\nexport function ApprovalQueue({\n getStewardPending,\n approveStewardTx,\n rejectStewardTx,\n copyToClipboard,\n setActionNotice,\n onPendingCountChange,\n embedded = false,\n refreshKey,\n}: ApprovalQueueProps) {\n const [items, setItems] = useState<StewardPendingApproval[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [actionInFlight, setActionInFlight] = useState<string | null>(null);\n const [rejectDialogTxId, setRejectDialogTxId] = useState<string | null>(null);\n const [rejectReason, setRejectReason] = useState(\"\");\n const prevCountRef = useRef(0);\n\n const loadData = useCallback(async () => {\n try {\n const data = await getStewardPending();\n const pending = Array.isArray(data) ? data : [];\n setItems(pending);\n setError(null);\n\n // Toast when new items arrive (check BEFORE updating ref)\n const prevCount = prevCountRef.current;\n if (pending.length > prevCount && prevCount > 0) {\n setActionNotice(\n `${pending.length - prevCount} new approval${pending.length - prevCount > 1 ? \"s\" : \"\"} pending`,\n \"info\",\n 3000,\n );\n }\n\n // Notify parent of count changes (update ref AFTER toast check)\n if (pending.length !== prevCount) {\n prevCountRef.current = pending.length;\n onPendingCountChange?.(pending.length);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load approvals\");\n } finally {\n setLoading(false);\n }\n }, [getStewardPending, onPendingCountChange, setActionNotice]);\n\n // Initial load + polling\n useEffect(() => {\n void loadData();\n const interval = setInterval(() => void loadData(), POLL_INTERVAL_MS);\n return () => clearInterval(interval);\n }, [loadData]);\n\n useEffect(() => {\n if (typeof refreshKey === \"undefined\") {\n return;\n }\n setLoading(true);\n void loadData();\n }, [loadData, refreshKey]);\n\n const handleApprove = useCallback(\n async (txId: string) => {\n setActionInFlight(txId);\n try {\n const result = await approveStewardTx(txId);\n if (result.ok !== false) {\n setActionNotice(\"Transaction approved\", \"success\", 3000);\n setItems((prev) =>\n prev.filter((item) => item.transaction.id !== txId),\n );\n onPendingCountChange?.(items.length - 1);\n } else {\n setActionNotice(result.error ?? \"Approval failed\", \"error\", 4000);\n }\n } catch (err) {\n setActionNotice(\n err instanceof Error ? err.message : \"Approval failed\",\n \"error\",\n 4000,\n );\n } finally {\n setActionInFlight(null);\n }\n },\n [approveStewardTx, setActionNotice, onPendingCountChange, items.length],\n );\n\n const handleReject = useCallback(\n async (txId: string, reason?: string) => {\n setActionInFlight(txId);\n try {\n const result = await rejectStewardTx(txId, reason);\n if (result.ok !== false) {\n setActionNotice(\"Transaction rejected\", \"info\", 3000);\n setItems((prev) =>\n prev.filter((item) => item.transaction.id !== txId),\n );\n onPendingCountChange?.(items.length - 1);\n } else {\n setActionNotice(result.error ?? \"Rejection failed\", \"error\", 4000);\n }\n } catch (err) {\n setActionNotice(\n err instanceof Error ? err.message : \"Rejection failed\",\n \"error\",\n 4000,\n );\n } finally {\n setActionInFlight(null);\n setRejectDialogTxId(null);\n setRejectReason(\"\");\n }\n },\n [rejectStewardTx, setActionNotice, onPendingCountChange, items.length],\n );\n\n const handleCopy = useCallback(\n async (text: string, label: string) => {\n await copyToClipboard(text);\n setActionNotice(`${label} copied`, \"success\", 2000);\n },\n [copyToClipboard, setActionNotice],\n );\n\n const formatTime = (dateStr: string) => {\n try {\n const d = new Date(dateStr);\n const now = new Date();\n const diff = now.getTime() - d.getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n return d.toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\" });\n } catch {\n return dateStr;\n }\n };\n\n const getPolicyReasons = (policyResults: StewardPolicyResult[]): string[] => {\n if (!Array.isArray(policyResults)) return [];\n return policyResults\n .filter(\n (r) => r.reason && (r.status === \"rejected\" || r.status === \"pending\"),\n )\n .map((r) => r.reason as string)\n .filter(Boolean);\n };\n\n return (\n <div className={embedded ? \"flex min-h-0 flex-1 flex-col\" : \"space-y-4\"}>\n {error ? (\n <PagePanel.Notice tone=\"danger\">{error}</PagePanel.Notice>\n ) : null}\n\n {loading && items.length === 0 ? (\n <div className=\"flex min-h-0 flex-1 items-center justify-center px-6 py-12\">\n <Spinner className=\"h-5 w-5 text-muted\" />\n <span className=\"ml-3 text-sm text-muted\">\n Checking for pending approvals…\n </span>\n </div>\n ) : null}\n\n {!loading && items.length === 0 && !error ? (\n <PagePanel.Empty\n variant={embedded ? \"workspace\" : \"panel\"}\n title=\"None\"\n />\n ) : null}\n\n {items.length > 0 ? (\n <PagePanel.Toolbar>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-semibold text-txt\">Pending</span>\n <span className=\"text-2xs font-bold text-muted\">\n {items.length}\n </span>\n </div>\n </PagePanel.Toolbar>\n ) : null}\n\n {/* Approval rows */}\n <div className=\"space-y-3\">\n {items.map((item) => {\n const tx = item.transaction;\n const reasons = getPolicyReasons(tx.policyResults ?? []);\n const isProcessing = actionInFlight === tx.id;\n\n return (\n <div\n key={item.queueId}\n className={`px-1 py-4 transition-opacity ${\n isProcessing ? \"opacity-60 pointer-events-none\" : \"\"\n }`}\n >\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"min-w-0 flex-1 space-y-2\">\n {/* Time + chain */}\n <div className=\"flex items-center gap-2 text-xs text-muted\">\n <Clock className=\"h-3 w-3\" />\n <span>{formatTime(item.requestedAt)}</span>\n <span className=\"text-2xs font-medium\">\n {getChainName(tx.request?.chainId ?? 0)}\n </span>\n </div>\n\n {/* Destination + amount */}\n <div className=\"flex flex-wrap items-baseline gap-x-3 gap-y-1\">\n <div className=\"text-base font-semibold text-txt\">\n {formatWeiValue(\n tx.request?.value ?? \"0\",\n tx.request?.chainId ?? 8453,\n )}\n </div>\n <span className=\"text-muted\">→</span>\n <ApprovalAddressButton\n txId={tx.id}\n address={tx.request?.to ?? \"\"}\n onCopy={() =>\n void handleCopy(tx.request?.to ?? \"\", \"Address\")\n }\n />\n </div>\n\n {/* Policy reasons */}\n {reasons.length > 0 && (\n <div className=\"space-y-1\">\n {reasons.map((reason) => (\n <div\n key={reason}\n className=\"rounded-lg bg-status-warning-bg px-2.5 py-1.5 text-xs text-status-warning\"\n >\n {reason}\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Action buttons */}\n <div className=\"flex items-center gap-2 sm:flex-col sm:items-end\">\n {isProcessing ? (\n <Spinner className=\"h-5 w-5 text-muted\" />\n ) : (\n <PendingApprovalActions\n txId={tx.id}\n onApprove={(id) => void handleApprove(id)}\n onReject={(id) => setRejectDialogTxId(id)}\n />\n )}\n </div>\n </div>\n\n {/* Reject reason dialog inline */}\n {rejectDialogTxId === tx.id && (\n <div className=\"mt-3 flex items-end gap-2 pt-3\">\n <div className=\"flex-1\">\n <label\n className=\"block text-2xs font-medium text-muted mb-1\"\n htmlFor={`reject-reason-${tx.id}`}\n >\n Rejection reason (optional)\n <RejectReasonInput\n inputId={`reject-reason-${tx.id}`}\n txId={tx.id}\n value={rejectReason}\n onChange={setRejectReason}\n />\n </label>\n </div>\n <ConfirmRejectButton\n txId={tx.id}\n onConfirm={() =>\n void handleReject(tx.id, rejectReason || undefined)\n }\n />\n <CancelRejectButton\n txId={tx.id}\n onCancel={() => {\n setRejectDialogTxId(null);\n setRejectReason(\"\");\n }}\n />\n </div>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Steward brand icon.
|
|
3
|
+
* Keep this inline so package builds do not depend on app-only SVG loaders.
|
|
4
|
+
*/
|
|
5
|
+
interface StewardLogoProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
size?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function StewardLogo({ className, size }: StewardLogoProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=StewardLogo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StewardLogo.d.ts","sourceRoot":"","sources":["../src/StewardLogo.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,UAAU,gBAAgB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,IAAS,EAAE,EAAE,gBAAgB,2CAsBrE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
function StewardLogo({ className, size = 20 }) {
|
|
3
|
+
return /* @__PURE__ */ jsxs(
|
|
4
|
+
"svg",
|
|
5
|
+
{
|
|
6
|
+
viewBox: "0 0 24 24",
|
|
7
|
+
width: size,
|
|
8
|
+
height: size,
|
|
9
|
+
className,
|
|
10
|
+
"aria-hidden": "true",
|
|
11
|
+
focusable: "false",
|
|
12
|
+
fill: "none",
|
|
13
|
+
children: [
|
|
14
|
+
/* @__PURE__ */ jsx(
|
|
15
|
+
"path",
|
|
16
|
+
{
|
|
17
|
+
d: "M12 2.25 19.25 5v5.82c0 5.25-3.53 9.92-7.25 10.93-3.72-1.01-7.25-5.68-7.25-10.93V5L12 2.25Z",
|
|
18
|
+
fill: "#8B6539"
|
|
19
|
+
}
|
|
20
|
+
),
|
|
21
|
+
/* @__PURE__ */ jsx(
|
|
22
|
+
"path",
|
|
23
|
+
{
|
|
24
|
+
d: "M12 5.25 16.25 6.86v3.62c0 3.47-2.12 6.55-4.25 7.37-2.13-.82-4.25-3.9-4.25-7.37V6.86L12 5.25Z",
|
|
25
|
+
fill: "#D9BE8E"
|
|
26
|
+
}
|
|
27
|
+
),
|
|
28
|
+
/* @__PURE__ */ jsx("path", { d: "m12 8.2 2.4 2.65L12 15.75l-2.4-4.9L12 8.2Z", fill: "#F7E7C8" })
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
StewardLogo
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=StewardLogo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/StewardLogo.tsx"],"sourcesContent":["/**\n * Steward brand icon.\n * Keep this inline so package builds do not depend on app-only SVG loaders.\n */\n\ninterface StewardLogoProps {\n className?: string;\n size?: number;\n}\n\nexport function StewardLogo({ className, size = 20 }: StewardLogoProps) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n className={className}\n aria-hidden=\"true\"\n focusable=\"false\"\n fill=\"none\"\n >\n <path\n d=\"M12 2.25 19.25 5v5.82c0 5.25-3.53 9.92-7.25 10.93-3.72-1.01-7.25-5.68-7.25-10.93V5L12 2.25Z\"\n fill=\"#8B6539\"\n />\n <path\n d=\"M12 5.25 16.25 6.86v3.62c0 3.47-2.12 6.55-4.25 7.37-2.13-.82-4.25-3.9-4.25-7.37V6.86L12 5.25Z\"\n fill=\"#D9BE8E\"\n />\n <path d=\"m12 8.2 2.4 2.65L12 15.75l-2.4-4.9L12 8.2Z\" fill=\"#F7E7C8\" />\n </svg>\n );\n}\n"],"mappings":"AAYI,SASE,KATF;AAFG,SAAS,YAAY,EAAE,WAAW,OAAO,GAAG,GAAqB;AACtE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR;AAAA,MACA,eAAY;AAAA,MACZ,WAAU;AAAA,MACV,MAAK;AAAA,MAEL;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,GAAE;AAAA,YACF,MAAK;AAAA;AAAA,QACP;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,GAAE;AAAA,YACF,MAAK;AAAA;AAAA,QACP;AAAA,QACA,oBAAC,UAAK,GAAE,8CAA6C,MAAK,WAAU;AAAA;AAAA;AAAA,EACtE;AAEJ;","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StewardView — the single GUI/XR data wrapper for the Steward surface.
|
|
3
|
+
*
|
|
4
|
+
* It owns the live vault data (status, pending approvals, transaction history)
|
|
5
|
+
* read through the app store accessors, builds one {@link StewardSnapshot}, and
|
|
6
|
+
* renders the one presentational {@link StewardSpatialView} inside a
|
|
7
|
+
* {@link SpatialSurface}. Omitting the `modality` prop lets `SpatialSurface`
|
|
8
|
+
* auto-detect GUI vs XR via `window.__elizaXRContext`, so the SAME component
|
|
9
|
+
* serves both surfaces. The TUI surface renders the same `StewardSpatialView`
|
|
10
|
+
* through the terminal registry (see `register-terminal-view.tsx`).
|
|
11
|
+
*/
|
|
12
|
+
export declare function StewardView(): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=StewardView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StewardView.d.ts","sourceRoot":"","sources":["../src/StewardView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA4EH,wBAAgB,WAAW,4CAyO1B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { StewardPendingApproval, StewardStatusResponse, StewardTxRecord } from "./types/steward.js";
|
|
2
|
+
export interface StewardTxRecordsResponse {
|
|
3
|
+
records: StewardTxRecord[];
|
|
4
|
+
total: number;
|
|
5
|
+
offset: number;
|
|
6
|
+
limit: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function stewardJson<T>(url: string): Promise<T>;
|
|
9
|
+
export declare function postStewardJson<T>(url: string, body: Record<string, unknown>): Promise<T>;
|
|
10
|
+
export declare function loadStewardTuiState(): Promise<{
|
|
11
|
+
status: StewardStatusResponse;
|
|
12
|
+
pending: StewardPendingApproval[];
|
|
13
|
+
history: StewardTxRecordsResponse | null;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=StewardView.helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StewardView.helpers.d.ts","sourceRoot":"","sources":["../src/StewardView.helpers.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAW5D;AAED,wBAAsB,eAAe,CAAC,CAAC,EACrC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,CAAC,CAAC,CAeZ;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IACnD,MAAM,EAAE,qBAAqB,CAAC;IAC9B,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAAC;CAC1C,CAAC,CAmBD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
async function stewardJson(url) {
|
|
2
|
+
const response = await fetch(url);
|
|
3
|
+
const data = await response.json().catch(() => ({}));
|
|
4
|
+
if (!response.ok) {
|
|
5
|
+
const message = data && typeof data === "object" && "error" in data ? String(data.error) : `Steward request failed with ${response.status}`;
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
async function postStewardJson(url, body) {
|
|
11
|
+
const response = await fetch(url, {
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: { "Content-Type": "application/json" },
|
|
14
|
+
body: JSON.stringify(body)
|
|
15
|
+
});
|
|
16
|
+
const data = await response.json().catch(() => ({}));
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
const message = data && typeof data === "object" && "error" in data ? String(data.error) : `Steward request failed with ${response.status}`;
|
|
19
|
+
throw new Error(message);
|
|
20
|
+
}
|
|
21
|
+
return data;
|
|
22
|
+
}
|
|
23
|
+
async function loadStewardTuiState() {
|
|
24
|
+
const status = await stewardJson(
|
|
25
|
+
"/api/wallet/steward-status"
|
|
26
|
+
);
|
|
27
|
+
if (!status.connected) {
|
|
28
|
+
return { status, pending: [], history: null };
|
|
29
|
+
}
|
|
30
|
+
const [pending, history] = await Promise.all([
|
|
31
|
+
stewardJson(
|
|
32
|
+
"/api/wallet/steward-pending-approvals"
|
|
33
|
+
),
|
|
34
|
+
stewardJson(
|
|
35
|
+
"/api/wallet/steward-tx-records?limit=25&offset=0"
|
|
36
|
+
)
|
|
37
|
+
]);
|
|
38
|
+
return { status, pending, history };
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
loadStewardTuiState,
|
|
42
|
+
postStewardJson,
|
|
43
|
+
stewardJson
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=StewardView.helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/StewardView.helpers.ts"],"sourcesContent":["// Shared data helpers for the Steward view, used by the `interact` capability\n// handler (in StewardView.interact.ts) that serves the terminal surface. Kept\n// out of the .tsx so that file exports only React components and stays\n// Fast-Refresh-compatible in dev.\nimport type {\n StewardPendingApproval,\n StewardStatusResponse,\n StewardTxRecord,\n} from \"./types/steward.js\";\n\nexport interface StewardTxRecordsResponse {\n records: StewardTxRecord[];\n total: number;\n offset: number;\n limit: number;\n}\n\nexport async function stewardJson<T>(url: string): Promise<T> {\n const response = await fetch(url);\n const data = await response.json().catch(() => ({}));\n if (!response.ok) {\n const message =\n data && typeof data === \"object\" && \"error\" in data\n ? String(data.error)\n : `Steward request failed with ${response.status}`;\n throw new Error(message);\n }\n return data as T;\n}\n\nexport async function postStewardJson<T>(\n url: string,\n body: Record<string, unknown>,\n): Promise<T> {\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n const data = await response.json().catch(() => ({}));\n if (!response.ok) {\n const message =\n data && typeof data === \"object\" && \"error\" in data\n ? String(data.error)\n : `Steward request failed with ${response.status}`;\n throw new Error(message);\n }\n return data as T;\n}\n\nexport async function loadStewardTuiState(): Promise<{\n status: StewardStatusResponse;\n pending: StewardPendingApproval[];\n history: StewardTxRecordsResponse | null;\n}> {\n const status = await stewardJson<StewardStatusResponse>(\n \"/api/wallet/steward-status\",\n );\n\n if (!status.connected) {\n return { status, pending: [], history: null };\n }\n\n const [pending, history] = await Promise.all([\n stewardJson<StewardPendingApproval[]>(\n \"/api/wallet/steward-pending-approvals\",\n ),\n stewardJson<StewardTxRecordsResponse>(\n \"/api/wallet/steward-tx-records?limit=25&offset=0\",\n ),\n ]);\n\n return { status, pending, history };\n}\n"],"mappings":"AAiBA,eAAsB,YAAe,KAAyB;AAC5D,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,QAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACnD,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,UACJ,QAAQ,OAAO,SAAS,YAAY,WAAW,OAC3C,OAAO,KAAK,KAAK,IACjB,+BAA+B,SAAS,MAAM;AACpD,UAAM,IAAI,MAAM,OAAO;AAAA,EACzB;AACA,SAAO;AACT;AAEA,eAAsB,gBACpB,KACA,MACY;AACZ,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,QAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACnD,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,UACJ,QAAQ,OAAO,SAAS,YAAY,WAAW,OAC3C,OAAO,KAAK,KAAK,IACjB,+BAA+B,SAAS,MAAM;AACpD,UAAM,IAAI,MAAM,OAAO;AAAA,EACzB;AACA,SAAO;AACT;AAEA,eAAsB,sBAInB;AACD,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,WAAW;AACrB,WAAO,EAAE,QAAQ,SAAS,CAAC,GAAG,SAAS,KAAK;AAAA,EAC9C;AAEA,QAAM,CAAC,SAAS,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC3C;AAAA,MACE;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,EAAE,QAAQ,SAAS,QAAQ;AACpC;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StewardView.interact.d.ts","sourceRoot":"","sources":["../src/StewardView.interact.ts"],"names":[],"mappings":"AAeA,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CAoDlB"}
|