@chipi-stack/chipi-react 14.8.0 → 14.10.0

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/multisig.mjs CHANGED
@@ -1,5 +1,7 @@
1
1
  import { MAX_OE_VALIDITY_WINDOW_SECONDS, buildOutsideExecution, ANY_CALLER_FELT, computeOeHash, buildThresholdEnvelope, serializeExecuteFromOutsideV2Calldata } from '@chipi-stack/backend';
2
2
  import { useQueryClient, useMutation, useQuery } from '@tanstack/react-query';
3
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+ import { useState, useEffect, useMemo } from 'react';
3
5
 
4
6
  // src/multisig/action-template.ts
5
7
  var FELT_PRIME = BigInt(
@@ -172,6 +174,7 @@ async function createProposal(params) {
172
174
  title,
173
175
  calls,
174
176
  ...meta ? { meta } : {},
177
+ ...params.template.risk ? { risk: params.template.risk } : {},
175
178
  oeMessageHash: proposal.oeMessageHash,
176
179
  oeNonce: proposal.oeNonce,
177
180
  oeExecuteBefore: proposal.oeExecuteBefore,
@@ -196,7 +199,8 @@ function buildExecuteCalldata(proposal) {
196
199
  if (!proposal.oeNonce || !proposal.oeExecuteBefore) {
197
200
  throw new Error("Proposal is missing OE params (nonce / executeBefore)");
198
201
  }
199
- const signatures = [...proposal.signatures].sort((a, b) => a.ownerId - b.ownerId).map((s) => s.signature);
202
+ const need = Math.max(1, proposal.requiredApprovals);
203
+ const signatures = [...proposal.signatures].sort((a, b) => a.ownerId - b.ownerId).slice(0, need).map((s) => s.signature);
200
204
  return assembleActionExecuteCalldata({
201
205
  calls: proposal.calls,
202
206
  oeNonce: proposal.oeNonce,
@@ -252,6 +256,459 @@ function useTreasuryProposals(config) {
252
256
  return { proposals, approve, execute };
253
257
  }
254
258
 
255
- export { FELT_PRIME, OE_WINDOW_SECONDS, SN_MAIN_CHAIN_ID, amountToBase, assembleActionExecuteCalldata, buildActionProposal, buildApproval, buildExecuteCalldata, createProposal, defineActions, deriveExecuteAfter, deserializeEnvelope, newOeNonce, serializeEnvelope, signActionApproval, toFelt, u256, useProposeAction, useTreasuryProposals, voteTemplate };
259
+ // src/multisig/components/theme.ts
260
+ var DEFAULT_THEME = {
261
+ accent: "#4f46e5",
262
+ accentText: "#ffffff",
263
+ surface: "#fffdf8",
264
+ surfaceMuted: "#f4f1ea",
265
+ text: "#111111",
266
+ textMuted: "#6b7280",
267
+ danger: "#dc2626",
268
+ success: "#16a34a",
269
+ border: "#111111",
270
+ radius: "12px",
271
+ shadow: "4px 4px 0 0 #111111",
272
+ font: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
273
+ };
274
+ function themeVars(theme) {
275
+ const t = { ...DEFAULT_THEME, ...theme };
276
+ return {
277
+ "--cgov-accent": t.accent,
278
+ "--cgov-accent-text": t.accentText,
279
+ "--cgov-surface": t.surface,
280
+ "--cgov-surface-muted": t.surfaceMuted,
281
+ "--cgov-text": t.text,
282
+ "--cgov-text-muted": t.textMuted,
283
+ "--cgov-danger": t.danger,
284
+ "--cgov-success": t.success,
285
+ "--cgov-border": t.border,
286
+ "--cgov-radius": t.radius,
287
+ "--cgov-shadow": t.shadow,
288
+ "--cgov-font": t.font
289
+ };
290
+ }
291
+ var STYLE_ID = "chipi-gov-styles";
292
+ var STYLE_TEXT = `
293
+ .cgov-root{font-family:var(--cgov-font);color:var(--cgov-text);box-sizing:border-box}
294
+ .cgov-root *,.cgov-root *::before,.cgov-root *::after{box-sizing:inherit}
295
+ .cgov-card{background:var(--cgov-surface);border:2px solid var(--cgov-border);border-radius:var(--cgov-radius);box-shadow:var(--cgov-shadow)}
296
+ .cgov-btn{display:inline-flex;align-items:center;gap:.5em;font:inherit;font-weight:600;cursor:pointer;border:2px solid var(--cgov-border);border-radius:calc(var(--cgov-radius) * .75);padding:.5em 1em;background:var(--cgov-surface);color:var(--cgov-text);transition:transform .06s ease}
297
+ .cgov-btn:hover:not(:disabled){transform:translate(-1px,-1px)}
298
+ .cgov-btn:active:not(:disabled){transform:translate(1px,1px)}
299
+ .cgov-btn:disabled{opacity:.5;cursor:not-allowed}
300
+ .cgov-btn-primary{background:var(--cgov-accent);color:var(--cgov-accent-text)}
301
+ .cgov-btn-sm{font-size:.8125rem;padding:.35em .8em}
302
+ .cgov-input,.cgov-select{font:inherit;width:100%;padding:.5em .75em;border:2px solid var(--cgov-border);border-radius:calc(var(--cgov-radius) * .6);background:var(--cgov-surface-muted);color:var(--cgov-text)}
303
+ .cgov-input:focus,.cgov-select:focus{outline:3px solid color-mix(in srgb, var(--cgov-accent) 40%, transparent);outline-offset:1px}
304
+ .cgov-label{display:block;font-size:.8125rem;font-weight:600;margin:0 0 .3em}
305
+ .cgov-help{font-size:.75rem;color:var(--cgov-text-muted);margin:.25em 0 0}
306
+ .cgov-field{margin-bottom:.9rem}
307
+ .cgov-field-error{font-size:.75rem;color:var(--cgov-danger);margin:.25em 0 0}
308
+ .cgov-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);display:flex;align-items:flex-end;justify-content:center;z-index:2147483000;padding:1rem}
309
+ @media (min-width:640px){.cgov-overlay{align-items:center}}
310
+ .cgov-dialog{width:100%;max-width:28rem;max-height:calc(100vh - 2rem);overflow-y:auto;padding:1.25rem}
311
+ .cgov-dialog-title{font-size:1.05rem;font-weight:700;margin:0 0 .25rem}
312
+ .cgov-dialog-desc{font-size:.8125rem;color:var(--cgov-text-muted);margin:0 0 1rem}
313
+ .cgov-preview{background:var(--cgov-surface-muted);border:2px dashed var(--cgov-border);border-radius:calc(var(--cgov-radius) * .6);padding:.75rem;margin:.25rem 0 1rem}
314
+ .cgov-preview-title{font-weight:700;font-size:.9375rem;margin:0}
315
+ .cgov-preview-rule{font-size:.75rem;color:var(--cgov-text-muted);margin:.35em 0 0}
316
+ .cgov-preview-call{font-family:ui-monospace,monospace;font-size:.6875rem;color:var(--cgov-text-muted);margin:.35em 0 0;word-break:break-all}
317
+ .cgov-tabs{display:flex;gap:.4rem;flex-wrap:wrap;margin:0 0 1rem}
318
+ .cgov-tab{font:inherit;font-size:.8125rem;font-weight:600;padding:.35em .8em;cursor:pointer;border:2px solid var(--cgov-border);border-radius:999px;background:var(--cgov-surface)}
319
+ .cgov-tab[aria-selected="true"]{background:var(--cgov-accent);color:var(--cgov-accent-text)}
320
+ .cgov-row{display:flex;align-items:center;gap:.75rem;padding:.75rem;border-bottom:2px solid color-mix(in srgb, var(--cgov-border) 15%, transparent)}
321
+ .cgov-row:last-child{border-bottom:none}
322
+ .cgov-row-main{flex:1;min-width:0}
323
+ .cgov-row-title{font-weight:600;font-size:.9375rem;margin:0;overflow:hidden;text-overflow:ellipsis}
324
+ .cgov-row-sub{font-size:.75rem;color:var(--cgov-text-muted);margin:.15em 0 0;display:flex;gap:.5em;align-items:center;flex-wrap:wrap}
325
+ .cgov-chip{display:inline-block;font-size:.6875rem;font-weight:700;padding:.15em .6em;border:1.5px solid var(--cgov-border);border-radius:999px;background:var(--cgov-surface-muted)}
326
+ .cgov-chip-success{background:color-mix(in srgb, var(--cgov-success) 18%, transparent)}
327
+ .cgov-chip-accent{background:color-mix(in srgb, var(--cgov-accent) 18%, transparent)}
328
+ .cgov-empty{padding:1.5rem;text-align:center;color:var(--cgov-text-muted);font-size:.875rem}
329
+ .cgov-error{padding:.6rem .75rem;border:2px solid var(--cgov-danger);border-radius:calc(var(--cgov-radius) * .6);background:color-mix(in srgb, var(--cgov-danger) 8%, transparent);color:var(--cgov-danger);font-size:.8125rem;margin:.5rem 0}
330
+ .cgov-group-label{font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--cgov-text-muted);margin:1rem 0 .35rem;padding:0 .25rem}
331
+ .cgov-group-label:first-child{margin-top:0}
332
+ .cgov-spinner{display:inline-block;width:.9em;height:.9em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:cgov-spin .7s linear infinite}
333
+ @keyframes cgov-spin{to{transform:rotate(360deg)}}
334
+ `;
335
+ function injectGovStyles() {
336
+ const doc = globalThis.document;
337
+ if (!doc) return;
338
+ if (doc.getElementById(STYLE_ID)) return;
339
+ const el = doc.createElement("style");
340
+ el.id = STYLE_ID;
341
+ el.textContent = STYLE_TEXT;
342
+ doc.head.appendChild(el);
343
+ }
344
+ function fieldSyntaxError(field, raw) {
345
+ if (raw.trim() === "") return `${field.label} is required`;
346
+ const v = raw.trim();
347
+ switch (field.type) {
348
+ case "address":
349
+ return /^0x[0-9a-fA-F]{1,64}$/.test(v) ? null : `${field.label} must be a 0x address`;
350
+ case "felt":
351
+ return /^(0x[0-9a-fA-F]+|\d+)$/.test(v) ? null : `${field.label} must be a felt (0x-hex or decimal)`;
352
+ case "amount":
353
+ return /^\d+(\.\d+)?$/.test(v) ? null : `${field.label} must be a positive amount`;
354
+ case "number":
355
+ case "bps":
356
+ case "days":
357
+ return /^\d+$/.test(v) ? null : `${field.label} must be a whole number`;
358
+ default:
359
+ return null;
360
+ }
361
+ }
362
+ function FieldInput(props) {
363
+ const { field, value, onChange, error, disabled } = props;
364
+ const id = `cgov-field-${field.name}`;
365
+ return /* @__PURE__ */ jsxs("div", { className: "cgov-field", children: [
366
+ /* @__PURE__ */ jsx("label", { className: "cgov-label", htmlFor: id, children: field.label }),
367
+ field.type === "select" ? /* @__PURE__ */ jsxs(
368
+ "select",
369
+ {
370
+ id,
371
+ className: "cgov-select",
372
+ value,
373
+ disabled,
374
+ onChange: (e) => onChange(e.target.value),
375
+ children: [
376
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Choose\u2026" }),
377
+ field.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
378
+ ]
379
+ }
380
+ ) : /* @__PURE__ */ jsx(
381
+ "input",
382
+ {
383
+ id,
384
+ className: "cgov-input",
385
+ value,
386
+ disabled,
387
+ inputMode: field.type === "amount" || field.type === "number" || field.type === "bps" || field.type === "days" ? "decimal" : "text",
388
+ placeholder: field.type === "address" ? "0x\u2026" : field.type === "amount" ? "0.00" : void 0,
389
+ onChange: (e) => onChange(e.target.value)
390
+ }
391
+ ),
392
+ "help" in field && field.help ? /* @__PURE__ */ jsx("p", { className: "cgov-help", children: field.help }) : null,
393
+ error ? /* @__PURE__ */ jsx("p", { className: "cgov-field-error", children: error }) : null
394
+ ] });
395
+ }
396
+ function buildPreview(template, values) {
397
+ for (const f of template.fields) {
398
+ const err = fieldSyntaxError(f, values[f.name] ?? "");
399
+ if (err) return { error: err };
400
+ }
401
+ try {
402
+ return { title: template.title(values), calls: template.toCalls(values) };
403
+ } catch (e) {
404
+ return { error: e instanceof Error ? e.message : "Invalid values" };
405
+ }
406
+ }
407
+ function ProposeAction(props) {
408
+ const [open, setOpen] = useState(false);
409
+ const [templateKey, setTemplateKey] = useState(props.preselect ?? props.actions[0]?.key ?? "");
410
+ const [values, setValues] = useState({});
411
+ const [touched, setTouched] = useState({});
412
+ const [requiredApprovals, setRequiredApprovals] = useState(null);
413
+ const [done, setDone] = useState(null);
414
+ useEffect(injectGovStyles, []);
415
+ const template = props.actions.find((t) => t.key === templateKey) ?? props.actions[0];
416
+ const propose = useProposeAction({
417
+ walletAddress: props.walletAddress,
418
+ transport: props.transport,
419
+ signer: props.signer,
420
+ getRequiredApprovals: props.getRequiredApprovals,
421
+ chainId: props.chainId
422
+ });
423
+ useEffect(() => {
424
+ if (!open) return;
425
+ let on = true;
426
+ props.getRequiredApprovals().then(
427
+ (n) => on && setRequiredApprovals(n),
428
+ () => on && setRequiredApprovals(null)
429
+ );
430
+ return () => {
431
+ on = false;
432
+ };
433
+ }, [open]);
434
+ const preview = useMemo(
435
+ () => template ? buildPreview(template, values) : { error: "No action templates" },
436
+ [template, values]
437
+ );
438
+ const reset = () => {
439
+ setValues({});
440
+ setTouched({});
441
+ setDone(null);
442
+ propose.reset();
443
+ };
444
+ const close = () => {
445
+ setOpen(false);
446
+ reset();
447
+ };
448
+ const submit = async () => {
449
+ if (!template || "error" in preview) return;
450
+ try {
451
+ const proposal = await propose.mutateAsync({ template, values });
452
+ setDone(proposal);
453
+ props.onProposed?.(proposal);
454
+ } catch {
455
+ }
456
+ };
457
+ return /* @__PURE__ */ jsxs("div", { className: "cgov-root", style: themeVars(props.theme), children: [
458
+ props.trigger ? props.trigger(() => setOpen(true)) : /* @__PURE__ */ jsx("button", { type: "button", className: "cgov-btn cgov-btn-primary", onClick: () => setOpen(true), children: "Propose action" }),
459
+ open ? /* @__PURE__ */ jsx("div", { className: "cgov-overlay", role: "presentation", onClick: close, children: /* @__PURE__ */ jsx(
460
+ "div",
461
+ {
462
+ className: "cgov-card cgov-dialog cgov-root",
463
+ style: themeVars(props.theme),
464
+ role: "dialog",
465
+ "aria-modal": "true",
466
+ "aria-label": done ? "Proposal created" : "Propose an action",
467
+ onClick: (e) => e.stopPropagation(),
468
+ children: done ? /* @__PURE__ */ jsxs(Fragment, { children: [
469
+ /* @__PURE__ */ jsx("h2", { className: "cgov-dialog-title", children: "Proposed \u2713" }),
470
+ /* @__PURE__ */ jsxs("p", { className: "cgov-dialog-desc", children: [
471
+ done.title ?? "Your action",
472
+ " \u2014",
473
+ " ",
474
+ done.status === "APPROVED" ? "approved and ready to execute." : `needs ${done.requiredApprovals} approval${done.requiredApprovals === 1 ? "" : "s"}.`
475
+ ] }),
476
+ /* @__PURE__ */ jsx("button", { type: "button", className: "cgov-btn cgov-btn-primary", onClick: close, children: "Done" })
477
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
478
+ /* @__PURE__ */ jsx("h2", { className: "cgov-dialog-title", children: "Propose an action" }),
479
+ /* @__PURE__ */ jsx("p", { className: "cgov-dialog-desc", children: "Your team approves before anything moves on chain." }),
480
+ props.actions.length > 1 ? /* @__PURE__ */ jsx("div", { className: "cgov-tabs", role: "tablist", "aria-label": "Action type", children: props.actions.map((t) => /* @__PURE__ */ jsx(
481
+ "button",
482
+ {
483
+ type: "button",
484
+ role: "tab",
485
+ "aria-selected": t.key === template?.key,
486
+ className: "cgov-tab",
487
+ onClick: () => {
488
+ setTemplateKey(t.key);
489
+ reset();
490
+ },
491
+ children: t.label
492
+ },
493
+ t.key
494
+ )) }) : null,
495
+ template?.description ? /* @__PURE__ */ jsx("p", { className: "cgov-help", style: { marginBottom: "0.9rem" }, children: template.description }) : null,
496
+ template?.fields.map((f) => /* @__PURE__ */ jsx(
497
+ FieldInput,
498
+ {
499
+ field: f,
500
+ value: values[f.name] ?? "",
501
+ disabled: propose.isPending,
502
+ error: touched[f.name] ? fieldSyntaxError(f, values[f.name] ?? "") : null,
503
+ onChange: (raw) => {
504
+ setValues((v) => ({ ...v, [f.name]: raw }));
505
+ setTouched((t) => ({ ...t, [f.name]: true }));
506
+ }
507
+ },
508
+ f.name
509
+ )),
510
+ /* @__PURE__ */ jsx("div", { className: "cgov-preview", "aria-live": "polite", children: "error" in preview ? /* @__PURE__ */ jsx("p", { className: "cgov-preview-rule", children: "What this does \u2014 fill in the fields above." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
511
+ /* @__PURE__ */ jsx("p", { className: "cgov-preview-title", children: preview.title }),
512
+ preview.calls.map((c, i) => /* @__PURE__ */ jsxs("p", { className: "cgov-preview-call", children: [
513
+ c.entrypoint,
514
+ "(",
515
+ c.calldata.join(", "),
516
+ ") \u2192 ",
517
+ c.to.slice(0, 10),
518
+ "\u2026"
519
+ ] }, i)),
520
+ /* @__PURE__ */ jsx("p", { className: "cgov-preview-rule", children: requiredApprovals != null ? `Needs ${requiredApprovals} approval${requiredApprovals === 1 ? "" : "s"} before it executes.` : "Approval rule loads from your wallet." })
521
+ ] }) }),
522
+ propose.error ? /* @__PURE__ */ jsx("div", { className: "cgov-error", role: "alert", children: propose.error instanceof Error ? propose.error.message : "Could not create the proposal. Try again." }) : null,
523
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.5rem", justifyContent: "flex-end" }, children: [
524
+ /* @__PURE__ */ jsx(
525
+ "button",
526
+ {
527
+ type: "button",
528
+ className: "cgov-btn",
529
+ onClick: close,
530
+ disabled: propose.isPending,
531
+ children: "Cancel"
532
+ }
533
+ ),
534
+ /* @__PURE__ */ jsx(
535
+ "button",
536
+ {
537
+ type: "button",
538
+ className: "cgov-btn cgov-btn-primary",
539
+ disabled: "error" in preview || propose.isPending,
540
+ onClick: submit,
541
+ children: propose.isPending ? /* @__PURE__ */ jsxs(Fragment, { children: [
542
+ /* @__PURE__ */ jsx("span", { className: "cgov-spinner", "aria-hidden": true }),
543
+ " Signing\u2026"
544
+ ] }) : "Sign & propose"
545
+ }
546
+ )
547
+ ] })
548
+ ] })
549
+ }
550
+ ) }) : null
551
+ ] });
552
+ }
553
+ var STATUS_LABEL = {
554
+ PROPOSED: "Needs approvals",
555
+ APPROVED: "Ready to execute",
556
+ EXECUTED: "Executed",
557
+ CANCELED: "Canceled",
558
+ EXPIRED: "Expired"
559
+ };
560
+ function proposalTitle(p) {
561
+ return p.title?.trim() || "Treasury action";
562
+ }
563
+ function ProposalRow(props) {
564
+ const p = props.proposal;
565
+ const signed = props.myOwnerIndex != null && p.signatures.some((s) => s.ownerId === props.myOwnerIndex);
566
+ const canApprove = p.status === "PROPOSED" && props.myOwnerIndex != null && !signed;
567
+ const canExecute = p.status === "APPROVED";
568
+ const label = props.agentLabel ?? "Agent";
569
+ const title = props.isAgent ? `${label} wants: ${proposalTitle(p)}` : proposalTitle(p);
570
+ return /* @__PURE__ */ jsxs("div", { className: "cgov-row", children: [
571
+ /* @__PURE__ */ jsxs("div", { className: "cgov-row-main", children: [
572
+ /* @__PURE__ */ jsx("p", { className: "cgov-row-title", children: title }),
573
+ /* @__PURE__ */ jsxs("div", { className: "cgov-row-sub", children: [
574
+ props.isAgent ? /* @__PURE__ */ jsx("span", { className: "cgov-chip cgov-chip-accent", children: label }) : null,
575
+ /* @__PURE__ */ jsx(
576
+ "span",
577
+ {
578
+ className: `cgov-chip${p.status === "EXECUTED" ? " cgov-chip-success" : p.status === "APPROVED" ? " cgov-chip-accent" : ""}`,
579
+ children: STATUS_LABEL[p.status]
580
+ }
581
+ ),
582
+ /* @__PURE__ */ jsxs("span", { children: [
583
+ p.signatures.length,
584
+ " of ",
585
+ p.requiredApprovals,
586
+ " approvals"
587
+ ] }),
588
+ p.risk === "SENSITIVE" ? /* @__PURE__ */ jsx("span", { className: "cgov-chip", children: "Sensitive" }) : null,
589
+ signed && p.status === "PROPOSED" ? /* @__PURE__ */ jsx("span", { children: "\xB7 you approved" }) : null,
590
+ p.status === "EXECUTED" && p.executedTxHash && props.explorerTxUrl ? /* @__PURE__ */ jsx(
591
+ "a",
592
+ {
593
+ href: props.explorerTxUrl(p.executedTxHash),
594
+ target: "_blank",
595
+ rel: "noopener noreferrer",
596
+ children: "receipt \u2197"
597
+ }
598
+ ) : null,
599
+ props.renderContext ? /* @__PURE__ */ jsx("span", { children: props.renderContext(p) }) : null
600
+ ] })
601
+ ] }),
602
+ canApprove ? /* @__PURE__ */ jsx(
603
+ "button",
604
+ {
605
+ type: "button",
606
+ className: "cgov-btn cgov-btn-primary cgov-btn-sm",
607
+ disabled: props.busy,
608
+ onClick: () => props.onApprove(p),
609
+ children: "Approve"
610
+ }
611
+ ) : canExecute ? /* @__PURE__ */ jsx(
612
+ "button",
613
+ {
614
+ type: "button",
615
+ className: "cgov-btn cgov-btn-primary cgov-btn-sm",
616
+ disabled: props.busy,
617
+ onClick: () => props.onExecute(p),
618
+ children: "Execute"
619
+ }
620
+ ) : null
621
+ ] });
622
+ }
623
+ function Approvals(props) {
624
+ const filter = props.filter ?? "actionable";
625
+ const [myOwnerIndex, setMyOwnerIndex] = useState(null);
626
+ const [actionError, setActionError] = useState(null);
627
+ useEffect(injectGovStyles, []);
628
+ useEffect(() => {
629
+ let on = true;
630
+ props.signer.resolveOwnerIndex(props.walletAddress).then(
631
+ (i) => on && setMyOwnerIndex(i),
632
+ () => on && setMyOwnerIndex(null)
633
+ // not an owner on this device → read-only
634
+ );
635
+ return () => {
636
+ on = false;
637
+ };
638
+ }, [props.walletAddress]);
639
+ const { proposals, approve, execute } = useTreasuryProposals({
640
+ walletAddress: props.walletAddress,
641
+ transport: props.transport,
642
+ signer: props.signer
643
+ });
644
+ const busy = approve.isPending || execute.isPending;
645
+ const onApprove = async (p) => {
646
+ setActionError(null);
647
+ try {
648
+ await approve.mutateAsync(p);
649
+ } catch (e) {
650
+ setActionError(e instanceof Error ? e.message : "Could not approve. Try again.");
651
+ }
652
+ };
653
+ const onExecute = async (p) => {
654
+ setActionError(null);
655
+ try {
656
+ const res = await execute.mutateAsync(p);
657
+ props.onExecuted?.(p, res.executedTxHash ?? res.transactionHash);
658
+ } catch (e) {
659
+ setActionError(e instanceof Error ? e.message : "Could not execute. Try again.");
660
+ }
661
+ };
662
+ const items = (proposals.data?.items ?? []).filter((p) => {
663
+ if (filter === "all") return true;
664
+ if (filter === "pending") return p.status === "PROPOSED" || p.status === "APPROVED";
665
+ return p.status === "APPROVED" || p.status === "PROPOSED" && (myOwnerIndex == null || !p.signatures.some((s) => s.ownerId === myOwnerIndex));
666
+ });
667
+ return /* @__PURE__ */ jsxs("div", { className: "cgov-root", style: themeVars(props.theme), children: [
668
+ /* @__PURE__ */ jsx("div", { className: "cgov-card", children: proposals.isLoading ? /* @__PURE__ */ jsxs("div", { className: "cgov-empty", children: [
669
+ /* @__PURE__ */ jsx("span", { className: "cgov-spinner", "aria-hidden": true }),
670
+ " Loading\u2026"
671
+ ] }) : proposals.error ? /* @__PURE__ */ jsx("div", { className: "cgov-empty", children: "Could not load proposals." }) : items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "cgov-empty", children: props.empty ?? "You're all caught up." }) : items.map((p) => /* @__PURE__ */ jsx(
672
+ ProposalRow,
673
+ {
674
+ proposal: p,
675
+ myOwnerIndex,
676
+ busy,
677
+ onApprove,
678
+ onExecute,
679
+ renderContext: props.renderContext,
680
+ explorerTxUrl: props.explorerTxUrl,
681
+ isAgent: props.isAgentProposal?.(p) ?? false,
682
+ agentLabel: props.agentLabel
683
+ },
684
+ p.id
685
+ )) }),
686
+ actionError ? /* @__PURE__ */ jsx("div", { className: "cgov-error", role: "alert", children: actionError }) : null
687
+ ] });
688
+ }
689
+ function ApprovalInbox(props) {
690
+ useEffect(injectGovStyles, []);
691
+ return /* @__PURE__ */ jsx("div", { className: "cgov-root", style: themeVars(props.theme), children: props.treasuries.map((t) => /* @__PURE__ */ jsxs("section", { "aria-label": t.label, children: [
692
+ /* @__PURE__ */ jsx("p", { className: "cgov-group-label", children: t.label }),
693
+ /* @__PURE__ */ jsx(
694
+ Approvals,
695
+ {
696
+ walletAddress: t.walletAddress,
697
+ transport: t.transport,
698
+ signer: t.signer,
699
+ renderContext: t.renderContext,
700
+ explorerTxUrl: t.explorerTxUrl,
701
+ isAgentProposal: t.isAgentProposal,
702
+ agentLabel: t.agentLabel,
703
+ filter: "actionable",
704
+ theme: props.theme,
705
+ empty: props.onEmpty ?? "All caught up.",
706
+ onExecuted: (p, tx) => props.onExecuted?.(t, p, tx)
707
+ }
708
+ )
709
+ ] }, t.walletAddress)) });
710
+ }
711
+
712
+ export { ApprovalInbox, Approvals, DEFAULT_THEME, FELT_PRIME, FieldInput, OE_WINDOW_SECONDS, ProposeAction, SN_MAIN_CHAIN_ID, amountToBase, assembleActionExecuteCalldata, buildActionProposal, buildApproval, buildExecuteCalldata, createProposal, defineActions, deriveExecuteAfter, deserializeEnvelope, fieldSyntaxError, injectGovStyles, newOeNonce, proposalTitle, serializeEnvelope, signActionApproval, themeVars, toFelt, u256, useProposeAction, useTreasuryProposals, voteTemplate };
256
713
  //# sourceMappingURL=multisig.mjs.map
257
714
  //# sourceMappingURL=multisig.mjs.map