@ixo/editor 6.30.3 → 6.31.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/action-manifest.json +17 -1
- package/dist/{chunk-XYAKFAZ3.js → chunk-NYQBGIZ2.js} +273 -18
- package/dist/chunk-NYQBGIZ2.js.map +1 -0
- package/dist/{chunk-OAAEXL7Q.js → chunk-S7CAGFE3.js} +2 -2
- package/dist/{chunk-LY32OATI.js → chunk-ZXNBOVAA.js} +149 -56
- package/dist/chunk-ZXNBOVAA.js.map +1 -0
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +2 -2
- package/dist/{graphql-client-BV2YEKAc.d.ts → graphql-client-ZY4Iw0jB.d.ts} +1 -1
- package/dist/{index-CEIunGZv.d.ts → index-Up8gA_E9.d.ts} +25 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/mantine/index.d.ts +3 -3
- package/dist/mantine/index.js +2 -2
- package/dist/{store-whqrkEVn.d.ts → store-CqvAkvIZ.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-LY32OATI.js.map +0 -1
- package/dist/chunk-XYAKFAZ3.js.map +0 -1
- /package/dist/{chunk-OAAEXL7Q.js.map → chunk-S7CAGFE3.js.map} +0 -0
|
@@ -2117,7 +2117,7 @@
|
|
|
2117
2117
|
},
|
|
2118
2118
|
"granteeKind": {
|
|
2119
2119
|
"type": "string",
|
|
2120
|
-
"description": "How to treat the add grantee: user, group-account, or
|
|
2120
|
+
"description": "How to treat the add grantee: user, group-account, group-members, or address-list."
|
|
2121
2121
|
},
|
|
2122
2122
|
"agentQuota": {
|
|
2123
2123
|
"type": "string",
|
|
@@ -2134,10 +2134,20 @@
|
|
|
2134
2134
|
"members": {
|
|
2135
2135
|
"type": "array",
|
|
2136
2136
|
"description": "Resolved members to fan the grant out to when granteeKind is group-members."
|
|
2137
|
+
},
|
|
2138
|
+
"granteeAddresses": {
|
|
2139
|
+
"type": "array",
|
|
2140
|
+
"description": "Accounts pasted in bulk to grant in one transaction when granteeKind is address-list."
|
|
2137
2141
|
}
|
|
2138
2142
|
}
|
|
2139
2143
|
},
|
|
2140
2144
|
"outputSchema": [
|
|
2145
|
+
{
|
|
2146
|
+
"path": "operation",
|
|
2147
|
+
"displayName": "Operation",
|
|
2148
|
+
"type": "string",
|
|
2149
|
+
"description": "Which op produced this output: add, revoke or list"
|
|
2150
|
+
},
|
|
2141
2151
|
{
|
|
2142
2152
|
"path": "transactionHash",
|
|
2143
2153
|
"displayName": "Tx Hash",
|
|
@@ -2168,6 +2178,12 @@
|
|
|
2168
2178
|
"type": "string",
|
|
2169
2179
|
"description": "Address granted/revoked"
|
|
2170
2180
|
},
|
|
2181
|
+
{
|
|
2182
|
+
"path": "granteeAddresses",
|
|
2183
|
+
"displayName": "Grantee Addresses",
|
|
2184
|
+
"type": "array",
|
|
2185
|
+
"description": "Every address granted by a bulk/fan-out add"
|
|
2186
|
+
},
|
|
2171
2187
|
{
|
|
2172
2188
|
"path": "grantees",
|
|
2173
2189
|
"displayName": "Grantees",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
COLLECTION_USERS_MAX_GRANTS_PER_TX,
|
|
2
3
|
DIFFERENT_WHEN_OPTIONS,
|
|
3
4
|
DIFFERENT_WHEN_OTHER_MAX,
|
|
4
5
|
EVAL_ENGINE_ACTION_TYPE,
|
|
@@ -35,6 +36,7 @@ import {
|
|
|
35
36
|
cancelRun,
|
|
36
37
|
closeRun,
|
|
37
38
|
collectPhantomLegacyRun,
|
|
39
|
+
collectionUsersBatchCount,
|
|
38
40
|
countSuccessfulRuns,
|
|
39
41
|
createInvocationStore,
|
|
40
42
|
createReference,
|
|
@@ -130,7 +132,7 @@ import {
|
|
|
130
132
|
writeActionState,
|
|
131
133
|
writeRunRecordAndReconcile,
|
|
132
134
|
xeroOracleActivityForBlockForEditor
|
|
133
|
-
} from "./chunk-
|
|
135
|
+
} from "./chunk-ZXNBOVAA.js";
|
|
134
136
|
|
|
135
137
|
// src/mantine/hooks/usePanel.ts
|
|
136
138
|
import { useCallback, useMemo, useEffect, useRef } from "react";
|
|
@@ -27314,7 +27316,7 @@ import React270, { useCallback as useCallback96, useEffect as useEffect98, useRe
|
|
|
27314
27316
|
import { Alert as Alert39, Button as Button54, Flex as Flex37, Loader as Loader44, Paper as Paper22, Stack as Stack183, Text as Text163, TextInput as TextInput10 } from "@mantine/core";
|
|
27315
27317
|
import { IconSearch as IconSearch10 } from "@tabler/icons-react";
|
|
27316
27318
|
var ADDRESS_PREFIX = "ixo1";
|
|
27317
|
-
var RecipientInput = ({ value, onChange, isDisabled, placeholder }) => {
|
|
27319
|
+
var RecipientInput = ({ value, onChange, isDisabled, placeholder, onBulkPaste }) => {
|
|
27318
27320
|
const handlers = useBlocknoteHandlers();
|
|
27319
27321
|
const handlersRef = useRef30(handlers);
|
|
27320
27322
|
handlersRef.current = handlers;
|
|
@@ -27388,6 +27390,13 @@ var RecipientInput = ({ value, onChange, isDisabled, placeholder }) => {
|
|
|
27388
27390
|
rightSection: searching ? /* @__PURE__ */ React270.createElement(Loader44, { size: 14 }) : null,
|
|
27389
27391
|
value: query,
|
|
27390
27392
|
onChange: (e) => handleQueryChange(e.currentTarget.value),
|
|
27393
|
+
onPaste: (e) => {
|
|
27394
|
+
if (!onBulkPaste) return;
|
|
27395
|
+
const text = e.clipboardData?.getData("text") ?? "";
|
|
27396
|
+
if (!/[\r\n\t]/.test(text.trim())) return;
|
|
27397
|
+
e.preventDefault();
|
|
27398
|
+
onBulkPaste(text);
|
|
27399
|
+
},
|
|
27391
27400
|
onKeyDown: (e) => {
|
|
27392
27401
|
if (e.key === "Enter") {
|
|
27393
27402
|
e.preventDefault();
|
|
@@ -33858,7 +33867,107 @@ import React320, { useCallback as useCallback112, useEffect as useEffect115, use
|
|
|
33858
33867
|
import { ActionIcon as ActionIcon47, Alert as MantineAlert, Badge as Badge52, Box as Box60, Button as Button67, Divider as Divider22, Group as Group116, Loader as Loader61, Radio as Radio5, SegmentedControl as SegmentedControl16, Stack as Stack211, Text as Text199 } from "@mantine/core";
|
|
33859
33868
|
import { useDebouncedValue } from "@mantine/hooks";
|
|
33860
33869
|
import { IconAlertCircle as IconAlertCircle28, IconArrowLeft as IconArrowLeft10, IconCheck as IconCheck24, IconRefresh as IconRefresh9, IconTrash as IconTrash10 } from "@tabler/icons-react";
|
|
33870
|
+
|
|
33871
|
+
// src/core/utils/accountList.ts
|
|
33872
|
+
var IXO_HRP = "ixo";
|
|
33873
|
+
var TOKEN_SEPARATORS = /[\s,;|]+/;
|
|
33874
|
+
var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
33875
|
+
var GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
33876
|
+
function polymod(values) {
|
|
33877
|
+
let chk = 1;
|
|
33878
|
+
for (const value of values) {
|
|
33879
|
+
const top = chk >> 25;
|
|
33880
|
+
chk = (chk & 33554431) << 5 ^ value;
|
|
33881
|
+
for (let i = 0; i < 5; i += 1) {
|
|
33882
|
+
if (top >> i & 1) chk ^= GENERATOR[i];
|
|
33883
|
+
}
|
|
33884
|
+
}
|
|
33885
|
+
return chk;
|
|
33886
|
+
}
|
|
33887
|
+
function hrpExpand(hrp) {
|
|
33888
|
+
const high = [];
|
|
33889
|
+
const low = [];
|
|
33890
|
+
for (let i = 0; i < hrp.length; i += 1) {
|
|
33891
|
+
high.push(hrp.charCodeAt(i) >> 5);
|
|
33892
|
+
low.push(hrp.charCodeAt(i) & 31);
|
|
33893
|
+
}
|
|
33894
|
+
return [...high, 0, ...low];
|
|
33895
|
+
}
|
|
33896
|
+
function isValidBech32Address(value, hrp = IXO_HRP) {
|
|
33897
|
+
if (!value) return false;
|
|
33898
|
+
if (value !== value.toLowerCase() && value !== value.toUpperCase()) return false;
|
|
33899
|
+
const address = value.toLowerCase();
|
|
33900
|
+
if (address.length < hrp.length + 8 || address.length > 90) return false;
|
|
33901
|
+
if (!address.startsWith(`${hrp}1`)) return false;
|
|
33902
|
+
const dataPart = address.slice(hrp.length + 1);
|
|
33903
|
+
const data = [];
|
|
33904
|
+
for (const char of dataPart) {
|
|
33905
|
+
const index = CHARSET.indexOf(char);
|
|
33906
|
+
if (index === -1) return false;
|
|
33907
|
+
data.push(index);
|
|
33908
|
+
}
|
|
33909
|
+
return polymod([...hrpExpand(hrp), ...data]) === 1;
|
|
33910
|
+
}
|
|
33911
|
+
function normalizeToken(token) {
|
|
33912
|
+
let value = token.trim();
|
|
33913
|
+
value = value.replace(/^["'`]+|["'`]+$/g, "");
|
|
33914
|
+
value = value.replace(/^[([{<]+|[)\]}>.,;:]+$/g, "");
|
|
33915
|
+
if (/^did:ixo:/i.test(value)) value = value.slice("did:ixo:".length);
|
|
33916
|
+
return value.trim();
|
|
33917
|
+
}
|
|
33918
|
+
function looksLikeAddress(token) {
|
|
33919
|
+
return /^ixo1/i.test(token);
|
|
33920
|
+
}
|
|
33921
|
+
function parseAccountList(text) {
|
|
33922
|
+
const rows = [];
|
|
33923
|
+
const addresses = [];
|
|
33924
|
+
const seen = /* @__PURE__ */ new Set();
|
|
33925
|
+
let duplicates = 0;
|
|
33926
|
+
const lines = String(text ?? "").split(/\r\n|\n|\r/);
|
|
33927
|
+
lines.forEach((line, index) => {
|
|
33928
|
+
const raw = line.replace(/\t/g, " ").trim();
|
|
33929
|
+
if (!raw) return;
|
|
33930
|
+
const row = { line: index + 1, raw };
|
|
33931
|
+
const tokens = line.split(TOKEN_SEPARATORS).map(normalizeToken).filter(Boolean);
|
|
33932
|
+
const candidates = tokens.filter(looksLikeAddress);
|
|
33933
|
+
if (candidates.length === 0) {
|
|
33934
|
+
row.problem = "no-address";
|
|
33935
|
+
rows.push(row);
|
|
33936
|
+
return;
|
|
33937
|
+
}
|
|
33938
|
+
const valid = candidates.map((candidate) => candidate.toLowerCase()).filter((candidate) => isValidBech32Address(candidate));
|
|
33939
|
+
if (valid.length === 0) {
|
|
33940
|
+
row.problem = "invalid-address";
|
|
33941
|
+
rows.push(row);
|
|
33942
|
+
return;
|
|
33943
|
+
}
|
|
33944
|
+
const [address, ...extras] = valid;
|
|
33945
|
+
row.address = address;
|
|
33946
|
+
if (seen.has(address)) {
|
|
33947
|
+
duplicates += 1;
|
|
33948
|
+
row.problem = "duplicate";
|
|
33949
|
+
} else {
|
|
33950
|
+
seen.add(address);
|
|
33951
|
+
addresses.push(address);
|
|
33952
|
+
}
|
|
33953
|
+
rows.push(row);
|
|
33954
|
+
for (const extra of extras) {
|
|
33955
|
+
rows.push({ line: index + 1, raw: extra, address: extra, problem: "extra-in-row" });
|
|
33956
|
+
}
|
|
33957
|
+
});
|
|
33958
|
+
return {
|
|
33959
|
+
addresses,
|
|
33960
|
+
rows,
|
|
33961
|
+
// Duplicates are excluded: they are not a loss (the account is in the list
|
|
33962
|
+
// once already) and they are counted separately.
|
|
33963
|
+
rejected: rows.filter((row) => !!row.problem && row.problem !== "duplicate"),
|
|
33964
|
+
duplicates
|
|
33965
|
+
};
|
|
33966
|
+
}
|
|
33967
|
+
|
|
33968
|
+
// src/mantine/blocks/action/actionTypes/collectionUsers/CollectionUsersFlowDetail.tsx
|
|
33861
33969
|
var LOG2 = "[collection.users]";
|
|
33970
|
+
var MAX_LISTED_REJECTIONS = 8;
|
|
33862
33971
|
function roleLabel(role) {
|
|
33863
33972
|
return role === "submit" ? "Submit (Contributor)" : "Evaluate (Evaluator)";
|
|
33864
33973
|
}
|
|
@@ -33933,6 +34042,72 @@ function MaxAmountsInput({ value, onChange, disabled }) {
|
|
|
33933
34042
|
}
|
|
33934
34043
|
)));
|
|
33935
34044
|
}
|
|
34045
|
+
function broadcastTxCount(output) {
|
|
34046
|
+
if (Array.isArray(output?.transactionHashes)) return output.transactionHashes.length;
|
|
34047
|
+
return output?.batched === false ? Number(output?.grantedCount) || 1 : 1;
|
|
34048
|
+
}
|
|
34049
|
+
function grantBroadcastSummary(output) {
|
|
34050
|
+
const count = Number(output?.grantedCount);
|
|
34051
|
+
if (!Number.isFinite(count) || count <= 1) return "Grant broadcast";
|
|
34052
|
+
const transactions = broadcastTxCount(output);
|
|
34053
|
+
return transactions === 1 ? `${count} accounts granted in one transaction` : `${count} accounts granted in ${transactions} transactions`;
|
|
34054
|
+
}
|
|
34055
|
+
function rejectionReason(problem) {
|
|
34056
|
+
if (problem === "invalid-address") return "not a valid ixo1\u2026 address";
|
|
34057
|
+
if (problem === "extra-in-row") return "a second account on the same row \u2014 only the first one on a row is granted";
|
|
34058
|
+
return "no account found in this row";
|
|
34059
|
+
}
|
|
34060
|
+
function signingPlan(count, canBatchGrants) {
|
|
34061
|
+
if (count <= 1) return null;
|
|
34062
|
+
if (!canBatchGrants) {
|
|
34063
|
+
return { color: "yellow", message: `This host cannot bundle grants \u2014 it will ask you to sign ${count} separate transactions, one per account.` };
|
|
34064
|
+
}
|
|
34065
|
+
const batches = collectionUsersBatchCount(count);
|
|
34066
|
+
if (batches === 1) return { color: "blue", message: `All ${count} grants go in one transaction \u2014 you sign once.` };
|
|
34067
|
+
return {
|
|
34068
|
+
color: "yellow",
|
|
34069
|
+
message: `${count} grants exceed the ${COLLECTION_USERS_MAX_GRANTS_PER_TX} per transaction limit, so they are split into ${batches} batches \u2014 you will be asked to sign ${batches} times, one after the other.`
|
|
34070
|
+
};
|
|
34071
|
+
}
|
|
34072
|
+
function BulkAccountsInput({
|
|
34073
|
+
text,
|
|
34074
|
+
onChange,
|
|
34075
|
+
parsed,
|
|
34076
|
+
isDisabled,
|
|
34077
|
+
canBatchGrants,
|
|
34078
|
+
actingAsGroup
|
|
34079
|
+
}) {
|
|
34080
|
+
const { addresses, rejected, duplicates } = parsed;
|
|
34081
|
+
const listed = rejected.slice(0, MAX_LISTED_REJECTIONS);
|
|
34082
|
+
const plan = signingPlan(addresses.length, canBatchGrants);
|
|
34083
|
+
return /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs" }, /* @__PURE__ */ React320.createElement(
|
|
34084
|
+
BaseTextArea,
|
|
34085
|
+
{
|
|
34086
|
+
label: "Accounts",
|
|
34087
|
+
description: "Paste (Ctrl+V) a column copied from Google Sheets or Excel \u2014 one account per row. Other columns, headers and blank rows are ignored.",
|
|
34088
|
+
placeholder: "ixo1\u2026\nixo1\u2026\nixo1\u2026",
|
|
34089
|
+
minRows: 4,
|
|
34090
|
+
maxRows: 12,
|
|
34091
|
+
value: text,
|
|
34092
|
+
onChange: (event) => onChange(event.currentTarget.value),
|
|
34093
|
+
disabled: isDisabled,
|
|
34094
|
+
styles: { input: { fontFamily: "var(--mantine-font-family-monospace)" } }
|
|
34095
|
+
}
|
|
34096
|
+
), /* @__PURE__ */ React320.createElement(Group116, { justify: "space-between", align: "center" }, /* @__PURE__ */ React320.createElement(Group116, { gap: "xs" }, /* @__PURE__ */ React320.createElement(Badge52, { size: "sm", variant: "light", color: addresses.length > 0 ? "green" : "gray" }, addresses.length, " account", addresses.length === 1 ? "" : "s", " to grant"), duplicates > 0 && /* @__PURE__ */ React320.createElement(Badge52, { size: "sm", variant: "light", color: "gray" }, duplicates, " duplicate", duplicates === 1 ? "" : "s", " removed"), rejected.length > 0 && /* @__PURE__ */ React320.createElement(Badge52, { size: "sm", variant: "light", color: "yellow" }, rejected.length, " row", rejected.length === 1 ? "" : "s", " skipped")), !!text.trim() && /* @__PURE__ */ React320.createElement(Button67, { size: "compact-xs", variant: "subtle", color: "gray", onClick: () => onChange(""), disabled: isDisabled }, "Clear")), rejected.length > 0 && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: "yellow", styles: actionAlertStyles }, /* @__PURE__ */ React320.createElement(Stack211, { gap: 2 }, /* @__PURE__ */ React320.createElement(Text199, { size: "xs", fw: 600 }, "These rows will NOT be granted:"), listed.map((row) => /* @__PURE__ */ React320.createElement(Text199, { key: row.line, size: "xs" }, "Row ", row.line, ": \u201C", row.raw.length > 60 ? `${row.raw.slice(0, 60)}\u2026` : row.raw, "\u201D \u2014 ", rejectionReason(row.problem))), rejected.length > listed.length && /* @__PURE__ */ React320.createElement(Text199, { size: "xs", c: "dimmed" }, "\u2026and ", rejected.length - listed.length, " more."))), addresses.length > 0 && /* @__PURE__ */ React320.createElement(
|
|
34097
|
+
Box60,
|
|
34098
|
+
{
|
|
34099
|
+
style: {
|
|
34100
|
+
border: "1px solid var(--mantine-color-neutralColor-6)",
|
|
34101
|
+
borderRadius: 8,
|
|
34102
|
+
padding: 8,
|
|
34103
|
+
maxHeight: 160,
|
|
34104
|
+
overflowY: "auto",
|
|
34105
|
+
background: "var(--mantine-color-neutralColor-5)"
|
|
34106
|
+
}
|
|
34107
|
+
},
|
|
34108
|
+
/* @__PURE__ */ React320.createElement(Stack211, { gap: 2 }, addresses.map((address, index) => /* @__PURE__ */ React320.createElement(Text199, { key: address, size: "xs", ff: "monospace", truncate: true }, index + 1, ". ", address)))
|
|
34109
|
+
), actingAsGroup && addresses.length > COLLECTION_USERS_MAX_GRANTS_PER_TX && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: "red", styles: actionAlertStyles }, "Acting as a POD puts every grant in one proposal, which executes as a single transaction \u2014 so this list cannot be split. Reduce it to ", COLLECTION_USERS_MAX_GRANTS_PER_TX, " ", "accounts or fewer, or grant without acting as a POD."), !actingAsGroup && plan && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: plan.color, styles: actionAlertStyles }, plan.message));
|
|
34110
|
+
}
|
|
33936
34111
|
function toQuotaString(value) {
|
|
33937
34112
|
const n = Number(value);
|
|
33938
34113
|
if (!Number.isFinite(n) || n < MIN_AGENT_QUOTA) return String(MIN_AGENT_QUOTA);
|
|
@@ -34053,7 +34228,28 @@ var CollectionUsersFlowDetail = ({
|
|
|
34053
34228
|
const [addMaxAmounts, setAddMaxAmounts] = useState170(EMPTY_MAX_AMOUNTS);
|
|
34054
34229
|
const [granteeKind, setGranteeKind] = useState170("user");
|
|
34055
34230
|
const [members, setMembers] = useState170([]);
|
|
34231
|
+
const [addMode, setAddMode] = useState170("single");
|
|
34232
|
+
const [bulkText, setBulkText] = useState170("");
|
|
34233
|
+
const parsedAccounts = useMemo120(() => parseAccountList(bulkText), [bulkText]);
|
|
34234
|
+
const bulkAddresses = parsedAccounts.addresses;
|
|
34235
|
+
const canBatchGrants = typeof handlers.collectionUsers?.grantMany === "function";
|
|
34056
34236
|
const [revokeTarget, setRevokeTarget] = useState170(null);
|
|
34237
|
+
const handleBulkPaste = useCallback112(
|
|
34238
|
+
(text) => {
|
|
34239
|
+
const carried = addAddress.trim();
|
|
34240
|
+
setActiveOp("add");
|
|
34241
|
+
setRevokeTarget(null);
|
|
34242
|
+
setAddAddress("");
|
|
34243
|
+
setAddMode("list");
|
|
34244
|
+
setBulkText((prev) => [prev.replace(/\s+$/, ""), carried, text].filter((part) => part.trim()).join("\n"));
|
|
34245
|
+
},
|
|
34246
|
+
[addAddress]
|
|
34247
|
+
);
|
|
34248
|
+
const handleAddModeChange = useCallback112((mode) => {
|
|
34249
|
+
setActiveOp("add");
|
|
34250
|
+
setRevokeTarget(null);
|
|
34251
|
+
setAddMode(mode);
|
|
34252
|
+
}, []);
|
|
34057
34253
|
const classifyHandler = handlers.classifyAddress;
|
|
34058
34254
|
const enumerateHandler = handlers.enumerateMembers;
|
|
34059
34255
|
const canClassify = typeof classifyHandler === "function";
|
|
@@ -34116,6 +34312,8 @@ var CollectionUsersFlowDetail = ({
|
|
|
34116
34312
|
}, [addRole]);
|
|
34117
34313
|
const isGroup = !!classification?.daodao;
|
|
34118
34314
|
const canExerciseGrant = !!classification?.daodao?.canExerciseGrant;
|
|
34315
|
+
const pendingGranteeCount = addMode === "list" ? bulkAddresses.length : granteeKind === "group-members" ? members.length : 1;
|
|
34316
|
+
const memberSigningPlan = useMemo120(() => signingPlan(members.length, canBatchGrants), [members.length, canBatchGrants]);
|
|
34119
34317
|
const listOnLoadRef = useRef42(false);
|
|
34120
34318
|
const runList = useCallback112(async () => {
|
|
34121
34319
|
if (!executeAction) {
|
|
@@ -34208,20 +34406,49 @@ var CollectionUsersFlowDetail = ({
|
|
|
34208
34406
|
if (!revokeTarget?.address) return { ok: false, error: "Pick a grantee to revoke from the list." };
|
|
34209
34407
|
return { ok: true };
|
|
34210
34408
|
}
|
|
34211
|
-
|
|
34212
|
-
|
|
34213
|
-
|
|
34214
|
-
|
|
34409
|
+
if (addMode === "list") {
|
|
34410
|
+
if (bulkAddresses.length === 0) {
|
|
34411
|
+
return { ok: false, error: parsedAccounts.rows.length > 0 ? "No valid ixo1\u2026 accounts in the pasted list." : "Paste a list of accounts to grant." };
|
|
34412
|
+
}
|
|
34413
|
+
} else {
|
|
34414
|
+
const address = addAddress.trim();
|
|
34415
|
+
if (!address) return { ok: false, error: "Enter a grantee address." };
|
|
34416
|
+
if (granteeKind === "group-account" && !canExerciseGrant) {
|
|
34417
|
+
return { ok: false, error: "This group cannot hold the authorization. Grant its members individually instead." };
|
|
34418
|
+
}
|
|
34419
|
+
if (granteeKind === "group-members") {
|
|
34420
|
+
if (members.length === 0) return { ok: false, error: "No group members resolved yet." };
|
|
34421
|
+
}
|
|
34215
34422
|
}
|
|
34216
|
-
if (
|
|
34217
|
-
|
|
34423
|
+
if (actAs.actAsGroup && pendingGranteeCount > COLLECTION_USERS_MAX_GRANTS_PER_TX) {
|
|
34424
|
+
return {
|
|
34425
|
+
ok: false,
|
|
34426
|
+
error: `Acting as a POD allows at most ${COLLECTION_USERS_MAX_GRANTS_PER_TX} accounts per proposal; this grants ${pendingGranteeCount}. Remove ${pendingGranteeCount - COLLECTION_USERS_MAX_GRANTS_PER_TX}, or grant without acting as a POD.`
|
|
34427
|
+
};
|
|
34218
34428
|
}
|
|
34219
34429
|
const quotaNum = Number(addQuota);
|
|
34220
34430
|
if (!Number.isFinite(quotaNum) || quotaNum < MIN_AGENT_QUOTA) {
|
|
34221
34431
|
return { ok: false, error: `Agent quota must be at least ${MIN_AGENT_QUOTA}.` };
|
|
34222
34432
|
}
|
|
34223
34433
|
return { ok: true };
|
|
34224
|
-
}, [
|
|
34434
|
+
}, [
|
|
34435
|
+
section,
|
|
34436
|
+
collectionId,
|
|
34437
|
+
adminAddress,
|
|
34438
|
+
adminError,
|
|
34439
|
+
activeOp,
|
|
34440
|
+
revokeTarget,
|
|
34441
|
+
addMode,
|
|
34442
|
+
bulkAddresses.length,
|
|
34443
|
+
parsedAccounts.rows.length,
|
|
34444
|
+
actAs.actAsGroup,
|
|
34445
|
+
pendingGranteeCount,
|
|
34446
|
+
addAddress,
|
|
34447
|
+
granteeKind,
|
|
34448
|
+
canExerciseGrant,
|
|
34449
|
+
members.length,
|
|
34450
|
+
addQuota
|
|
34451
|
+
]);
|
|
34225
34452
|
const buildRuntimeInputs = useCallback112(() => {
|
|
34226
34453
|
if (section === "bids") {
|
|
34227
34454
|
return { operation: "list", collectionId, adminAddress };
|
|
@@ -34237,19 +34464,21 @@ var CollectionUsersFlowDetail = ({
|
|
|
34237
34464
|
};
|
|
34238
34465
|
}
|
|
34239
34466
|
const maxAmounts = buildMaxAmounts(addMaxAmounts);
|
|
34467
|
+
const isBulk = addMode === "list";
|
|
34240
34468
|
return {
|
|
34241
34469
|
operation: "add",
|
|
34242
34470
|
collectionId,
|
|
34243
34471
|
adminAddress,
|
|
34244
34472
|
deedDid: deedDid || void 0,
|
|
34245
|
-
granteeAddress: addAddress.trim(),
|
|
34473
|
+
granteeAddress: isBulk ? void 0 : addAddress.trim(),
|
|
34246
34474
|
role: addRole,
|
|
34247
|
-
granteeKind,
|
|
34475
|
+
granteeKind: isBulk ? "address-list" : granteeKind,
|
|
34248
34476
|
agentQuota: toQuotaString(addQuota),
|
|
34249
34477
|
maxAmount: addRole === "evaluate" && maxAmounts.length > 0 ? maxAmounts : void 0,
|
|
34250
|
-
members: granteeKind === "group-members" ? members : void 0
|
|
34478
|
+
members: !isBulk && granteeKind === "group-members" ? members : void 0,
|
|
34479
|
+
granteeAddresses: isBulk ? bulkAddresses : void 0
|
|
34251
34480
|
};
|
|
34252
|
-
}, [section, activeOp, collectionId, adminAddress, deedDid, revokeTarget, addAddress, addRole, granteeKind, addQuota, addMaxAmounts, members]);
|
|
34481
|
+
}, [section, activeOp, collectionId, adminAddress, deedDid, revokeTarget, addMode, bulkAddresses, addAddress, addRole, granteeKind, addQuota, addMaxAmounts, members]);
|
|
34253
34482
|
useEffect115(() => {
|
|
34254
34483
|
if (!registerRuntimeInputs) return;
|
|
34255
34484
|
registerRuntimeInputs(buildRuntimeInputs());
|
|
@@ -34273,6 +34502,7 @@ var CollectionUsersFlowDetail = ({
|
|
|
34273
34502
|
collectionId,
|
|
34274
34503
|
granteeAddress: runtimeInputs.granteeAddress,
|
|
34275
34504
|
granteeKind: runtimeInputs.granteeKind,
|
|
34505
|
+
granteeCount: runtimeInputs.granteeAddresses?.length,
|
|
34276
34506
|
listener: isListener
|
|
34277
34507
|
});
|
|
34278
34508
|
try {
|
|
@@ -34287,6 +34517,7 @@ var CollectionUsersFlowDetail = ({
|
|
|
34287
34517
|
console.log(`${LOG2} execute success`, { operation: runtimeInputs.operation, transactionHash: payload.transactionHash });
|
|
34288
34518
|
if (runtimeInputs.operation === "add") {
|
|
34289
34519
|
setAddAddress("");
|
|
34520
|
+
setBulkText("");
|
|
34290
34521
|
setAddQuota(String(runtimeInputs.role === "evaluate" ? DEFAULT_EVALUATOR_QUOTA : DEFAULT_CONTRIBUTOR_QUOTA));
|
|
34291
34522
|
setAddMaxAmounts(EMPTY_MAX_AMOUNTS);
|
|
34292
34523
|
setGranteeKind("user");
|
|
@@ -34337,7 +34568,7 @@ var CollectionUsersFlowDetail = ({
|
|
|
34337
34568
|
defaultValue: "Configure the {{did}} and {{claimCollection}} in template mode before running this action.",
|
|
34338
34569
|
did: "DID",
|
|
34339
34570
|
claimCollection: "claim collection"
|
|
34340
|
-
})), isStale && /* @__PURE__ */ React320.createElement(DismissibleAlert, { icon: /* @__PURE__ */ React320.createElement(IconAlertCircle28, { size: 16 }), color: "yellow", title: "Inconsistent State" }, /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs" }, /* @__PURE__ */ React320.createElement(Text199, { size: "sm" }, "Block was marked completed but no result was recorded. This is stale state from a previous run \u2014 reset and re-run."), /* @__PURE__ */ React320.createElement(Group116, null, /* @__PURE__ */ React320.createElement(Button67, { variant: "outline", size: "xs", onClick: handleReset }, "Reset"), /* @__PURE__ */ React320.createElement(Button67, { variant: "filled", size: "xs", onClick: handleForceRun, disabled: !validation.ok }, "Force Run Now")))), isFailed && /* @__PURE__ */ React320.createElement(DismissibleAlert, { icon: /* @__PURE__ */ React320.createElement(IconAlertCircle28, { size: 16 }), color: "red", title: "Action Failed", styles: actionAlertStyles }, /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs" }, errorMessage && /* @__PURE__ */ React320.createElement(Text199, { size: "sm" }, errorMessage), /* @__PURE__ */ React320.createElement(Group116, null, /* @__PURE__ */ React320.createElement(Button67, { variant: "outline", size: "xs", onClick: handleReset }, "Reset"), !!collectionId && !!adminAddress && /* @__PURE__ */ React320.createElement(Button67, { variant: "filled", size: "xs", leftSection: /* @__PURE__ */ React320.createElement(IconRefresh9, { size: 14 }), onClick: handleManualRefreshList }, "Refresh List")))), isCompletedWithProof && hasTxProof && (lastOp === "add" || lastOp === "revoke") && /* @__PURE__ */ React320.createElement(DismissibleAlert, { icon: /* @__PURE__ */ React320.createElement(IconCheck24, { size: 16 }), color: "green", styles: actionAlertStyles }, lastOp === "add" ?
|
|
34571
|
+
})), isStale && /* @__PURE__ */ React320.createElement(DismissibleAlert, { icon: /* @__PURE__ */ React320.createElement(IconAlertCircle28, { size: 16 }), color: "yellow", title: "Inconsistent State" }, /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs" }, /* @__PURE__ */ React320.createElement(Text199, { size: "sm" }, "Block was marked completed but no result was recorded. This is stale state from a previous run \u2014 reset and re-run."), /* @__PURE__ */ React320.createElement(Group116, null, /* @__PURE__ */ React320.createElement(Button67, { variant: "outline", size: "xs", onClick: handleReset }, "Reset"), /* @__PURE__ */ React320.createElement(Button67, { variant: "filled", size: "xs", onClick: handleForceRun, disabled: !validation.ok }, "Force Run Now")))), isFailed && /* @__PURE__ */ React320.createElement(DismissibleAlert, { icon: /* @__PURE__ */ React320.createElement(IconAlertCircle28, { size: 16 }), color: "red", title: "Action Failed", styles: actionAlertStyles }, /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs" }, errorMessage && /* @__PURE__ */ React320.createElement(Text199, { size: "sm" }, errorMessage), /* @__PURE__ */ React320.createElement(Group116, null, /* @__PURE__ */ React320.createElement(Button67, { variant: "outline", size: "xs", onClick: handleReset }, "Reset"), !!collectionId && !!adminAddress && /* @__PURE__ */ React320.createElement(Button67, { variant: "filled", size: "xs", leftSection: /* @__PURE__ */ React320.createElement(IconRefresh9, { size: 14 }), onClick: handleManualRefreshList }, "Refresh List")))), isCompletedWithProof && hasTxProof && (lastOp === "add" || lastOp === "revoke") && /* @__PURE__ */ React320.createElement(DismissibleAlert, { icon: /* @__PURE__ */ React320.createElement(IconCheck24, { size: 16 }), color: "green", styles: actionAlertStyles }, lastOp === "add" ? grantBroadcastSummary(output) : "Revoke broadcast", " \u2014 ", broadcastTxCount(output) > 1 ? "last tx" : "tx", " ", truncateAddress4(String(output?.transactionHash || "")), "."), !configMissing && /* @__PURE__ */ React320.createElement(
|
|
34341
34572
|
SegmentedControl16,
|
|
34342
34573
|
{
|
|
34343
34574
|
fullWidth: true,
|
|
@@ -34379,7 +34610,30 @@ var CollectionUsersFlowDetail = ({
|
|
|
34379
34610
|
"Revoke"
|
|
34380
34611
|
))
|
|
34381
34612
|
);
|
|
34382
|
-
}), revokeTarget && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: "red", styles: actionAlertStyles }, "Slide to sign to revoke ", roleLabel(revokeTarget.role), " from ", truncateAddress4(revokeTarget.address), ".")), !configMissing && section === "add" && /* @__PURE__ */ React320.createElement(Stack211, { gap: "sm" }, revokeTarget && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: "yellow", styles: actionAlertStyles }, "A revoke is currently armed. Switch to the Users tab to sign it, or change the grantee below to arm an add instead."), /* @__PURE__ */ React320.createElement(
|
|
34613
|
+
}), revokeTarget && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: "red", styles: actionAlertStyles }, "Slide to sign to revoke ", roleLabel(revokeTarget.role), " from ", truncateAddress4(revokeTarget.address), ".")), !configMissing && section === "add" && /* @__PURE__ */ React320.createElement(Stack211, { gap: "sm" }, revokeTarget && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: "yellow", styles: actionAlertStyles }, "A revoke is currently armed. Switch to the Users tab to sign it, or change the grantee below to arm an add instead."), /* @__PURE__ */ React320.createElement(
|
|
34614
|
+
SegmentedControl16,
|
|
34615
|
+
{
|
|
34616
|
+
fullWidth: true,
|
|
34617
|
+
size: "xs",
|
|
34618
|
+
value: addMode,
|
|
34619
|
+
onChange: (value) => handleAddModeChange(value),
|
|
34620
|
+
disabled: isDisabled || isRunning,
|
|
34621
|
+
data: [
|
|
34622
|
+
{ label: "One account", value: "single" },
|
|
34623
|
+
{ label: "Paste a list", value: "list" }
|
|
34624
|
+
]
|
|
34625
|
+
}
|
|
34626
|
+
), addMode === "list" && /* @__PURE__ */ React320.createElement(
|
|
34627
|
+
BulkAccountsInput,
|
|
34628
|
+
{
|
|
34629
|
+
text: bulkText,
|
|
34630
|
+
onChange: setBulkText,
|
|
34631
|
+
parsed: parsedAccounts,
|
|
34632
|
+
isDisabled: isDisabled || isRunning,
|
|
34633
|
+
canBatchGrants,
|
|
34634
|
+
actingAsGroup: actAs.actAsGroup
|
|
34635
|
+
}
|
|
34636
|
+
), addMode === "single" && /* @__PURE__ */ React320.createElement(Stack211, { gap: 4 }, /* @__PURE__ */ React320.createElement(Text199, { size: "sm", fw: 500 }, "Grantee address"), /* @__PURE__ */ React320.createElement(
|
|
34383
34637
|
RecipientInput,
|
|
34384
34638
|
{
|
|
34385
34639
|
value: addAddress,
|
|
@@ -34388,10 +34642,11 @@ var CollectionUsersFlowDetail = ({
|
|
|
34388
34642
|
setRevokeTarget(null);
|
|
34389
34643
|
setAddAddress(address);
|
|
34390
34644
|
},
|
|
34645
|
+
onBulkPaste: handleBulkPaste,
|
|
34391
34646
|
isDisabled: isDisabled || isRunning,
|
|
34392
34647
|
placeholder: "Search by name / @user:\u2026, or paste an ixo1\u2026 address"
|
|
34393
34648
|
}
|
|
34394
|
-
)), canClassify ? /* @__PURE__ */ React320.createElement(Button67, { size: "xs", variant: "light", onClick: runClassify, disabled: !addAddress.trim() || classifying || isRunning, loading: classifying }, "Check address") : /* @__PURE__ */ React320.createElement(Text199, { size: "xs", c: "dimmed" }, "Address classification is unavailable in this host \u2014 the grantee will be added as a plain account."), classifyError && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: "red", styles: actionAlertStyles }, classifyError), isGroup && /* @__PURE__ */ React320.createElement(Box60, { style: { border: "1px solid var(--mantine-color-neutralColor-6)", borderRadius: 8, padding: 12 } }, /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs" }, /* @__PURE__ */ React320.createElement(Text199, { size: "sm", fw: 600 }, "Add the group, or all the members of the POD?"), /* @__PURE__ */ React320.createElement(Text199, { size: "xs", c: "dimmed" }, "Detected a DAO DAO group (", classification?.daodao?.type, "). Choose how to grant access."), /* @__PURE__ */ React320.createElement(Radio5.Group, { value: granteeKind, onChange: (value) => setGranteeKind(value) }, /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs", mt: "xs" }, /* @__PURE__ */ React320.createElement(
|
|
34649
|
+
)), addMode === "single" && (canClassify ? /* @__PURE__ */ React320.createElement(Button67, { size: "xs", variant: "light", onClick: runClassify, disabled: !addAddress.trim() || classifying || isRunning, loading: classifying }, "Check address") : /* @__PURE__ */ React320.createElement(Text199, { size: "xs", c: "dimmed" }, "Address classification is unavailable in this host \u2014 the grantee will be added as a plain account.")), addMode === "single" && classifyError && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: "red", styles: actionAlertStyles }, classifyError), addMode === "single" && isGroup && /* @__PURE__ */ React320.createElement(Box60, { style: { border: "1px solid var(--mantine-color-neutralColor-6)", borderRadius: 8, padding: 12 } }, /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs" }, /* @__PURE__ */ React320.createElement(Text199, { size: "sm", fw: 600 }, "Add the group, or all the members of the POD?"), /* @__PURE__ */ React320.createElement(Text199, { size: "xs", c: "dimmed" }, "Detected a DAO DAO group (", classification?.daodao?.type, "). Choose how to grant access."), /* @__PURE__ */ React320.createElement(Radio5.Group, { value: granteeKind, onChange: (value) => setGranteeKind(value) }, /* @__PURE__ */ React320.createElement(Stack211, { gap: "xs", mt: "xs" }, /* @__PURE__ */ React320.createElement(
|
|
34395
34650
|
Radio5,
|
|
34396
34651
|
{
|
|
34397
34652
|
value: "group-account",
|
|
@@ -34405,7 +34660,7 @@ var CollectionUsersFlowDetail = ({
|
|
|
34405
34660
|
disabled: isDisabled || isRunning,
|
|
34406
34661
|
label: /* @__PURE__ */ React320.createElement(Stack211, { gap: 0 }, /* @__PURE__ */ React320.createElement(Text199, { size: "sm" }, "Add all members of the POD"), /* @__PURE__ */ React320.createElement(Text199, { size: "xs", c: "dimmed" }, canEnumerate ? `Fan out: grant each member individually${members.length ? ` (${members.length} resolved)` : ""}.` : "Member enumeration is unavailable in this host."))
|
|
34407
34662
|
}
|
|
34408
|
-
))))), /* @__PURE__ */ React320.createElement(
|
|
34663
|
+
))), granteeKind === "group-members" && !actAs.actAsGroup && memberSigningPlan && /* @__PURE__ */ React320.createElement(DismissibleAlert, { color: memberSigningPlan.color, styles: actionAlertStyles }, memberSigningPlan.message))), addMode === "list" && bulkAddresses.length > 0 && /* @__PURE__ */ React320.createElement(Text199, { size: "xs", c: "dimmed" }, "The role, quota and limits below apply to all ", bulkAddresses.length, " accounts."), /* @__PURE__ */ React320.createElement(
|
|
34409
34664
|
BaseSelect,
|
|
34410
34665
|
{
|
|
34411
34666
|
label: "Role",
|
|
@@ -57934,4 +58189,4 @@ export {
|
|
|
57934
58189
|
ixoGraphQLClient,
|
|
57935
58190
|
getEntity
|
|
57936
58191
|
};
|
|
57937
|
-
//# sourceMappingURL=chunk-
|
|
58192
|
+
//# sourceMappingURL=chunk-NYQBGIZ2.js.map
|