@ixo/editor 6.3.0 → 6.5.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 +2083 -9
- package/dist/{chunk-W2ONFUVP.js → chunk-6J7SYJQB.js} +7181 -3728
- package/dist/chunk-6J7SYJQB.js.map +1 -0
- package/dist/{chunk-5JGB36AV.js → chunk-DZMEWZ5Z.js} +2 -2
- package/dist/{chunk-GUKGNTGT.js → chunk-EULL3QTC.js} +1572 -27
- package/dist/chunk-EULL3QTC.js.map +1 -0
- package/dist/core/index.d.ts +9 -5
- package/dist/core/index.js +6 -2
- package/dist/core/index.js.map +1 -1
- package/dist/{graphql-client-Bje1zG1x.d.ts → graphql-client-sSYnXfw4.d.ts} +1 -1
- package/dist/{index-KtqCT-bj.d.ts → index-veeFe81f.d.ts} +115 -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-CZP9PIO-.d.ts → store-2MxKjorO.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-GUKGNTGT.js.map +0 -1
- package/dist/chunk-W2ONFUVP.js.map +0 -1
- /package/dist/{chunk-5JGB36AV.js.map → chunk-DZMEWZ5Z.js.map} +0 -0
|
@@ -917,6 +917,8 @@ registerAction({
|
|
|
917
917
|
requiredCapability: "flow/block/execute",
|
|
918
918
|
outputSchema: [
|
|
919
919
|
{ path: "proposalId", displayName: "Proposal ID", type: "string", description: "The on-chain proposal identifier" },
|
|
920
|
+
{ path: "proposalTitle", displayName: "Proposal Title", type: "string", description: "The proposal name voters see on-chain" },
|
|
921
|
+
{ path: "proposalDescription", displayName: "Proposal Description", type: "string", description: "The long-form description voters see on-chain" },
|
|
920
922
|
{ path: "status", displayName: "Proposal Status", type: "string", description: "Current proposal status (open, passed, rejected, executed, etc.)" },
|
|
921
923
|
{ path: "proposalContractAddress", displayName: "Proposal Contract Address", type: "string", description: "The proposal module contract address" },
|
|
922
924
|
{ path: "coreAddress", displayName: "Core Address", type: "string", description: "The DAO core contract address" },
|
|
@@ -976,6 +978,8 @@ registerAction({
|
|
|
976
978
|
return {
|
|
977
979
|
output: {
|
|
978
980
|
proposalId: String(proposalId),
|
|
981
|
+
proposalTitle: title,
|
|
982
|
+
proposalDescription: description,
|
|
979
983
|
status: "open",
|
|
980
984
|
proposalContractAddress: proposalContractAddress || "",
|
|
981
985
|
coreAddress,
|
|
@@ -1003,6 +1007,8 @@ registerAction({
|
|
|
1003
1007
|
requiredCapability: "flow/block/execute",
|
|
1004
1008
|
outputSchema: [
|
|
1005
1009
|
{ path: "proposalId", displayName: "Proposal ID", type: "string", description: "The on-chain proposal identifier" },
|
|
1010
|
+
{ path: "proposalTitle", displayName: "Proposal Title", type: "string", description: "The proposal name voters see on-chain" },
|
|
1011
|
+
{ path: "proposalDescription", displayName: "Proposal Description", type: "string", description: "The long-form description voters see on-chain" },
|
|
1006
1012
|
{ path: "status", displayName: "Proposal Status", type: "string", description: "Current proposal status (open, passed, rejected, executed, etc.)" },
|
|
1007
1013
|
{ path: "proposalContractAddress", displayName: "Proposal Contract Address", type: "string", description: "The proposal module contract address" },
|
|
1008
1014
|
{ path: "coreAddress", displayName: "Core Address", type: "string", description: "The DAO core contract address" },
|
|
@@ -1040,7 +1046,7 @@ registerAction({
|
|
|
1040
1046
|
};
|
|
1041
1047
|
const updateVotingConfigAction = { type: "UpdateVotingConfig", data };
|
|
1042
1048
|
const title = String(inputs.title || "").trim() || "Update governance settings";
|
|
1043
|
-
const description = String(inputs.description || "").trim() || "Updates the
|
|
1049
|
+
const description = String(inputs.description || "").trim() || "Updates the POD's voting rules once the proposal passes.";
|
|
1044
1050
|
const { preProposalContractAddress } = await handlers.getPreProposalContractAddress({ coreAddress });
|
|
1045
1051
|
const { groupContractAddress } = await handlers.getGroupContractAddress({ coreAddress });
|
|
1046
1052
|
const { proposalContractAddress } = await handlers.getProposalContractAddress({ coreAddress });
|
|
@@ -1058,6 +1064,8 @@ registerAction({
|
|
|
1058
1064
|
return {
|
|
1059
1065
|
output: {
|
|
1060
1066
|
proposalId: String(proposalId),
|
|
1067
|
+
proposalTitle: title,
|
|
1068
|
+
proposalDescription: description,
|
|
1061
1069
|
status: "open",
|
|
1062
1070
|
proposalContractAddress: proposalContractAddress || "",
|
|
1063
1071
|
coreAddress,
|
|
@@ -1067,6 +1075,121 @@ registerAction({
|
|
|
1067
1075
|
}
|
|
1068
1076
|
});
|
|
1069
1077
|
|
|
1078
|
+
// src/core/lib/actionRegistry/actions/governance/_shared.ts
|
|
1079
|
+
var STANDARD_OUTPUT_SCHEMA = [
|
|
1080
|
+
{ path: "proposalId", displayName: "Proposal ID", type: "string", description: "The on-chain proposal identifier" },
|
|
1081
|
+
{ path: "proposalTitle", displayName: "Proposal Title", type: "string", description: "The proposal name voters see on-chain" },
|
|
1082
|
+
{ path: "proposalDescription", displayName: "Proposal Description", type: "string", description: "The long-form description voters see on-chain" },
|
|
1083
|
+
{ path: "status", displayName: "Proposal Status", type: "string", description: "Current proposal status (open, passed, rejected, executed, etc.)" },
|
|
1084
|
+
{ path: "proposalContractAddress", displayName: "Proposal Contract Address", type: "string", description: "The proposal module contract address" },
|
|
1085
|
+
{ path: "coreAddress", displayName: "Core Address", type: "string", description: "The DAO core contract address" },
|
|
1086
|
+
{ path: "createdAt", displayName: "Created At", type: "string", description: "ISO timestamp of proposal creation" }
|
|
1087
|
+
];
|
|
1088
|
+
function registerGovernanceProposalAction(spec) {
|
|
1089
|
+
registerAction({
|
|
1090
|
+
type: spec.type,
|
|
1091
|
+
can: spec.can,
|
|
1092
|
+
sideEffect: true,
|
|
1093
|
+
proof: { fields: ["proposalId"] },
|
|
1094
|
+
defaultRequiresConfirmation: true,
|
|
1095
|
+
requiredCapability: "flow/block/execute",
|
|
1096
|
+
outputSchema: [...STANDARD_OUTPUT_SCHEMA, ...spec.extraOutputSchema || []],
|
|
1097
|
+
run: async (inputs, ctx) => {
|
|
1098
|
+
const handlers = ctx.handlers;
|
|
1099
|
+
if (!handlers) {
|
|
1100
|
+
throw new Error("Handlers not available");
|
|
1101
|
+
}
|
|
1102
|
+
if (!handlers.getPreProposalContractAddress || !handlers.getGroupContractAddress || !handlers.getProposalContractAddress || !handlers.createProposal) {
|
|
1103
|
+
throw new Error("Governance proposal handlers not available");
|
|
1104
|
+
}
|
|
1105
|
+
const coreAddress = String(inputs.coreAddress || "").trim();
|
|
1106
|
+
if (!coreAddress) throw new Error("coreAddress is required");
|
|
1107
|
+
const actions2 = spec.buildActions(inputs);
|
|
1108
|
+
if (!actions2.length) throw new Error("The proposal must contain at least one action");
|
|
1109
|
+
const title = String(inputs.title || "").trim() || spec.defaultTitle(inputs);
|
|
1110
|
+
const description = String(inputs.description || "").trim() || (spec.defaultDescription ? spec.defaultDescription(inputs) : title);
|
|
1111
|
+
const { preProposalContractAddress } = await handlers.getPreProposalContractAddress({ coreAddress });
|
|
1112
|
+
const { groupContractAddress } = await handlers.getGroupContractAddress({ coreAddress });
|
|
1113
|
+
const { proposalContractAddress } = await handlers.getProposalContractAddress({ coreAddress });
|
|
1114
|
+
const proposalId = await handlers.createProposal({
|
|
1115
|
+
preProposalContractAddress,
|
|
1116
|
+
title,
|
|
1117
|
+
description,
|
|
1118
|
+
actions: actions2,
|
|
1119
|
+
coreAddress,
|
|
1120
|
+
groupContractAddress
|
|
1121
|
+
});
|
|
1122
|
+
if (proposalId === void 0 || proposalId === null || String(proposalId).trim() === "") {
|
|
1123
|
+
throw new Error("Proposal creation returned no proposal id. Check the handler logs.");
|
|
1124
|
+
}
|
|
1125
|
+
return {
|
|
1126
|
+
output: {
|
|
1127
|
+
proposalId: String(proposalId),
|
|
1128
|
+
proposalTitle: title,
|
|
1129
|
+
proposalDescription: description,
|
|
1130
|
+
status: "open",
|
|
1131
|
+
proposalContractAddress: proposalContractAddress || "",
|
|
1132
|
+
coreAddress,
|
|
1133
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1134
|
+
...spec.buildExtraOutput ? spec.buildExtraOutput(inputs) : {}
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// src/core/lib/actionRegistry/actions/governance/submissionConfigProposal.ts
|
|
1142
|
+
var REFUND_POLICIES = ["always", "only_passed", "never"];
|
|
1143
|
+
registerGovernanceProposalAction({
|
|
1144
|
+
type: "qi/governance.submission-config-proposal",
|
|
1145
|
+
can: "governance/submission-config-proposal",
|
|
1146
|
+
buildActions: (inputs) => {
|
|
1147
|
+
const anyoneCanPropose = Boolean(inputs.anyoneCanPropose);
|
|
1148
|
+
const depositRequired = Boolean(inputs.depositRequired);
|
|
1149
|
+
let amount = "0";
|
|
1150
|
+
let refundPolicy = "always";
|
|
1151
|
+
if (depositRequired) {
|
|
1152
|
+
amount = String(inputs.depositAmount || "").trim();
|
|
1153
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1154
|
+
throw new Error("depositAmount must be a positive whole number in uixo base units");
|
|
1155
|
+
}
|
|
1156
|
+
const policy = String(inputs.depositRefundPolicy || "").trim();
|
|
1157
|
+
if (!REFUND_POLICIES.includes(policy)) {
|
|
1158
|
+
throw new Error("depositRefundPolicy must be one of 'always', 'only_passed' or 'never'");
|
|
1159
|
+
}
|
|
1160
|
+
refundPolicy = policy;
|
|
1161
|
+
}
|
|
1162
|
+
return [
|
|
1163
|
+
{
|
|
1164
|
+
type: "UpdatePreProposeConfig",
|
|
1165
|
+
data: {
|
|
1166
|
+
depositRequired,
|
|
1167
|
+
// Deposit token fixed to the chain's native IXO (uixo) for now.
|
|
1168
|
+
depositInfo: { amount, type: "native", denomOrAddress: "uixo", refundPolicy },
|
|
1169
|
+
anyoneCanPropose
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
];
|
|
1173
|
+
},
|
|
1174
|
+
defaultTitle: () => "Update proposal submission rules",
|
|
1175
|
+
defaultDescription: () => "Updates who may submit proposals and the required deposit once the proposal passes.",
|
|
1176
|
+
buildExtraOutput: (inputs) => {
|
|
1177
|
+
const depositRequired = Boolean(inputs.depositRequired);
|
|
1178
|
+
return {
|
|
1179
|
+
anyoneCanPropose: String(Boolean(inputs.anyoneCanPropose)),
|
|
1180
|
+
depositRequired: String(depositRequired),
|
|
1181
|
+
depositAmount: depositRequired ? String(inputs.depositAmount || "") : "0",
|
|
1182
|
+
depositRefundPolicy: depositRequired ? String(inputs.depositRefundPolicy || "") : "always"
|
|
1183
|
+
};
|
|
1184
|
+
},
|
|
1185
|
+
extraOutputSchema: [
|
|
1186
|
+
{ path: "anyoneCanPropose", displayName: "Anyone Can Propose", type: "string", description: "Whether non-members may submit proposals after the update" },
|
|
1187
|
+
{ path: "depositRequired", displayName: "Deposit Required", type: "string", description: "Whether a deposit is required to submit a proposal" },
|
|
1188
|
+
{ path: "depositAmount", displayName: "Deposit Amount", type: "string", description: "Required deposit in uixo base units" },
|
|
1189
|
+
{ path: "depositRefundPolicy", displayName: "Deposit Refund Policy", type: "string", description: "What happens to the deposit after voting ends" }
|
|
1190
|
+
]
|
|
1191
|
+
});
|
|
1192
|
+
|
|
1070
1193
|
// src/core/lib/actionRegistry/actions/governance/transactionSendFunds.ts
|
|
1071
1194
|
registerAction({
|
|
1072
1195
|
type: "qi/governance.transaction.send-funds",
|
|
@@ -1077,6 +1200,8 @@ registerAction({
|
|
|
1077
1200
|
requiredCapability: "flow/block/execute",
|
|
1078
1201
|
outputSchema: [
|
|
1079
1202
|
{ path: "proposalId", displayName: "Proposal ID", type: "string", description: "The on-chain proposal identifier" },
|
|
1203
|
+
{ path: "proposalTitle", displayName: "Proposal Title", type: "string", description: "The proposal name voters see on-chain" },
|
|
1204
|
+
{ path: "proposalDescription", displayName: "Proposal Description", type: "string", description: "The long-form description voters see on-chain" },
|
|
1080
1205
|
{ path: "status", displayName: "Proposal Status", type: "string", description: "Current proposal status (open, passed, rejected, executed, etc.)" },
|
|
1081
1206
|
{ path: "proposalContractAddress", displayName: "Proposal Contract Address", type: "string", description: "The proposal module contract address" },
|
|
1082
1207
|
{ path: "coreAddress", displayName: "Core Address", type: "string", description: "The DAO core contract address" },
|
|
@@ -1109,7 +1234,7 @@ registerAction({
|
|
|
1109
1234
|
const baseAmount = BigInt(Math.round(amount * 10 ** tokenInfo.exponent)).toString();
|
|
1110
1235
|
const spendAction = { type: "Spend", data: { to: recipient, denom, amount: baseAmount } };
|
|
1111
1236
|
const title = String(inputs.title || "").trim() || `Send ${amount} ${tokenInfo.symbol} to ${recipient}`;
|
|
1112
|
-
const description = String(inputs.description || "").trim() || "Sends funds from the
|
|
1237
|
+
const description = String(inputs.description || "").trim() || "Sends funds from the POD treasury once the proposal passes.";
|
|
1113
1238
|
const { preProposalContractAddress } = await handlers.getPreProposalContractAddress({ coreAddress });
|
|
1114
1239
|
const { groupContractAddress } = await handlers.getGroupContractAddress({ coreAddress });
|
|
1115
1240
|
const { proposalContractAddress } = await handlers.getProposalContractAddress({ coreAddress });
|
|
@@ -1127,6 +1252,8 @@ registerAction({
|
|
|
1127
1252
|
return {
|
|
1128
1253
|
output: {
|
|
1129
1254
|
proposalId: String(proposalId),
|
|
1255
|
+
proposalTitle: title,
|
|
1256
|
+
proposalDescription: description,
|
|
1130
1257
|
status: "open",
|
|
1131
1258
|
proposalContractAddress: proposalContractAddress || "",
|
|
1132
1259
|
coreAddress,
|
|
@@ -1137,6 +1264,847 @@ registerAction({
|
|
|
1137
1264
|
}
|
|
1138
1265
|
});
|
|
1139
1266
|
|
|
1267
|
+
// src/core/lib/actionRegistry/actions/governance/transactionSendGroupToken.ts
|
|
1268
|
+
registerGovernanceProposalAction({
|
|
1269
|
+
type: "qi/governance.transaction.send-group-token",
|
|
1270
|
+
can: "governance.transaction/send-group-token",
|
|
1271
|
+
buildActions: (inputs) => {
|
|
1272
|
+
const contract = String(inputs.tokenContract || "").trim();
|
|
1273
|
+
if (!contract) throw new Error("tokenContract is required");
|
|
1274
|
+
const toAddress = String(inputs.recipient || "").trim();
|
|
1275
|
+
if (!toAddress) throw new Error("recipient is required");
|
|
1276
|
+
const amount = String(inputs.amount || "").trim();
|
|
1277
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1278
|
+
throw new Error("amount must be a positive whole number in the token\u2019s base units");
|
|
1279
|
+
}
|
|
1280
|
+
return [{ type: "SendGroupToken", data: { contract, toAddress, amount } }];
|
|
1281
|
+
},
|
|
1282
|
+
defaultTitle: (inputs) => `Send ${inputs.amount} group tokens to ${inputs.recipient}`,
|
|
1283
|
+
defaultDescription: () => "Transfers group tokens from the treasury once the proposal passes.",
|
|
1284
|
+
buildExtraOutput: (inputs) => ({ recipient: String(inputs.recipient || ""), tokenContract: String(inputs.tokenContract || "") }),
|
|
1285
|
+
extraOutputSchema: [
|
|
1286
|
+
{ path: "recipient", displayName: "Recipient", type: "string", description: "Destination address of the transfer" },
|
|
1287
|
+
{ path: "tokenContract", displayName: "Token Contract", type: "string", description: "The cw20 token contract transferred from" }
|
|
1288
|
+
]
|
|
1289
|
+
});
|
|
1290
|
+
|
|
1291
|
+
// src/core/lib/actionRegistry/actions/governance/transactionMint.ts
|
|
1292
|
+
registerGovernanceProposalAction({
|
|
1293
|
+
type: "qi/governance.transaction.mint",
|
|
1294
|
+
can: "governance.transaction/mint",
|
|
1295
|
+
buildActions: (inputs) => {
|
|
1296
|
+
const to = String(inputs.recipient || "").trim();
|
|
1297
|
+
if (!to) throw new Error("recipient is required");
|
|
1298
|
+
const amount = String(inputs.amount ?? "").trim();
|
|
1299
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1300
|
+
throw new Error("amount must be a positive whole number in the token\u2019s base units");
|
|
1301
|
+
}
|
|
1302
|
+
return [{ type: "Mint", data: { to, amount } }];
|
|
1303
|
+
},
|
|
1304
|
+
defaultTitle: (inputs) => `Mint ${inputs.amount} governance tokens to ${inputs.recipient}`,
|
|
1305
|
+
defaultDescription: () => "Mints new governance tokens to the recipient once the proposal passes.",
|
|
1306
|
+
buildExtraOutput: (inputs) => ({ recipient: String(inputs.recipient || ""), amount: String(inputs.amount || "") }),
|
|
1307
|
+
extraOutputSchema: [
|
|
1308
|
+
{ path: "recipient", displayName: "Recipient", type: "string", description: "Destination address the tokens are minted to" },
|
|
1309
|
+
{ path: "amount", displayName: "Amount", type: "string", description: "Number of governance tokens minted" }
|
|
1310
|
+
]
|
|
1311
|
+
});
|
|
1312
|
+
|
|
1313
|
+
// src/core/lib/actionRegistry/actions/governance/transactionPerformTokenSwap.ts
|
|
1314
|
+
registerGovernanceProposalAction({
|
|
1315
|
+
type: "qi/governance.transaction.perform-token-swap",
|
|
1316
|
+
can: "governance.transaction/perform-token-swap",
|
|
1317
|
+
buildActions: (inputs) => {
|
|
1318
|
+
const tokenSwapContractAddress = String(inputs.tokenSwapContractAddress || "").trim();
|
|
1319
|
+
if (!tokenSwapContractAddress) throw new Error("tokenSwapContractAddress is required");
|
|
1320
|
+
const type = String(inputs.selfPartyType || "").trim();
|
|
1321
|
+
if (type !== "native" && type !== "cw20") throw new Error("selfPartyType must be 'native' or 'cw20'");
|
|
1322
|
+
const denomOrAddress = String(inputs.selfPartyDenomOrAddress || "").trim();
|
|
1323
|
+
if (!denomOrAddress) throw new Error("selfPartyDenomOrAddress is required");
|
|
1324
|
+
const amount = String(inputs.selfPartyAmount || "").trim();
|
|
1325
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1326
|
+
throw new Error("selfPartyAmount must be a positive whole number in the token\u2019s base units");
|
|
1327
|
+
}
|
|
1328
|
+
return [
|
|
1329
|
+
{
|
|
1330
|
+
type: "PerformTokenSwap",
|
|
1331
|
+
data: { contractChosen: true, tokenSwapContractAddress, selfParty: { type, denomOrAddress, amount } }
|
|
1332
|
+
}
|
|
1333
|
+
];
|
|
1334
|
+
},
|
|
1335
|
+
defaultTitle: (inputs) => `Fund token swap ${inputs.tokenSwapContractAddress}`,
|
|
1336
|
+
defaultDescription: () => "Sends the group\u2019s side of the token swap to the swap contract once the proposal passes.",
|
|
1337
|
+
buildExtraOutput: (inputs) => ({
|
|
1338
|
+
tokenSwapContractAddress: String(inputs.tokenSwapContractAddress || ""),
|
|
1339
|
+
selfPartyDenomOrAddress: String(inputs.selfPartyDenomOrAddress || ""),
|
|
1340
|
+
selfPartyAmount: String(inputs.selfPartyAmount || "")
|
|
1341
|
+
}),
|
|
1342
|
+
extraOutputSchema: [
|
|
1343
|
+
{ path: "tokenSwapContractAddress", displayName: "Swap Contract", type: "string", description: "The cw-token-swap contract funded" },
|
|
1344
|
+
{ path: "selfPartyDenomOrAddress", displayName: "Token Denom / Address", type: "string", description: "The native denom or cw20 address the group provides" },
|
|
1345
|
+
{ path: "selfPartyAmount", displayName: "Amount", type: "string", description: "Amount provided, in the token\u2019s base units" }
|
|
1346
|
+
]
|
|
1347
|
+
});
|
|
1348
|
+
|
|
1349
|
+
// src/core/lib/actionRegistry/actions/governance/transactionWithdrawTokenSwap.ts
|
|
1350
|
+
registerGovernanceProposalAction({
|
|
1351
|
+
type: "qi/governance.transaction.withdraw-token-swap",
|
|
1352
|
+
can: "governance.transaction/withdraw-token-swap",
|
|
1353
|
+
buildActions: (inputs) => {
|
|
1354
|
+
const tokenSwapContractAddress = String(inputs.tokenSwapContractAddress || "").trim();
|
|
1355
|
+
if (!tokenSwapContractAddress) throw new Error("tokenSwapContractAddress is required");
|
|
1356
|
+
return [{ type: "WithdrawTokenSwap", data: { contractChosen: true, tokenSwapContractAddress } }];
|
|
1357
|
+
},
|
|
1358
|
+
defaultTitle: (inputs) => `Withdraw from token swap ${inputs.tokenSwapContractAddress}`,
|
|
1359
|
+
defaultDescription: () => "Returns the group\u2019s funds from the token swap contract once the proposal passes.",
|
|
1360
|
+
buildExtraOutput: (inputs) => ({ tokenSwapContractAddress: String(inputs.tokenSwapContractAddress || "") }),
|
|
1361
|
+
extraOutputSchema: [{ path: "tokenSwapContractAddress", displayName: "Swap Contract", type: "string", description: "The cw-token-swap contract withdrawn from" }]
|
|
1362
|
+
});
|
|
1363
|
+
|
|
1364
|
+
// src/core/lib/actionRegistry/actions/governance/stakingStake.ts
|
|
1365
|
+
var STAKE_TYPES = ["delegate", "undelegate", "redelegate", "withdraw_delegator_reward"];
|
|
1366
|
+
var displayIxo = (amount) => {
|
|
1367
|
+
const base = Number(amount);
|
|
1368
|
+
return Number.isFinite(base) ? String(base / 1e6) : String(amount || "");
|
|
1369
|
+
};
|
|
1370
|
+
registerGovernanceProposalAction({
|
|
1371
|
+
type: "qi/governance.staking.stake",
|
|
1372
|
+
can: "governance.staking/stake",
|
|
1373
|
+
buildActions: (inputs) => {
|
|
1374
|
+
const stakeType = String(inputs.stakeType || "").trim();
|
|
1375
|
+
if (!STAKE_TYPES.includes(stakeType)) {
|
|
1376
|
+
throw new Error("stakeType must be delegate, undelegate, redelegate or withdraw_delegator_reward");
|
|
1377
|
+
}
|
|
1378
|
+
const validator = String(inputs.validator || "").trim();
|
|
1379
|
+
if (!validator) throw new Error("validator is required");
|
|
1380
|
+
const isRedelegate = stakeType === "redelegate";
|
|
1381
|
+
const toValidator = String(inputs.toValidator || "").trim();
|
|
1382
|
+
if (isRedelegate && !toValidator) throw new Error("toValidator is required for redelegations");
|
|
1383
|
+
let amount = "0";
|
|
1384
|
+
if (stakeType !== "withdraw_delegator_reward") {
|
|
1385
|
+
amount = String(inputs.amount || "").trim();
|
|
1386
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1387
|
+
throw new Error("amount must be a positive whole number of uixo (base units)");
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
return [{ type: "Stake", data: { stakeType, validator, toValidator: isRedelegate ? toValidator : "", amount, denom: "uixo" } }];
|
|
1391
|
+
},
|
|
1392
|
+
// buildActions runs first, so the stake type is always a valid option here.
|
|
1393
|
+
defaultTitle: (inputs) => {
|
|
1394
|
+
switch (String(inputs.stakeType)) {
|
|
1395
|
+
case "undelegate":
|
|
1396
|
+
return `Unstake ${displayIxo(inputs.amount)} IXO from ${inputs.validator}`;
|
|
1397
|
+
case "redelegate":
|
|
1398
|
+
return `Restake ${displayIxo(inputs.amount)} IXO from ${inputs.validator} to ${inputs.toValidator}`;
|
|
1399
|
+
case "withdraw_delegator_reward":
|
|
1400
|
+
return `Claim staking rewards from ${inputs.validator}`;
|
|
1401
|
+
default:
|
|
1402
|
+
return `Stake ${displayIxo(inputs.amount)} IXO with ${inputs.validator}`;
|
|
1403
|
+
}
|
|
1404
|
+
},
|
|
1405
|
+
defaultDescription: () => "Executes the staking operation from the POD treasury once the proposal passes.",
|
|
1406
|
+
buildExtraOutput: (inputs) => ({
|
|
1407
|
+
stakeType: String(inputs.stakeType || ""),
|
|
1408
|
+
validator: String(inputs.validator || ""),
|
|
1409
|
+
amount: String(inputs.amount || "")
|
|
1410
|
+
}),
|
|
1411
|
+
extraOutputSchema: [
|
|
1412
|
+
{ path: "stakeType", displayName: "Stake Type", type: "string", description: "The staking operation (delegate, undelegate, redelegate, withdraw_delegator_reward)" },
|
|
1413
|
+
{ path: "validator", displayName: "Validator", type: "string", description: "The validator the operation targets (source for redelegations)" },
|
|
1414
|
+
{ path: "amount", displayName: "Amount", type: "string", description: "The uixo amount staked, in base units" }
|
|
1415
|
+
]
|
|
1416
|
+
});
|
|
1417
|
+
|
|
1418
|
+
// src/core/lib/actionRegistry/actions/governance/stakingStakeToGroup.ts
|
|
1419
|
+
registerGovernanceProposalAction({
|
|
1420
|
+
type: "qi/governance.staking.stake-to-group",
|
|
1421
|
+
can: "governance.staking/stake-to-group",
|
|
1422
|
+
buildActions: (inputs) => {
|
|
1423
|
+
const tokenContract = String(inputs.tokenContract || "").trim();
|
|
1424
|
+
if (!tokenContract) throw new Error("tokenContract is required");
|
|
1425
|
+
const stakingContract = String(inputs.stakingContract || "").trim();
|
|
1426
|
+
if (!stakingContract) throw new Error("stakingContract is required");
|
|
1427
|
+
const amount = String(inputs.amount || "").trim();
|
|
1428
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1429
|
+
throw new Error("amount must be a positive whole number in the token\u2019s base units");
|
|
1430
|
+
}
|
|
1431
|
+
return [{ type: "StakeToGroup", data: { tokenContract, stakingContract, amount } }];
|
|
1432
|
+
},
|
|
1433
|
+
defaultTitle: (inputs) => `Stake ${inputs.amount} tokens to the group`,
|
|
1434
|
+
defaultDescription: () => "Stakes treasury tokens into the group staking contract once the proposal passes.",
|
|
1435
|
+
buildExtraOutput: (inputs) => ({ tokenContract: String(inputs.tokenContract || ""), stakingContract: String(inputs.stakingContract || "") }),
|
|
1436
|
+
extraOutputSchema: [
|
|
1437
|
+
{ path: "tokenContract", displayName: "Token Contract", type: "string", description: "The cw20 token contract the tokens are sent from" },
|
|
1438
|
+
{ path: "stakingContract", displayName: "Staking Contract", type: "string", description: "The staking contract the tokens are staked into" }
|
|
1439
|
+
]
|
|
1440
|
+
});
|
|
1441
|
+
|
|
1442
|
+
// src/core/lib/actionRegistry/actions/governance/authzGrant.ts
|
|
1443
|
+
registerGovernanceProposalAction({
|
|
1444
|
+
type: "qi/governance.authz.grant",
|
|
1445
|
+
can: "governance.authz/grant",
|
|
1446
|
+
buildActions: (inputs) => {
|
|
1447
|
+
const grantee = String(inputs.grantee || "").trim();
|
|
1448
|
+
if (!grantee) throw new Error("grantee is required");
|
|
1449
|
+
const msgTypeUrl = String(inputs.msgTypeUrl || "").trim();
|
|
1450
|
+
if (!msgTypeUrl) throw new Error("msgTypeUrl is required");
|
|
1451
|
+
if (!msgTypeUrl.startsWith("/")) {
|
|
1452
|
+
throw new Error('msgTypeUrl must be a fully-qualified message type URL starting with "/"');
|
|
1453
|
+
}
|
|
1454
|
+
return [{ type: "AuthzGrant", data: { typeUrl: "/cosmos.authz.v1beta1.MsgGrant", value: { grantee, msgTypeUrl } } }];
|
|
1455
|
+
},
|
|
1456
|
+
defaultTitle: (inputs) => `Grant ${inputs.msgTypeUrl} authorization to ${inputs.grantee}`,
|
|
1457
|
+
defaultDescription: () => "Authorizes the grantee to execute the message type on the group\u2019s behalf (1-year expiry) once the proposal passes.",
|
|
1458
|
+
buildExtraOutput: (inputs) => ({ grantee: String(inputs.grantee || ""), msgTypeUrl: String(inputs.msgTypeUrl || "") }),
|
|
1459
|
+
extraOutputSchema: [
|
|
1460
|
+
{ path: "grantee", displayName: "Grantee", type: "string", description: "Address that receives the authorization" },
|
|
1461
|
+
{ path: "msgTypeUrl", displayName: "Message Type URL", type: "string", description: "The message type the grantee may execute" }
|
|
1462
|
+
]
|
|
1463
|
+
});
|
|
1464
|
+
|
|
1465
|
+
// src/core/lib/actionRegistry/actions/governance/authzRevoke.ts
|
|
1466
|
+
registerGovernanceProposalAction({
|
|
1467
|
+
type: "qi/governance.authz.revoke",
|
|
1468
|
+
can: "governance.authz/revoke",
|
|
1469
|
+
buildActions: (inputs) => {
|
|
1470
|
+
const grantee = String(inputs.grantee || "").trim();
|
|
1471
|
+
if (!grantee) throw new Error("grantee is required");
|
|
1472
|
+
const msgTypeUrl = String(inputs.msgTypeUrl || "").trim();
|
|
1473
|
+
if (!msgTypeUrl) throw new Error("msgTypeUrl is required");
|
|
1474
|
+
if (!msgTypeUrl.startsWith("/")) {
|
|
1475
|
+
throw new Error('msgTypeUrl must be a fully-qualified message type URL starting with "/"');
|
|
1476
|
+
}
|
|
1477
|
+
return [{ type: "AuthzRevoke", data: { typeUrl: "/cosmos.authz.v1beta1.MsgRevoke", value: { grantee, msgTypeUrl } } }];
|
|
1478
|
+
},
|
|
1479
|
+
defaultTitle: (inputs) => `Revoke ${inputs.msgTypeUrl} authorization from ${inputs.grantee}`,
|
|
1480
|
+
defaultDescription: () => "Revokes the grantee\u2019s authorization to execute the message type on the group\u2019s behalf once the proposal passes.",
|
|
1481
|
+
buildExtraOutput: (inputs) => ({ grantee: String(inputs.grantee || ""), msgTypeUrl: String(inputs.msgTypeUrl || "") }),
|
|
1482
|
+
extraOutputSchema: [
|
|
1483
|
+
{ path: "grantee", displayName: "Grantee", type: "string", description: "Address whose authorization is revoked" },
|
|
1484
|
+
{ path: "msgTypeUrl", displayName: "Message Type URL", type: "string", description: "The message type of the revoked grant" }
|
|
1485
|
+
]
|
|
1486
|
+
});
|
|
1487
|
+
|
|
1488
|
+
// src/core/lib/actionRegistry/actions/governance/authzExec.ts
|
|
1489
|
+
var AUTHZ_EXEC_ACTION_TYPES = {
|
|
1490
|
+
delegate: "/cosmos.staking.v1beta1.MsgDelegate",
|
|
1491
|
+
undelegate: "/cosmos.staking.v1beta1.MsgUndelegate",
|
|
1492
|
+
redelegate: "/cosmos.staking.v1beta1.MsgBeginRedelegate",
|
|
1493
|
+
claimRewards: "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward",
|
|
1494
|
+
custom: "custom"
|
|
1495
|
+
};
|
|
1496
|
+
var ACTION_LABELS = {
|
|
1497
|
+
[AUTHZ_EXEC_ACTION_TYPES.delegate]: "delegate",
|
|
1498
|
+
[AUTHZ_EXEC_ACTION_TYPES.undelegate]: "undelegate",
|
|
1499
|
+
[AUTHZ_EXEC_ACTION_TYPES.redelegate]: "redelegate",
|
|
1500
|
+
[AUTHZ_EXEC_ACTION_TYPES.claimRewards]: "claim-rewards",
|
|
1501
|
+
[AUTHZ_EXEC_ACTION_TYPES.custom]: "custom"
|
|
1502
|
+
};
|
|
1503
|
+
registerGovernanceProposalAction({
|
|
1504
|
+
type: "qi/governance.authz.exec",
|
|
1505
|
+
can: "governance.authz/exec",
|
|
1506
|
+
buildActions: (inputs) => {
|
|
1507
|
+
const actionType = String(inputs.authzExecActionType || "").trim();
|
|
1508
|
+
const known = Object.values(AUTHZ_EXEC_ACTION_TYPES);
|
|
1509
|
+
if (!known.includes(actionType)) {
|
|
1510
|
+
throw new Error(`authzExecActionType must be one of: ${known.join(", ")}`);
|
|
1511
|
+
}
|
|
1512
|
+
const delegator = String(inputs.delegatorAddress || "").trim();
|
|
1513
|
+
const validator = String(inputs.validatorAddress || "").trim();
|
|
1514
|
+
const validatorDst = String(inputs.validatorDstAddress || "").trim();
|
|
1515
|
+
const amount = String(inputs.amount || "").trim();
|
|
1516
|
+
const requireStakingFields = () => {
|
|
1517
|
+
if (!delegator) throw new Error("delegatorAddress is required");
|
|
1518
|
+
if (!validator) throw new Error("validatorAddress is required");
|
|
1519
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1520
|
+
throw new Error("amount must be a positive whole number in uixo base units");
|
|
1521
|
+
}
|
|
1522
|
+
};
|
|
1523
|
+
const data = {
|
|
1524
|
+
authzExecActionType: actionType,
|
|
1525
|
+
delegate: {},
|
|
1526
|
+
undelegate: {},
|
|
1527
|
+
redelegate: {},
|
|
1528
|
+
claimRewards: {},
|
|
1529
|
+
custom: ""
|
|
1530
|
+
};
|
|
1531
|
+
switch (actionType) {
|
|
1532
|
+
case AUTHZ_EXEC_ACTION_TYPES.delegate:
|
|
1533
|
+
requireStakingFields();
|
|
1534
|
+
data.delegate = { delegatorAddress: delegator, validatorAddress: validator, amount: { denom: "uixo", amount } };
|
|
1535
|
+
break;
|
|
1536
|
+
case AUTHZ_EXEC_ACTION_TYPES.undelegate:
|
|
1537
|
+
requireStakingFields();
|
|
1538
|
+
data.undelegate = { delegatorAddress: delegator, validatorAddress: validator, amount: { denom: "uixo", amount } };
|
|
1539
|
+
break;
|
|
1540
|
+
case AUTHZ_EXEC_ACTION_TYPES.redelegate:
|
|
1541
|
+
requireStakingFields();
|
|
1542
|
+
if (!validatorDst) throw new Error("validatorDstAddress is required");
|
|
1543
|
+
data.redelegate = { delegatorAddress: delegator, validatorSrcAddress: validator, validatorDstAddress: validatorDst, amount: { denom: "uixo", amount } };
|
|
1544
|
+
break;
|
|
1545
|
+
case AUTHZ_EXEC_ACTION_TYPES.claimRewards:
|
|
1546
|
+
if (!delegator) throw new Error("delegatorAddress is required");
|
|
1547
|
+
if (!validator) throw new Error("validatorAddress is required");
|
|
1548
|
+
data.claimRewards = { delegatorAddress: delegator, validatorAddress: validator };
|
|
1549
|
+
break;
|
|
1550
|
+
case AUTHZ_EXEC_ACTION_TYPES.custom: {
|
|
1551
|
+
const custom = String(inputs.custom || "").trim();
|
|
1552
|
+
if (!custom) throw new Error("custom is required");
|
|
1553
|
+
let parsed;
|
|
1554
|
+
try {
|
|
1555
|
+
parsed = JSON.parse(custom);
|
|
1556
|
+
} catch {
|
|
1557
|
+
throw new Error("custom must be valid JSON");
|
|
1558
|
+
}
|
|
1559
|
+
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
1560
|
+
throw new Error("custom must be a non-empty JSON array of encoded msgs");
|
|
1561
|
+
}
|
|
1562
|
+
data.custom = custom;
|
|
1563
|
+
break;
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
return [{ type: "AuthzExec", data }];
|
|
1567
|
+
},
|
|
1568
|
+
defaultTitle: (inputs) => `Execute authorized ${ACTION_LABELS[String(inputs.authzExecActionType || "").trim()] || "authz"} action`,
|
|
1569
|
+
defaultDescription: () => "Executes a message the group was previously authorized to run once the proposal passes.",
|
|
1570
|
+
buildExtraOutput: (inputs) => ({
|
|
1571
|
+
authzExecActionType: String(inputs.authzExecActionType || ""),
|
|
1572
|
+
validatorAddress: String(inputs.validatorAddress || "")
|
|
1573
|
+
}),
|
|
1574
|
+
extraOutputSchema: [
|
|
1575
|
+
{ path: "authzExecActionType", displayName: "Exec Action Type", type: "string", description: "The executed message type URL (or `custom`)" },
|
|
1576
|
+
{ path: "validatorAddress", displayName: "Validator Address", type: "string", description: "The validator targeted by staking ops (empty for custom)" }
|
|
1577
|
+
]
|
|
1578
|
+
});
|
|
1579
|
+
|
|
1580
|
+
// src/core/lib/actionRegistry/actions/governance/chainGovernanceVote.ts
|
|
1581
|
+
var VOTE_LABELS = { 1: "Yes", 2: "Abstain", 3: "No", 4: "No with veto" };
|
|
1582
|
+
registerGovernanceProposalAction({
|
|
1583
|
+
type: "qi/governance.chain-governance-vote",
|
|
1584
|
+
can: "governance/chain-governance-vote",
|
|
1585
|
+
buildActions: (inputs) => {
|
|
1586
|
+
const proposalId = String(inputs.proposalId || "").trim();
|
|
1587
|
+
if (!/^\d+$/.test(proposalId)) {
|
|
1588
|
+
throw new Error("proposalId must be a chain governance proposal number (digits only)");
|
|
1589
|
+
}
|
|
1590
|
+
const vote = Number(inputs.vote);
|
|
1591
|
+
if (!VOTE_LABELS[vote]) {
|
|
1592
|
+
throw new Error("vote must be 1 (Yes), 2 (Abstain), 3 (No) or 4 (No with veto)");
|
|
1593
|
+
}
|
|
1594
|
+
return [{ type: "GovernanceVote", data: { proposalId, vote } }];
|
|
1595
|
+
},
|
|
1596
|
+
// buildActions runs first, so the vote is always a valid option here.
|
|
1597
|
+
defaultTitle: (inputs) => `Vote ${VOTE_LABELS[Number(inputs.vote)]} on chain governance proposal #${inputs.proposalId}`,
|
|
1598
|
+
defaultDescription: () => "Casts the group's vote on the chain governance proposal once this proposal passes.",
|
|
1599
|
+
buildExtraOutput: (inputs) => ({
|
|
1600
|
+
chainProposalId: String(inputs.proposalId || ""),
|
|
1601
|
+
voteOption: VOTE_LABELS[Number(inputs.vote)] || String(inputs.vote || "")
|
|
1602
|
+
}),
|
|
1603
|
+
extraOutputSchema: [
|
|
1604
|
+
{ path: "chainProposalId", displayName: "Chain Proposal ID", type: "string", description: "The chain governance proposal the POD votes on" },
|
|
1605
|
+
{ path: "voteOption", displayName: "Vote Option", type: "string", description: "The vote cast (Yes, Abstain, No, No with veto)" }
|
|
1606
|
+
]
|
|
1607
|
+
});
|
|
1608
|
+
|
|
1609
|
+
// src/core/lib/actionRegistry/actions/governance/daoJoin.ts
|
|
1610
|
+
registerGovernanceProposalAction({
|
|
1611
|
+
type: "qi/governance.dao.join",
|
|
1612
|
+
can: "governance.dao/join",
|
|
1613
|
+
buildActions: (inputs) => {
|
|
1614
|
+
const id = String(inputs.entityDid || "").trim();
|
|
1615
|
+
if (!id) throw new Error("entityDid is required");
|
|
1616
|
+
const address = String(inputs.memberId || "").trim();
|
|
1617
|
+
if (!address) throw new Error("memberId is required");
|
|
1618
|
+
const coreAddress = String(inputs.coreAddress || "").trim();
|
|
1619
|
+
return [{ type: "Join", data: { id, coreAddress, address } }];
|
|
1620
|
+
},
|
|
1621
|
+
defaultTitle: (inputs) => `Join entity ${inputs.entityDid}`,
|
|
1622
|
+
defaultDescription: (inputs) => `Links ${inputs.memberId} as a member of ${inputs.entityDid} once the proposal passes.`,
|
|
1623
|
+
buildExtraOutput: (inputs) => ({ entityDid: String(inputs.entityDid || ""), memberId: String(inputs.memberId || "") }),
|
|
1624
|
+
extraOutputSchema: [
|
|
1625
|
+
{ path: "entityDid", displayName: "Entity DID", type: "string", description: "The entity the group joined" },
|
|
1626
|
+
{ path: "memberId", displayName: "Member ID", type: "string", description: "The member DID/id recorded as the linked entity" }
|
|
1627
|
+
]
|
|
1628
|
+
});
|
|
1629
|
+
|
|
1630
|
+
// src/core/lib/actionRegistry/actions/governance/daoUpdateInfo.ts
|
|
1631
|
+
registerGovernanceProposalAction({
|
|
1632
|
+
type: "qi/governance.dao.update-info",
|
|
1633
|
+
can: "governance.dao/update-info",
|
|
1634
|
+
buildActions: (inputs) => {
|
|
1635
|
+
const name = String(inputs.name || "").trim();
|
|
1636
|
+
if (!name) throw new Error("name is required");
|
|
1637
|
+
const daoDescription = String(inputs.daoDescription || "").trim();
|
|
1638
|
+
const imageUrl = String(inputs.imageUrl || "").trim();
|
|
1639
|
+
return [
|
|
1640
|
+
{
|
|
1641
|
+
type: "UpdateInfo",
|
|
1642
|
+
data: {
|
|
1643
|
+
name,
|
|
1644
|
+
description: daoDescription,
|
|
1645
|
+
automatically_add_cw20s: inputs.automaticallyAddCw20s === true || inputs.automaticallyAddCw20s === "true",
|
|
1646
|
+
automatically_add_cw721s: inputs.automaticallyAddCw721s === true || inputs.automaticallyAddCw721s === "true",
|
|
1647
|
+
image_url: imageUrl || null
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
];
|
|
1651
|
+
},
|
|
1652
|
+
defaultTitle: (inputs) => `Update DAO info to \u201C${inputs.name}\u201D`,
|
|
1653
|
+
defaultDescription: () => "Replaces the DAO name, description, image and auto-add settings once the proposal passes.",
|
|
1654
|
+
buildExtraOutput: (inputs) => ({ daoName: String(inputs.name || "") }),
|
|
1655
|
+
extraOutputSchema: [{ path: "daoName", displayName: "DAO Name", type: "string", description: "The DAO display name the proposal sets" }]
|
|
1656
|
+
});
|
|
1657
|
+
|
|
1658
|
+
// src/core/lib/actionRegistry/actions/governance/daoManageSubDaos.ts
|
|
1659
|
+
function normalizeAddresses(value) {
|
|
1660
|
+
return (Array.isArray(value) ? value : []).map((entry) => String(typeof entry === "string" ? entry : entry?.addr || entry?.address || "").trim());
|
|
1661
|
+
}
|
|
1662
|
+
registerGovernanceProposalAction({
|
|
1663
|
+
type: "qi/governance.dao.manage-subdaos",
|
|
1664
|
+
can: "governance.dao/manage-subdaos",
|
|
1665
|
+
buildActions: (inputs) => {
|
|
1666
|
+
const toAdd = normalizeAddresses(inputs.toAdd);
|
|
1667
|
+
const toRemove = normalizeAddresses(inputs.toRemove);
|
|
1668
|
+
if (toAdd.some((addr) => !addr) || toRemove.some((addr) => !addr)) {
|
|
1669
|
+
throw new Error("Every SubDAO entry needs an address");
|
|
1670
|
+
}
|
|
1671
|
+
if (toAdd.length + toRemove.length === 0) {
|
|
1672
|
+
throw new Error("Add or remove at least one SubDAO");
|
|
1673
|
+
}
|
|
1674
|
+
const all = [...toAdd, ...toRemove];
|
|
1675
|
+
if (new Set(all).size !== all.length) throw new Error("Duplicate SubDAO addresses are not allowed");
|
|
1676
|
+
return [
|
|
1677
|
+
{
|
|
1678
|
+
type: "ManageSubDaos",
|
|
1679
|
+
data: {
|
|
1680
|
+
toAdd: toAdd.map((addr) => ({ addr })),
|
|
1681
|
+
toRemove: toRemove.map((address) => ({ address }))
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
];
|
|
1685
|
+
},
|
|
1686
|
+
defaultTitle: (inputs) => {
|
|
1687
|
+
const added = normalizeAddresses(inputs.toAdd).length;
|
|
1688
|
+
const removed = normalizeAddresses(inputs.toRemove).length;
|
|
1689
|
+
return `Add ${added} and remove ${removed} SubDAOs`;
|
|
1690
|
+
},
|
|
1691
|
+
defaultDescription: () => "Updates the set of SubDAOs this DAO recognises once the proposal passes.",
|
|
1692
|
+
buildExtraOutput: (inputs) => ({
|
|
1693
|
+
addedCount: String(normalizeAddresses(inputs.toAdd).length),
|
|
1694
|
+
removedCount: String(normalizeAddresses(inputs.toRemove).length)
|
|
1695
|
+
}),
|
|
1696
|
+
extraOutputSchema: [
|
|
1697
|
+
{ path: "addedCount", displayName: "SubDAOs Added", type: "string", description: "Number of SubDAOs the proposal recognises" },
|
|
1698
|
+
{ path: "removedCount", displayName: "SubDAOs Removed", type: "string", description: "Number of SubDAOs the proposal removes" }
|
|
1699
|
+
]
|
|
1700
|
+
});
|
|
1701
|
+
|
|
1702
|
+
// src/core/lib/actionRegistry/actions/governance/daoManageStorage.ts
|
|
1703
|
+
registerGovernanceProposalAction({
|
|
1704
|
+
type: "qi/governance.dao.manage-storage",
|
|
1705
|
+
can: "governance.dao/manage-storage",
|
|
1706
|
+
buildActions: (inputs) => {
|
|
1707
|
+
const setting = inputs.setting === true || inputs.setting === "true";
|
|
1708
|
+
const key = String(inputs.key || "").trim();
|
|
1709
|
+
if (!key) throw new Error("key is required");
|
|
1710
|
+
const value = String(inputs.value || "").trim();
|
|
1711
|
+
if (setting && !value) throw new Error("value is required when setting a storage item");
|
|
1712
|
+
return [{ type: "ManageStorageItems", data: { setting, key, value: setting ? value : "" } }];
|
|
1713
|
+
},
|
|
1714
|
+
defaultTitle: (inputs) => {
|
|
1715
|
+
const setting = inputs.setting === true || inputs.setting === "true";
|
|
1716
|
+
return setting ? `Set storage item \u201C${inputs.key}\u201D` : `Remove storage item \u201C${inputs.key}\u201D`;
|
|
1717
|
+
},
|
|
1718
|
+
defaultDescription: () => "Updates the DAO's on-chain key/value storage once the proposal passes.",
|
|
1719
|
+
buildExtraOutput: (inputs) => ({
|
|
1720
|
+
storageKey: String(inputs.key || ""),
|
|
1721
|
+
storageAction: inputs.setting === true || inputs.setting === "true" ? "set" : "remove"
|
|
1722
|
+
}),
|
|
1723
|
+
extraOutputSchema: [
|
|
1724
|
+
{ path: "storageKey", displayName: "Storage Key", type: "string", description: "The storage key the proposal targets" },
|
|
1725
|
+
{ path: "storageAction", displayName: "Storage Action", type: "string", description: "set | remove" }
|
|
1726
|
+
]
|
|
1727
|
+
});
|
|
1728
|
+
|
|
1729
|
+
// src/core/lib/actionRegistry/actions/governance/daoAdminExec.ts
|
|
1730
|
+
registerGovernanceProposalAction({
|
|
1731
|
+
type: "qi/governance.dao.admin-exec",
|
|
1732
|
+
can: "governance.dao/admin-exec",
|
|
1733
|
+
buildActions: (inputs) => {
|
|
1734
|
+
const targetCoreAddress = String(inputs.targetCoreAddress || "").trim();
|
|
1735
|
+
if (!targetCoreAddress) throw new Error("targetCoreAddress is required");
|
|
1736
|
+
let msgs = inputs.msgs;
|
|
1737
|
+
if (typeof msgs === "string") {
|
|
1738
|
+
try {
|
|
1739
|
+
msgs = JSON.parse(msgs);
|
|
1740
|
+
} catch {
|
|
1741
|
+
throw new Error("msgs must be valid JSON");
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
if (!Array.isArray(msgs) || msgs.length === 0) {
|
|
1745
|
+
throw new Error("msgs must be a non-empty JSON array of messages");
|
|
1746
|
+
}
|
|
1747
|
+
return [{ type: "DaoAdminExec", data: { coreAddress: targetCoreAddress, msgs } }];
|
|
1748
|
+
},
|
|
1749
|
+
defaultTitle: (inputs) => `Execute admin messages on ${inputs.targetCoreAddress}`,
|
|
1750
|
+
defaultDescription: () => "Executes the listed admin messages on the target SubDAO once the proposal passes.",
|
|
1751
|
+
buildExtraOutput: (inputs) => ({ targetCoreAddress: String(inputs.targetCoreAddress || "") }),
|
|
1752
|
+
extraOutputSchema: [{ path: "targetCoreAddress", displayName: "Target Core Address", type: "string", description: "The SubDAO core address the admin messages execute on" }]
|
|
1753
|
+
});
|
|
1754
|
+
|
|
1755
|
+
// src/core/lib/actionRegistry/actions/governance/daoAcceptToMarketplace.ts
|
|
1756
|
+
registerGovernanceProposalAction({
|
|
1757
|
+
type: "qi/governance.dao.accept-to-marketplace",
|
|
1758
|
+
can: "governance.dao/accept-to-marketplace",
|
|
1759
|
+
buildActions: (inputs) => {
|
|
1760
|
+
const did = String(inputs.did || "").trim();
|
|
1761
|
+
if (!did) throw new Error("did is required");
|
|
1762
|
+
const relayerNodeDid = String(inputs.relayerNodeDid || "").trim();
|
|
1763
|
+
if (!relayerNodeDid) throw new Error("relayerNodeDid is required");
|
|
1764
|
+
const relayerNodeAddress = String(inputs.relayerNodeAddress || "").trim();
|
|
1765
|
+
if (!relayerNodeAddress) throw new Error("relayerNodeAddress is required");
|
|
1766
|
+
return [{ type: "AcceptToMarketplace", data: { did, relayerNodeDid, relayerNodeAddress } }];
|
|
1767
|
+
},
|
|
1768
|
+
defaultTitle: (inputs) => `Accept ${inputs.did} to the marketplace`,
|
|
1769
|
+
defaultDescription: () => "Marks the entity as verified on the marketplace once the proposal passes.",
|
|
1770
|
+
buildExtraOutput: (inputs) => ({ entityDid: String(inputs.did || ""), relayerNodeDid: String(inputs.relayerNodeDid || "") }),
|
|
1771
|
+
extraOutputSchema: [
|
|
1772
|
+
{ path: "entityDid", displayName: "Entity DID", type: "string", description: "The entity marked verified" },
|
|
1773
|
+
{ path: "relayerNodeDid", displayName: "Relayer Node DID", type: "string", description: "The relayer node vouching for the entity" }
|
|
1774
|
+
]
|
|
1775
|
+
});
|
|
1776
|
+
|
|
1777
|
+
// src/core/lib/actionRegistry/actions/governance/daoCreateEntity.ts
|
|
1778
|
+
var DEFAULT_TYPE_URL = "/ixo.entity.v1beta1.MsgCreateEntity";
|
|
1779
|
+
registerGovernanceProposalAction({
|
|
1780
|
+
type: "qi/governance.dao.create-entity",
|
|
1781
|
+
can: "governance.dao/create-entity",
|
|
1782
|
+
buildActions: (inputs) => {
|
|
1783
|
+
const typeUrl = String(inputs.typeUrl || "").trim() || DEFAULT_TYPE_URL;
|
|
1784
|
+
if (!typeUrl.startsWith("/")) throw new Error("typeUrl must be a fully-qualified message type url starting with \u201C/\u201D");
|
|
1785
|
+
let value = inputs.value;
|
|
1786
|
+
if (typeof value === "string") {
|
|
1787
|
+
try {
|
|
1788
|
+
value = JSON.parse(value);
|
|
1789
|
+
} catch {
|
|
1790
|
+
throw new Error("value must be valid JSON");
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1794
|
+
throw new Error("value must be a JSON object with the message fields");
|
|
1795
|
+
}
|
|
1796
|
+
return [{ type: "CreateEntity", data: { typeUrl, value } }];
|
|
1797
|
+
},
|
|
1798
|
+
defaultTitle: () => "Create entity",
|
|
1799
|
+
defaultDescription: (inputs) => `Broadcasts a ${String(inputs.typeUrl || "").trim() || DEFAULT_TYPE_URL} message once the proposal passes.`,
|
|
1800
|
+
buildExtraOutput: (inputs) => ({ typeUrl: String(inputs.typeUrl || "").trim() || DEFAULT_TYPE_URL }),
|
|
1801
|
+
extraOutputSchema: [{ path: "typeUrl", displayName: "Message Type URL", type: "string", description: "The stargate message type the proposal broadcasts" }]
|
|
1802
|
+
});
|
|
1803
|
+
|
|
1804
|
+
// src/core/lib/actionRegistry/actions/governance/nftBurn.ts
|
|
1805
|
+
registerGovernanceProposalAction({
|
|
1806
|
+
type: "qi/governance.nft.burn",
|
|
1807
|
+
can: "governance.nft/burn",
|
|
1808
|
+
buildActions: (inputs) => {
|
|
1809
|
+
const collection = String(inputs.collection || "").trim();
|
|
1810
|
+
if (!collection) throw new Error("collection is required");
|
|
1811
|
+
const tokenId = String(inputs.tokenId || "").trim();
|
|
1812
|
+
if (!tokenId) throw new Error("tokenId is required");
|
|
1813
|
+
return [{ type: "BurnNft", data: { collection, tokenId } }];
|
|
1814
|
+
},
|
|
1815
|
+
defaultTitle: (inputs) => `Burn NFT ${inputs.tokenId} from ${inputs.collection}`,
|
|
1816
|
+
defaultDescription: () => "Permanently burns the NFT from the treasury once the proposal passes.",
|
|
1817
|
+
buildExtraOutput: (inputs) => ({ collection: String(inputs.collection || ""), tokenId: String(inputs.tokenId || "") }),
|
|
1818
|
+
extraOutputSchema: [
|
|
1819
|
+
{ path: "collection", displayName: "Collection", type: "string", description: "The cw721 collection contract the token is burned from" },
|
|
1820
|
+
{ path: "tokenId", displayName: "Token ID", type: "string", description: "The id of the burned token" }
|
|
1821
|
+
]
|
|
1822
|
+
});
|
|
1823
|
+
|
|
1824
|
+
// src/core/lib/actionRegistry/actions/governance/nftTransfer.ts
|
|
1825
|
+
registerGovernanceProposalAction({
|
|
1826
|
+
type: "qi/governance.nft.transfer",
|
|
1827
|
+
can: "governance.nft/transfer",
|
|
1828
|
+
buildActions: (inputs) => {
|
|
1829
|
+
const collection = String(inputs.collection || "").trim();
|
|
1830
|
+
if (!collection) throw new Error("collection is required");
|
|
1831
|
+
const tokenId = String(inputs.tokenId || "").trim();
|
|
1832
|
+
if (!tokenId) throw new Error("tokenId is required");
|
|
1833
|
+
const recipient = String(inputs.recipient || "").trim();
|
|
1834
|
+
if (!recipient) throw new Error("recipient is required");
|
|
1835
|
+
const executeSmartContract = inputs.executeSmartContract === true || inputs.executeSmartContract === "true";
|
|
1836
|
+
let smartContractMsg = "";
|
|
1837
|
+
if (executeSmartContract) {
|
|
1838
|
+
const raw = String(inputs.smartContractMsg || "").trim();
|
|
1839
|
+
if (!raw) throw new Error("smartContractMsg is required when executeSmartContract is enabled");
|
|
1840
|
+
try {
|
|
1841
|
+
smartContractMsg = JSON.parse(raw);
|
|
1842
|
+
} catch {
|
|
1843
|
+
throw new Error("smartContractMsg must be valid JSON");
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
return [{ type: "TransferNft", data: { collection, tokenId, recipient, executeSmartContract, smartContractMsg } }];
|
|
1847
|
+
},
|
|
1848
|
+
defaultTitle: (inputs) => `Transfer NFT ${inputs.tokenId} to ${inputs.recipient}`,
|
|
1849
|
+
defaultDescription: () => "Transfers the NFT from the treasury once the proposal passes.",
|
|
1850
|
+
buildExtraOutput: (inputs) => ({
|
|
1851
|
+
collection: String(inputs.collection || ""),
|
|
1852
|
+
tokenId: String(inputs.tokenId || ""),
|
|
1853
|
+
recipient: String(inputs.recipient || "")
|
|
1854
|
+
}),
|
|
1855
|
+
extraOutputSchema: [
|
|
1856
|
+
{ path: "collection", displayName: "Collection", type: "string", description: "The cw721 collection contract the token is transferred from" },
|
|
1857
|
+
{ path: "tokenId", displayName: "Token ID", type: "string", description: "The id of the transferred token" },
|
|
1858
|
+
{ path: "recipient", displayName: "Recipient", type: "string", description: "Destination address of the transfer" }
|
|
1859
|
+
]
|
|
1860
|
+
});
|
|
1861
|
+
|
|
1862
|
+
// src/core/lib/actionRegistry/actions/governance/nftManageCollections.ts
|
|
1863
|
+
registerGovernanceProposalAction({
|
|
1864
|
+
type: "qi/governance.nft.manage-collections",
|
|
1865
|
+
can: "governance.nft/manage-collections",
|
|
1866
|
+
buildActions: (inputs) => {
|
|
1867
|
+
const address = String(inputs.address || "").trim();
|
|
1868
|
+
if (!address) throw new Error("address is required");
|
|
1869
|
+
const adding = inputs.adding === true || inputs.adding === "true";
|
|
1870
|
+
return [{ type: "ManageCw721", data: { adding, address } }];
|
|
1871
|
+
},
|
|
1872
|
+
defaultTitle: (inputs) => {
|
|
1873
|
+
const adding = inputs.adding === true || inputs.adding === "true";
|
|
1874
|
+
return `${adding ? "Track" : "Untrack"} NFT collection ${inputs.address}`;
|
|
1875
|
+
},
|
|
1876
|
+
defaultDescription: () => "Updates the NFT collections tracked in the treasury once the proposal passes.",
|
|
1877
|
+
buildExtraOutput: (inputs) => ({
|
|
1878
|
+
adding: String(inputs.adding === true || inputs.adding === "true"),
|
|
1879
|
+
address: String(inputs.address || "")
|
|
1880
|
+
}),
|
|
1881
|
+
extraOutputSchema: [
|
|
1882
|
+
{ path: "adding", displayName: "Adding", type: "string", description: "Whether the collection is tracked (true) or untracked (false)" },
|
|
1883
|
+
{ path: "address", displayName: "Collection Address", type: "string", description: "The cw721 collection contract tracked or untracked" }
|
|
1884
|
+
]
|
|
1885
|
+
});
|
|
1886
|
+
|
|
1887
|
+
// src/core/lib/actionRegistry/actions/governance/contractExecute.ts
|
|
1888
|
+
registerGovernanceProposalAction({
|
|
1889
|
+
type: "qi/governance.contract.execute",
|
|
1890
|
+
can: "governance.contract/execute",
|
|
1891
|
+
buildActions: (inputs) => {
|
|
1892
|
+
const address = String(inputs.address || "").trim();
|
|
1893
|
+
if (!address) throw new Error("address is required");
|
|
1894
|
+
const message = String(inputs.message || "").trim();
|
|
1895
|
+
if (!message) throw new Error("message is required");
|
|
1896
|
+
try {
|
|
1897
|
+
JSON.parse(message);
|
|
1898
|
+
} catch {
|
|
1899
|
+
throw new Error("message must be a valid JSON object");
|
|
1900
|
+
}
|
|
1901
|
+
const rawFunds = Array.isArray(inputs.funds) ? inputs.funds : [];
|
|
1902
|
+
const funds = rawFunds.map((fund) => {
|
|
1903
|
+
const denom = String(fund?.denom || "").trim();
|
|
1904
|
+
if (!denom) throw new Error("every attached fund needs a denom");
|
|
1905
|
+
const amount = String(fund?.amount || "").trim();
|
|
1906
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1907
|
+
throw new Error("every attached fund amount must be a positive whole number in base units");
|
|
1908
|
+
}
|
|
1909
|
+
return { denom, amount };
|
|
1910
|
+
});
|
|
1911
|
+
return [{ type: "Execute", data: { address, message, funds } }];
|
|
1912
|
+
},
|
|
1913
|
+
defaultTitle: (inputs) => `Execute a message on contract ${inputs.address}`,
|
|
1914
|
+
defaultDescription: () => "Executes the message on the smart contract as the DAO once the proposal passes.",
|
|
1915
|
+
buildExtraOutput: (inputs) => ({ contractAddress: String(inputs.address || "") }),
|
|
1916
|
+
extraOutputSchema: [{ path: "contractAddress", displayName: "Contract Address", type: "string", description: "The smart contract the message executes on" }]
|
|
1917
|
+
});
|
|
1918
|
+
|
|
1919
|
+
// src/core/lib/actionRegistry/actions/governance/contractInstantiate.ts
|
|
1920
|
+
registerGovernanceProposalAction({
|
|
1921
|
+
type: "qi/governance.contract.instantiate",
|
|
1922
|
+
can: "governance.contract/instantiate",
|
|
1923
|
+
buildActions: (inputs) => {
|
|
1924
|
+
const codeId = Number(inputs.codeId);
|
|
1925
|
+
if (!Number.isInteger(codeId) || codeId <= 0) throw new Error("codeId must be a positive whole number");
|
|
1926
|
+
const label = String(inputs.label || "").trim();
|
|
1927
|
+
if (!label) throw new Error("label is required");
|
|
1928
|
+
const admin = String(inputs.admin || "").trim() || String(inputs.coreAddress || "").trim();
|
|
1929
|
+
if (!admin) throw new Error("admin is required (defaults to the group core address)");
|
|
1930
|
+
const message = String(inputs.message || "").trim();
|
|
1931
|
+
if (!message) throw new Error("message is required");
|
|
1932
|
+
try {
|
|
1933
|
+
JSON.parse(message);
|
|
1934
|
+
} catch {
|
|
1935
|
+
throw new Error("message must be a valid JSON object");
|
|
1936
|
+
}
|
|
1937
|
+
const rawFunds = Array.isArray(inputs.funds) ? inputs.funds : [];
|
|
1938
|
+
const funds = rawFunds.map((fund) => {
|
|
1939
|
+
const denom = String(fund?.denom || "").trim();
|
|
1940
|
+
if (!denom) throw new Error("every attached fund needs a denom");
|
|
1941
|
+
const amount = String(fund?.amount || "").trim();
|
|
1942
|
+
if (!/^\d+$/.test(amount) || BigInt(amount) <= 0n) {
|
|
1943
|
+
throw new Error("every attached fund amount must be a positive whole number in base units");
|
|
1944
|
+
}
|
|
1945
|
+
return { denom, amount };
|
|
1946
|
+
});
|
|
1947
|
+
return [{ type: "Instantiate", data: { admin, codeId, label, message, funds } }];
|
|
1948
|
+
},
|
|
1949
|
+
defaultTitle: (inputs) => `Instantiate code ${inputs.codeId} as \u201C${inputs.label}\u201D`,
|
|
1950
|
+
defaultDescription: () => "Instantiates a new smart contract from the code id once the proposal passes.",
|
|
1951
|
+
buildExtraOutput: (inputs) => ({ codeId: String(inputs.codeId || ""), contractLabel: String(inputs.label || "") }),
|
|
1952
|
+
extraOutputSchema: [
|
|
1953
|
+
{ path: "codeId", displayName: "Code ID", type: "string", description: "The wasm code id instantiated" },
|
|
1954
|
+
{ path: "contractLabel", displayName: "Contract Label", type: "string", description: "The label stored on the new contract" }
|
|
1955
|
+
]
|
|
1956
|
+
});
|
|
1957
|
+
|
|
1958
|
+
// src/core/lib/actionRegistry/actions/governance/contractMigrate.ts
|
|
1959
|
+
registerGovernanceProposalAction({
|
|
1960
|
+
type: "qi/governance.contract.migrate",
|
|
1961
|
+
can: "governance.contract/migrate",
|
|
1962
|
+
buildActions: (inputs) => {
|
|
1963
|
+
const contract = String(inputs.contract || "").trim();
|
|
1964
|
+
if (!contract) throw new Error("contract is required");
|
|
1965
|
+
const codeId = Number(inputs.codeId);
|
|
1966
|
+
if (!Number.isInteger(codeId) || codeId <= 0) throw new Error("codeId must be a positive whole number");
|
|
1967
|
+
const msg = String(inputs.msg || "").trim();
|
|
1968
|
+
if (!msg) throw new Error("msg is required (use {} for contracts whose migrate entry point takes no data)");
|
|
1969
|
+
try {
|
|
1970
|
+
JSON.parse(msg);
|
|
1971
|
+
} catch {
|
|
1972
|
+
throw new Error("msg must be a valid JSON object");
|
|
1973
|
+
}
|
|
1974
|
+
return [{ type: "Migrate", data: { contract, codeId, msg } }];
|
|
1975
|
+
},
|
|
1976
|
+
defaultTitle: (inputs) => `Migrate contract ${inputs.contract} to code ${inputs.codeId}`,
|
|
1977
|
+
defaultDescription: () => "Migrates the smart contract to the new code id once the proposal passes.",
|
|
1978
|
+
buildExtraOutput: (inputs) => ({ contractAddress: String(inputs.contract || ""), codeId: String(inputs.codeId || "") }),
|
|
1979
|
+
extraOutputSchema: [
|
|
1980
|
+
{ path: "contractAddress", displayName: "Contract Address", type: "string", description: "The smart contract migrated" },
|
|
1981
|
+
{ path: "codeId", displayName: "Code ID", type: "string", description: "The wasm code id migrated to" }
|
|
1982
|
+
]
|
|
1983
|
+
});
|
|
1984
|
+
|
|
1985
|
+
// src/core/lib/actionRegistry/actions/governance/contractUpdateAdmin.ts
|
|
1986
|
+
registerGovernanceProposalAction({
|
|
1987
|
+
type: "qi/governance.contract.update-admin",
|
|
1988
|
+
can: "governance.contract/update-admin",
|
|
1989
|
+
buildActions: (inputs) => {
|
|
1990
|
+
const contract = String(inputs.contract || "").trim();
|
|
1991
|
+
if (!contract) throw new Error("contract is required");
|
|
1992
|
+
const newAdmin = String(inputs.newAdmin || "").trim();
|
|
1993
|
+
if (!newAdmin) throw new Error("newAdmin is required");
|
|
1994
|
+
return [{ type: "UpdateAdmin", data: { contract, newAdmin } }];
|
|
1995
|
+
},
|
|
1996
|
+
defaultTitle: (inputs) => `Update admin of ${inputs.contract} to ${inputs.newAdmin}`,
|
|
1997
|
+
defaultDescription: () => "Transfers admin rights over the smart contract once the proposal passes.",
|
|
1998
|
+
buildExtraOutput: (inputs) => ({ contractAddress: String(inputs.contract || ""), newAdmin: String(inputs.newAdmin || "") }),
|
|
1999
|
+
extraOutputSchema: [
|
|
2000
|
+
{ path: "contractAddress", displayName: "Contract Address", type: "string", description: "The smart contract whose admin changed" },
|
|
2001
|
+
{ path: "newAdmin", displayName: "New Admin", type: "string", description: "The address that becomes the contract admin" }
|
|
2002
|
+
]
|
|
2003
|
+
});
|
|
2004
|
+
|
|
2005
|
+
// src/core/lib/actionRegistry/actions/governance/contractManageCw20.ts
|
|
2006
|
+
registerGovernanceProposalAction({
|
|
2007
|
+
type: "qi/governance.contract.manage-cw20",
|
|
2008
|
+
can: "governance.contract/manage-cw20",
|
|
2009
|
+
buildActions: (inputs) => {
|
|
2010
|
+
const rawAdding = inputs.adding;
|
|
2011
|
+
const adding = rawAdding === true || rawAdding === "true" ? true : rawAdding === false || rawAdding === "false" ? false : null;
|
|
2012
|
+
if (adding === null) throw new Error("adding must be true (track the token) or false (untrack it)");
|
|
2013
|
+
const address = String(inputs.address || "").trim();
|
|
2014
|
+
if (!address) throw new Error("address is required");
|
|
2015
|
+
return [{ type: "ManageCw20", data: { adding, address } }];
|
|
2016
|
+
},
|
|
2017
|
+
defaultTitle: (inputs) => {
|
|
2018
|
+
const adding = inputs.adding === true || inputs.adding === "true";
|
|
2019
|
+
return `${adding ? "Track" : "Untrack"} cw20 token ${inputs.address} in the treasury`;
|
|
2020
|
+
},
|
|
2021
|
+
defaultDescription: () => "Updates the treasury\u2019s cw20 token list once the proposal passes.",
|
|
2022
|
+
buildExtraOutput: (inputs) => ({
|
|
2023
|
+
tokenContract: String(inputs.address || ""),
|
|
2024
|
+
adding: inputs.adding === true || inputs.adding === "true" ? "true" : "false"
|
|
2025
|
+
}),
|
|
2026
|
+
extraOutputSchema: [
|
|
2027
|
+
{ path: "tokenContract", displayName: "Token Contract", type: "string", description: "The cw20 token contract tracked or untracked" },
|
|
2028
|
+
{ path: "adding", displayName: "Tracking", type: "string", description: "'true' when the token was tracked, 'false' when untracked" }
|
|
2029
|
+
]
|
|
2030
|
+
});
|
|
2031
|
+
|
|
2032
|
+
// src/core/lib/actionRegistry/actions/governance/validatorActions.ts
|
|
2033
|
+
var VALIDATOR_ACTION_LABELS = {
|
|
2034
|
+
"/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission": "Withdraw validator commission",
|
|
2035
|
+
"/cosmos.staking.v1beta1.MsgCreateValidator": "Create validator",
|
|
2036
|
+
"/cosmos.staking.v1beta1.MsgEditValidator": "Edit validator",
|
|
2037
|
+
"/cosmos.slashing.v1beta1.MsgUnjail": "Unjail validator"
|
|
2038
|
+
};
|
|
2039
|
+
registerGovernanceProposalAction({
|
|
2040
|
+
type: "qi/governance.validator.actions",
|
|
2041
|
+
can: "governance.validator/actions",
|
|
2042
|
+
buildActions: (inputs) => {
|
|
2043
|
+
const validatorActionType = String(inputs.validatorActionType || "").trim();
|
|
2044
|
+
if (!VALIDATOR_ACTION_LABELS[validatorActionType]) {
|
|
2045
|
+
throw new Error("validatorActionType must be one of the supported typeUrls (MsgWithdrawValidatorCommission, MsgCreateValidator, MsgEditValidator, MsgUnjail)");
|
|
2046
|
+
}
|
|
2047
|
+
const isCreate = validatorActionType === "/cosmos.staking.v1beta1.MsgCreateValidator";
|
|
2048
|
+
const isEdit = validatorActionType === "/cosmos.staking.v1beta1.MsgEditValidator";
|
|
2049
|
+
let createMsg = "";
|
|
2050
|
+
if (isCreate) {
|
|
2051
|
+
createMsg = String(inputs.createMsg || "").trim();
|
|
2052
|
+
if (!createMsg) throw new Error("createMsg is required for MsgCreateValidator");
|
|
2053
|
+
try {
|
|
2054
|
+
JSON.parse(createMsg);
|
|
2055
|
+
} catch {
|
|
2056
|
+
throw new Error("createMsg must be valid JSON");
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
let editMsg = "";
|
|
2060
|
+
if (isEdit) {
|
|
2061
|
+
editMsg = String(inputs.editMsg || "").trim();
|
|
2062
|
+
if (!editMsg) throw new Error("editMsg is required for MsgEditValidator");
|
|
2063
|
+
try {
|
|
2064
|
+
JSON.parse(editMsg);
|
|
2065
|
+
} catch {
|
|
2066
|
+
throw new Error("editMsg must be valid JSON");
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
return [{ type: "ValidatorActions", data: { validatorActionType, createMsg, editMsg } }];
|
|
2070
|
+
},
|
|
2071
|
+
// buildActions runs first, so the action type is always a valid option here.
|
|
2072
|
+
defaultTitle: (inputs) => `Validator action: ${VALIDATOR_ACTION_LABELS[String(inputs.validatorActionType)] || inputs.validatorActionType}`,
|
|
2073
|
+
defaultDescription: () => "Executes the validator operation with the POD's validator account once the proposal passes.",
|
|
2074
|
+
buildExtraOutput: (inputs) => ({
|
|
2075
|
+
validatorActionType: String(inputs.validatorActionType || ""),
|
|
2076
|
+
validatorActionLabel: VALIDATOR_ACTION_LABELS[String(inputs.validatorActionType)] || ""
|
|
2077
|
+
}),
|
|
2078
|
+
extraOutputSchema: [
|
|
2079
|
+
{ path: "validatorActionType", displayName: "Validator Action Type", type: "string", description: "The full cosmos typeUrl of the validator operation" },
|
|
2080
|
+
{ path: "validatorActionLabel", displayName: "Validator Action", type: "string", description: "Human-readable name of the validator operation" }
|
|
2081
|
+
]
|
|
2082
|
+
});
|
|
2083
|
+
|
|
2084
|
+
// src/core/lib/actionRegistry/actions/governance/customMessage.ts
|
|
2085
|
+
registerGovernanceProposalAction({
|
|
2086
|
+
type: "qi/governance.custom-message",
|
|
2087
|
+
can: "governance/custom-message",
|
|
2088
|
+
buildActions: (inputs) => {
|
|
2089
|
+
const message = String(inputs.message || "").trim();
|
|
2090
|
+
if (!message) throw new Error("message is required");
|
|
2091
|
+
let parsed;
|
|
2092
|
+
try {
|
|
2093
|
+
parsed = JSON.parse(message);
|
|
2094
|
+
} catch (err) {
|
|
2095
|
+
throw new Error(`message must be valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
2096
|
+
}
|
|
2097
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2098
|
+
throw new Error('message must be a JSON object \u2014 a single cosmos msg like {"bank":\u2026}, {"wasm":\u2026} or {"stargate":\u2026}');
|
|
2099
|
+
}
|
|
2100
|
+
return [{ type: "Custom", data: { message } }];
|
|
2101
|
+
},
|
|
2102
|
+
defaultTitle: () => "Execute custom message",
|
|
2103
|
+
defaultDescription: () => "Executes the raw cosmos message exactly as written once the proposal passes.",
|
|
2104
|
+
buildExtraOutput: (inputs) => ({ message: String(inputs.message || "") }),
|
|
2105
|
+
extraOutputSchema: [{ path: "message", displayName: "Message", type: "string", description: "The raw JSON cosmos message the proposal executes" }]
|
|
2106
|
+
});
|
|
2107
|
+
|
|
1140
2108
|
// src/core/lib/actionRegistry/actions/httpRequest.ts
|
|
1141
2109
|
registerAction({
|
|
1142
2110
|
type: "qi/http.request",
|
|
@@ -1407,6 +2375,60 @@ registerAction({
|
|
|
1407
2375
|
}
|
|
1408
2376
|
});
|
|
1409
2377
|
|
|
2378
|
+
// src/core/lib/actionRegistry/actions/_shared/groupExecution.ts
|
|
2379
|
+
var GROUP_PROPOSAL_READBACK_KIND = "group-proposal";
|
|
2380
|
+
function isGroupExecution(inputs) {
|
|
2381
|
+
return inputs?.actAsGroup === true || inputs?.actAsGroup === "true";
|
|
2382
|
+
}
|
|
2383
|
+
function requireGroupExecutionParams(inputs) {
|
|
2384
|
+
const coreAddress = String(inputs.groupCoreAddress || "").trim();
|
|
2385
|
+
if (!coreAddress) throw new Error("groupCoreAddress is required when acting as a POD");
|
|
2386
|
+
const title = String(inputs.proposalTitle || "").trim();
|
|
2387
|
+
if (!title) throw new Error("proposalTitle is required when acting as a POD \u2014 voters must see what they are approving");
|
|
2388
|
+
const description = String(inputs.proposalDescription || "").trim();
|
|
2389
|
+
if (!description) throw new Error("proposalDescription is required when acting as a POD \u2014 voters must see what they are approving");
|
|
2390
|
+
return { coreAddress, title, description };
|
|
2391
|
+
}
|
|
2392
|
+
async function proposeGroupExecution(ctx, params) {
|
|
2393
|
+
const handlers = ctx.handlers;
|
|
2394
|
+
if (!handlers?.createGroupExecutionProposal) {
|
|
2395
|
+
throw new Error("Group execution is not available: the host does not implement createGroupExecutionProposal");
|
|
2396
|
+
}
|
|
2397
|
+
const { coreAddress, title, description, msgs, expectedOutput, finalize, finalizeParams, completionEvent } = params;
|
|
2398
|
+
const { proposalId, proposalContractAddress } = await handlers.createGroupExecutionProposal({
|
|
2399
|
+
coreAddress,
|
|
2400
|
+
title,
|
|
2401
|
+
description,
|
|
2402
|
+
msgs
|
|
2403
|
+
});
|
|
2404
|
+
if (proposalId === void 0 || proposalId === null || String(proposalId).trim() === "") {
|
|
2405
|
+
throw new Error("POD proposal creation returned no proposal id. Check the handler logs.");
|
|
2406
|
+
}
|
|
2407
|
+
return {
|
|
2408
|
+
output: {
|
|
2409
|
+
...expectedOutput,
|
|
2410
|
+
groupExecution: true,
|
|
2411
|
+
groupCoreAddress: coreAddress,
|
|
2412
|
+
groupProposalId: String(proposalId),
|
|
2413
|
+
groupProposalContractAddress: String(proposalContractAddress || ""),
|
|
2414
|
+
proposalTitle: title,
|
|
2415
|
+
proposalDescription: description
|
|
2416
|
+
},
|
|
2417
|
+
completion: {
|
|
2418
|
+
state: "awaiting_readback",
|
|
2419
|
+
readBack: {
|
|
2420
|
+
kind: GROUP_PROPOSAL_READBACK_KIND,
|
|
2421
|
+
proposalId: String(proposalId),
|
|
2422
|
+
proposalContractAddress: String(proposalContractAddress || ""),
|
|
2423
|
+
coreAddress,
|
|
2424
|
+
expectedOutput,
|
|
2425
|
+
...completionEvent ? { completionEvent } : {},
|
|
2426
|
+
...finalize ? { finalize, finalizeParams: finalizeParams || {} } : {}
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
};
|
|
2430
|
+
}
|
|
2431
|
+
|
|
1410
2432
|
// src/core/lib/actionRegistry/actions/bid/bid.ts
|
|
1411
2433
|
function normalizeBidRole(role) {
|
|
1412
2434
|
const normalized = String(role || "").trim().toLowerCase();
|
|
@@ -1460,6 +2482,29 @@ registerAction({
|
|
|
1460
2482
|
throw new Error("surveyAnswers must be an object");
|
|
1461
2483
|
}
|
|
1462
2484
|
const chainRole = normalizeBidRole(roleInput);
|
|
2485
|
+
if (isGroupExecution(inputs)) {
|
|
2486
|
+
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
2487
|
+
return proposeGroupExecution(ctx, {
|
|
2488
|
+
coreAddress,
|
|
2489
|
+
title,
|
|
2490
|
+
description,
|
|
2491
|
+
msgs: [],
|
|
2492
|
+
expectedOutput: {
|
|
2493
|
+
bidId: "",
|
|
2494
|
+
collectionId,
|
|
2495
|
+
role: roleInput,
|
|
2496
|
+
submitterDid: coreAddress,
|
|
2497
|
+
deedDid
|
|
2498
|
+
},
|
|
2499
|
+
finalize: "bid.submit",
|
|
2500
|
+
finalizeParams: {
|
|
2501
|
+
collectionId,
|
|
2502
|
+
role: chainRole,
|
|
2503
|
+
surveyAnswers,
|
|
2504
|
+
entityDid: deedDid || void 0
|
|
2505
|
+
}
|
|
2506
|
+
});
|
|
2507
|
+
}
|
|
1463
2508
|
const submission = await service.submitBid({
|
|
1464
2509
|
collectionId,
|
|
1465
2510
|
role: chainRole,
|
|
@@ -1552,6 +2597,71 @@ registerAction({
|
|
|
1552
2597
|
if (!role) throw new Error("role is required");
|
|
1553
2598
|
if (!applicantDid) throw new Error("applicantDid is required");
|
|
1554
2599
|
if (!applicantAddress) throw new Error("applicantAddress is required");
|
|
2600
|
+
if (isGroupExecution(inputs)) {
|
|
2601
|
+
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
2602
|
+
const expectedOutput = {
|
|
2603
|
+
bidId,
|
|
2604
|
+
decision,
|
|
2605
|
+
status: decision === "approve" ? "approved" : "rejected",
|
|
2606
|
+
evaluatedByDid: coreAddress,
|
|
2607
|
+
evaluatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2608
|
+
reason: decision === "reject" ? String(inputs.reason || "") : "",
|
|
2609
|
+
collectionId,
|
|
2610
|
+
role,
|
|
2611
|
+
deedDid,
|
|
2612
|
+
applicantDid,
|
|
2613
|
+
applicantAddress
|
|
2614
|
+
};
|
|
2615
|
+
if (decision === "approve") {
|
|
2616
|
+
const adminAddress = String(inputs.adminAddress || "").trim();
|
|
2617
|
+
if (!adminAddress) throw new Error("adminAddress is required when decision is approve");
|
|
2618
|
+
if (!isServiceAgentRole(role) && !isEvaluationAgentRole(role)) {
|
|
2619
|
+
throw new Error("Invalid role for evaluation. Expected service_agent or evaluation_agent");
|
|
2620
|
+
}
|
|
2621
|
+
const groupHandlers = ctx.handlers;
|
|
2622
|
+
if (typeof groupHandlers?.prepareGroupAgentApplicationApproval !== "function") {
|
|
2623
|
+
throw new Error("Acting as a POD is not available: the host does not implement prepareGroupAgentApplicationApproval");
|
|
2624
|
+
}
|
|
2625
|
+
let maxAmounts = inputs.maxAmounts;
|
|
2626
|
+
if (typeof maxAmounts === "string" && maxAmounts.trim()) {
|
|
2627
|
+
try {
|
|
2628
|
+
maxAmounts = JSON.parse(maxAmounts);
|
|
2629
|
+
} catch {
|
|
2630
|
+
throw new Error("maxAmounts must be valid JSON when provided");
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
const prepared = await groupHandlers.prepareGroupAgentApplicationApproval({
|
|
2634
|
+
groupAddress: coreAddress,
|
|
2635
|
+
deedDid,
|
|
2636
|
+
collectionId,
|
|
2637
|
+
adminAddress,
|
|
2638
|
+
role: isServiceAgentRole(role) ? "service_agent" : "evaluation_agent",
|
|
2639
|
+
applicantAddress,
|
|
2640
|
+
agentQuota: isServiceAgentRole(role) ? 30 : 10,
|
|
2641
|
+
maxAmounts: Array.isArray(maxAmounts) ? maxAmounts : void 0
|
|
2642
|
+
});
|
|
2643
|
+
return proposeGroupExecution(ctx, {
|
|
2644
|
+
coreAddress,
|
|
2645
|
+
title,
|
|
2646
|
+
description,
|
|
2647
|
+
msgs: prepared.msgs || [],
|
|
2648
|
+
expectedOutput,
|
|
2649
|
+
finalize: "bid.approve",
|
|
2650
|
+
finalizeParams: { bidId, collectionId, did: applicantDid, entityDid: deedDid }
|
|
2651
|
+
});
|
|
2652
|
+
}
|
|
2653
|
+
const reason = String(inputs.reason || "").trim();
|
|
2654
|
+
if (!reason) throw new Error("reason is required when decision is reject");
|
|
2655
|
+
return proposeGroupExecution(ctx, {
|
|
2656
|
+
coreAddress,
|
|
2657
|
+
title,
|
|
2658
|
+
description,
|
|
2659
|
+
msgs: [],
|
|
2660
|
+
expectedOutput,
|
|
2661
|
+
finalize: "bid.reject",
|
|
2662
|
+
finalizeParams: { bidId, collectionId, did: deedDid, reason, entityDid: deedDid }
|
|
2663
|
+
});
|
|
2664
|
+
}
|
|
1555
2665
|
if (decision === "approve") {
|
|
1556
2666
|
const adminAddress = String(inputs.adminAddress || "").trim();
|
|
1557
2667
|
if (!adminAddress) {
|
|
@@ -1820,6 +2930,40 @@ registerAction({
|
|
|
1820
2930
|
if (!pin) {
|
|
1821
2931
|
throw new Error("PIN is required to submit claim");
|
|
1822
2932
|
}
|
|
2933
|
+
if (isGroupExecution(inputs)) {
|
|
2934
|
+
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
2935
|
+
const handlers = ctx.handlers;
|
|
2936
|
+
if (typeof handlers?.prepareGroupClaimSubmission !== "function") {
|
|
2937
|
+
throw new Error("Acting as a POD is not available: the host does not implement prepareGroupClaimSubmission");
|
|
2938
|
+
}
|
|
2939
|
+
const prepared = await handlers.prepareGroupClaimSubmission({
|
|
2940
|
+
surveyData: surveyAnswers,
|
|
2941
|
+
deedDid,
|
|
2942
|
+
entityDid: deedDid,
|
|
2943
|
+
collectionId,
|
|
2944
|
+
adminAddress,
|
|
2945
|
+
pin,
|
|
2946
|
+
groupAddress: coreAddress
|
|
2947
|
+
});
|
|
2948
|
+
const claimId2 = String(prepared?.claimId || "").trim();
|
|
2949
|
+
if (!claimId2) throw new Error("prepareGroupClaimSubmission returned no claim identifier");
|
|
2950
|
+
return proposeGroupExecution(ctx, {
|
|
2951
|
+
coreAddress,
|
|
2952
|
+
title,
|
|
2953
|
+
description,
|
|
2954
|
+
msgs: prepared.msgs || [],
|
|
2955
|
+
expectedOutput: {
|
|
2956
|
+
claimId: claimId2,
|
|
2957
|
+
transactionHash: "",
|
|
2958
|
+
collectionId,
|
|
2959
|
+
deedDid,
|
|
2960
|
+
submittedByDid: coreAddress,
|
|
2961
|
+
submittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2962
|
+
surveyAnswers
|
|
2963
|
+
},
|
|
2964
|
+
completionEvent: "submitted"
|
|
2965
|
+
});
|
|
2966
|
+
}
|
|
1823
2967
|
const result = await service.submitClaim({
|
|
1824
2968
|
surveyData: surveyAnswers,
|
|
1825
2969
|
deedDid,
|
|
@@ -2524,7 +3668,8 @@ registerAction({
|
|
|
2524
3668
|
if (!deedDid) throw new Error("deedDid is required");
|
|
2525
3669
|
if (!adminAddress) throw new Error("adminAddress is required");
|
|
2526
3670
|
const handlers = ctx.handlers;
|
|
2527
|
-
const
|
|
3671
|
+
const groupMode = isGroupExecution(inputs);
|
|
3672
|
+
const actorAddress = groupMode ? String(inputs.groupCoreAddress || "").trim() : String(ctx.actorDid || service.getCurrentUser?.()?.address || "").trim();
|
|
2528
3673
|
if (!actorAddress) {
|
|
2529
3674
|
throw new Error("Unable to resolve actor address for evaluator authorization");
|
|
2530
3675
|
}
|
|
@@ -2598,6 +3743,54 @@ registerAction({
|
|
|
2598
3743
|
});
|
|
2599
3744
|
verificationProof = String(udid?.url || udid?.cid || "");
|
|
2600
3745
|
}
|
|
3746
|
+
if (groupMode) {
|
|
3747
|
+
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
3748
|
+
const groupHandlers = ctx.handlers;
|
|
3749
|
+
if (typeof groupHandlers?.prepareGroupClaimEvaluation !== "function") {
|
|
3750
|
+
throw new Error("Acting as a POD is not available: the host does not implement prepareGroupClaimEvaluation");
|
|
3751
|
+
}
|
|
3752
|
+
const prepared = await groupHandlers.prepareGroupClaimEvaluation({
|
|
3753
|
+
groupAddress: coreAddress,
|
|
3754
|
+
deedDid,
|
|
3755
|
+
claimId,
|
|
3756
|
+
collectionId,
|
|
3757
|
+
adminAddress,
|
|
3758
|
+
status: toStatus(decision),
|
|
3759
|
+
verificationProof,
|
|
3760
|
+
amount: normalizedCoin
|
|
3761
|
+
});
|
|
3762
|
+
let expectedSurveyAnswers = {};
|
|
3763
|
+
try {
|
|
3764
|
+
const getClaimData = groupHandlers?.getClaimData;
|
|
3765
|
+
if (typeof getClaimData === "function") {
|
|
3766
|
+
const claim = await getClaimData(collectionId, claimId, { entityDid: deedDid });
|
|
3767
|
+
const candidate = claim?.credentialSubject ?? claim?.surveyAnswers ?? claim;
|
|
3768
|
+
if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) {
|
|
3769
|
+
expectedSurveyAnswers = candidate;
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
} catch {
|
|
3773
|
+
}
|
|
3774
|
+
return proposeGroupExecution(ctx, {
|
|
3775
|
+
coreAddress,
|
|
3776
|
+
title,
|
|
3777
|
+
description,
|
|
3778
|
+
msgs: prepared.msgs || [],
|
|
3779
|
+
expectedOutput: {
|
|
3780
|
+
claimId,
|
|
3781
|
+
decision,
|
|
3782
|
+
status: decision === "approve" ? "approved" : "rejected",
|
|
3783
|
+
verificationProof,
|
|
3784
|
+
transactionHash: "",
|
|
3785
|
+
collectionId,
|
|
3786
|
+
deedDid,
|
|
3787
|
+
evaluatedByDid: coreAddress,
|
|
3788
|
+
evaluatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3789
|
+
surveyAnswers: expectedSurveyAnswers
|
|
3790
|
+
},
|
|
3791
|
+
completionEvent: "evaluated"
|
|
3792
|
+
});
|
|
3793
|
+
}
|
|
2601
3794
|
const currentUser = service.getCurrentUser();
|
|
2602
3795
|
const granteeAddress = String(inputs.granteeAddress || currentUser?.address || "").trim();
|
|
2603
3796
|
if (!granteeAddress) {
|
|
@@ -6000,6 +7193,32 @@ registerAction({
|
|
|
6000
7193
|
payments: inputs.payments,
|
|
6001
7194
|
intents: inputs.intents
|
|
6002
7195
|
};
|
|
7196
|
+
if (isGroupExecution(inputs)) {
|
|
7197
|
+
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
7198
|
+
const groupHandlers = ctx.handlers;
|
|
7199
|
+
if (typeof groupHandlers?.prepareGroupCollectionLifecycle !== "function") {
|
|
7200
|
+
throw new Error("Acting as a POD is not available: the host does not implement prepareGroupCollectionLifecycle");
|
|
7201
|
+
}
|
|
7202
|
+
const prepared = await groupHandlers.prepareGroupCollectionLifecycle({
|
|
7203
|
+
groupAddress: coreAddress,
|
|
7204
|
+
operation: "create",
|
|
7205
|
+
params: createParams
|
|
7206
|
+
});
|
|
7207
|
+
return proposeGroupExecution(ctx, {
|
|
7208
|
+
coreAddress,
|
|
7209
|
+
title,
|
|
7210
|
+
description,
|
|
7211
|
+
msgs: prepared.msgs || [],
|
|
7212
|
+
expectedOutput: { collectionId: "", entity, protocol, state: inputs.state, startDate: inputs.startDate, endDate: inputs.endDate, quota, transactionHash: "" },
|
|
7213
|
+
finalize: "collection.create-resolve",
|
|
7214
|
+
finalizeParams: {
|
|
7215
|
+
entityDid: entity,
|
|
7216
|
+
protocolDid: protocol,
|
|
7217
|
+
priorCollectionIds: Array.isArray(prepared.priorCollectionIds) ? prepared.priorCollectionIds : []
|
|
7218
|
+
},
|
|
7219
|
+
completionEvent: COLLECTION_CREATED_EVENT_NAME
|
|
7220
|
+
});
|
|
7221
|
+
}
|
|
6003
7222
|
const result = await service.create(createParams);
|
|
6004
7223
|
const transactionHash2 = String(result?.transactionHash || "").trim();
|
|
6005
7224
|
const collectionId2 = String(result?.collectionId || "").trim();
|
|
@@ -6042,6 +7261,27 @@ registerAction({
|
|
|
6042
7261
|
if (!adminAddress) {
|
|
6043
7262
|
throw new Error(`${writeOp}: could not resolve admin address for collection "${collectionId}" (chain state has no admin). Cannot authorise the update.`);
|
|
6044
7263
|
}
|
|
7264
|
+
if (isGroupExecution(inputs)) {
|
|
7265
|
+
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
7266
|
+
const groupHandlers = ctx.handlers;
|
|
7267
|
+
if (typeof groupHandlers?.prepareGroupCollectionLifecycle !== "function") {
|
|
7268
|
+
throw new Error("Acting as a POD is not available: the host does not implement prepareGroupCollectionLifecycle");
|
|
7269
|
+
}
|
|
7270
|
+
const prepared = await groupHandlers.prepareGroupCollectionLifecycle({
|
|
7271
|
+
groupAddress: coreAddress,
|
|
7272
|
+
operation: writeOp,
|
|
7273
|
+
params: { ...inputs, collectionId, adminAddress }
|
|
7274
|
+
});
|
|
7275
|
+
return proposeGroupExecution(ctx, {
|
|
7276
|
+
coreAddress,
|
|
7277
|
+
title,
|
|
7278
|
+
description,
|
|
7279
|
+
msgs: prepared.msgs || [],
|
|
7280
|
+
expectedOutput: { ...current, collectionId, transactionHash: "" },
|
|
7281
|
+
finalize: "collection.refresh",
|
|
7282
|
+
finalizeParams: { collectionId }
|
|
7283
|
+
});
|
|
7284
|
+
}
|
|
6045
7285
|
let transactionHash = "";
|
|
6046
7286
|
switch (writeOp) {
|
|
6047
7287
|
case "updateState": {
|
|
@@ -6201,6 +7441,53 @@ registerAction({
|
|
|
6201
7441
|
if (!adminAddress) throw new Error(`${operation}: adminAddress (entity admin account) is required`);
|
|
6202
7442
|
const role = normalizeRole(inputs.role);
|
|
6203
7443
|
const deedDid = String(inputs.deedDid || "").trim() || void 0;
|
|
7444
|
+
if (isGroupExecution(inputs) && (operation === "add" || operation === "revoke")) {
|
|
7445
|
+
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
7446
|
+
const groupHandlers = ctx.handlers;
|
|
7447
|
+
if (typeof groupHandlers?.prepareGroupCollectionUserChange !== "function") {
|
|
7448
|
+
throw new Error("Acting as a POD is not available: the host does not implement prepareGroupCollectionUserChange");
|
|
7449
|
+
}
|
|
7450
|
+
if (!deedDid) throw new Error(`${operation}: deedDid is required when acting as a POD`);
|
|
7451
|
+
const grantees = [];
|
|
7452
|
+
if (operation === "add" && inputs.granteeKind === "group-members") {
|
|
7453
|
+
const members = Array.isArray(inputs.members) ? inputs.members.filter((m) => !!String(m?.address || "").trim()) : [];
|
|
7454
|
+
if (members.length === 0) throw new Error("add (group-members): no members resolved to grant to.");
|
|
7455
|
+
grantees.push(...members.map((m) => String(m.address).trim()));
|
|
7456
|
+
} else {
|
|
7457
|
+
const granteeAddress2 = String(inputs.granteeAddress || "").trim();
|
|
7458
|
+
if (!granteeAddress2) throw new Error(`${operation}: granteeAddress is required`);
|
|
7459
|
+
grantees.push(granteeAddress2);
|
|
7460
|
+
}
|
|
7461
|
+
const msgs = [];
|
|
7462
|
+
for (const granteeAddress2 of grantees) {
|
|
7463
|
+
const prepared = await groupHandlers.prepareGroupCollectionUserChange({
|
|
7464
|
+
groupAddress: coreAddress,
|
|
7465
|
+
operation,
|
|
7466
|
+
entityDid: deedDid,
|
|
7467
|
+
collectionId,
|
|
7468
|
+
adminAddress,
|
|
7469
|
+
role,
|
|
7470
|
+
granteeAddress: granteeAddress2,
|
|
7471
|
+
quota: inputs.agentQuota !== void 0 && inputs.agentQuota !== null ? Number(inputs.agentQuota) : void 0,
|
|
7472
|
+
maxAmount: Array.isArray(inputs.maxAmount) ? inputs.maxAmount : void 0
|
|
7473
|
+
});
|
|
7474
|
+
msgs.push(...prepared.msgs || []);
|
|
7475
|
+
}
|
|
7476
|
+
return proposeGroupExecution(ctx, {
|
|
7477
|
+
coreAddress,
|
|
7478
|
+
title,
|
|
7479
|
+
description,
|
|
7480
|
+
msgs,
|
|
7481
|
+
expectedOutput: {
|
|
7482
|
+
transactionHash: "",
|
|
7483
|
+
transactionHashes: [],
|
|
7484
|
+
grantedCount: operation === "add" ? grantees.length : 0,
|
|
7485
|
+
role,
|
|
7486
|
+
collectionId,
|
|
7487
|
+
granteeAddress: grantees.length === 1 ? grantees[0] : void 0
|
|
7488
|
+
}
|
|
7489
|
+
});
|
|
7490
|
+
}
|
|
6204
7491
|
if (operation === "revoke") {
|
|
6205
7492
|
const granteeAddress2 = String(inputs.granteeAddress || "").trim();
|
|
6206
7493
|
if (!granteeAddress2) throw new Error("revoke: granteeAddress is required");
|
|
@@ -9593,11 +10880,23 @@ var VERSION_MANIFEST = {
|
|
|
9593
10880
|
}
|
|
9594
10881
|
};
|
|
9595
10882
|
var LATEST_VERSION = "1.0.0";
|
|
10883
|
+
var tempUcanEnforcementDisabled = true;
|
|
10884
|
+
function isTempUcanEnforcementDisabled() {
|
|
10885
|
+
return tempUcanEnforcementDisabled;
|
|
10886
|
+
}
|
|
10887
|
+
function setTempUcanEnforcementDisabled(disabled) {
|
|
10888
|
+
tempUcanEnforcementDisabled = disabled;
|
|
10889
|
+
}
|
|
9596
10890
|
var MIGRATION_PATH = ["0.3", "1.0.0"];
|
|
9597
10891
|
function getVersionPolicy(version) {
|
|
9598
|
-
const policy = VERSION_MANIFEST[version];
|
|
9599
|
-
if (
|
|
9600
|
-
return
|
|
10892
|
+
const policy = VERSION_MANIFEST[version] ?? VERSION_MANIFEST[LATEST_VERSION];
|
|
10893
|
+
if (tempUcanEnforcementDisabled && policy.ucanRequired) {
|
|
10894
|
+
return {
|
|
10895
|
+
...policy,
|
|
10896
|
+
ucanRequired: false,
|
|
10897
|
+
delegationRootRequired: false,
|
|
10898
|
+
ui: { ...policy.ui, requirePinForExecution: false }
|
|
10899
|
+
};
|
|
9601
10900
|
}
|
|
9602
10901
|
return policy;
|
|
9603
10902
|
}
|
|
@@ -10607,6 +11906,42 @@ import * as Y3 from "yjs";
|
|
|
10607
11906
|
|
|
10608
11907
|
// src/core/lib/flowEngine/readBackReconciler.ts
|
|
10609
11908
|
import * as Y2 from "yjs";
|
|
11909
|
+
function isYDoc(value) {
|
|
11910
|
+
return value instanceof Y2.Doc;
|
|
11911
|
+
}
|
|
11912
|
+
function getYDoc(editorOrYDoc) {
|
|
11913
|
+
if (!editorOrYDoc) return void 0;
|
|
11914
|
+
if (isYDoc(editorOrYDoc)) return editorOrYDoc;
|
|
11915
|
+
return editorOrYDoc._yDoc;
|
|
11916
|
+
}
|
|
11917
|
+
function getEditor(editorOrYDoc) {
|
|
11918
|
+
return editorOrYDoc && !isYDoc(editorOrYDoc) ? editorOrYDoc : void 0;
|
|
11919
|
+
}
|
|
11920
|
+
function getRuntime(editorOrYDoc, runtime) {
|
|
11921
|
+
if (runtime) return runtime;
|
|
11922
|
+
const yDoc = getYDoc(editorOrYDoc);
|
|
11923
|
+
if (yDoc) return createYDocRuntimeManager(yDoc);
|
|
11924
|
+
return createRuntimeStateManager(!isYDoc(editorOrYDoc) ? editorOrYDoc : void 0);
|
|
11925
|
+
}
|
|
11926
|
+
function getReconcileEditor(params, yDoc, editor) {
|
|
11927
|
+
if (editor) return editor;
|
|
11928
|
+
if (!yDoc || !params.document) return void 0;
|
|
11929
|
+
return {
|
|
11930
|
+
_yDoc: yDoc,
|
|
11931
|
+
_yRuntime: yDoc.getMap("runtime"),
|
|
11932
|
+
document: params.document
|
|
11933
|
+
};
|
|
11934
|
+
}
|
|
11935
|
+
function makeRunId(now) {
|
|
11936
|
+
return `readback-${now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
11937
|
+
}
|
|
11938
|
+
function asOutput(value) {
|
|
11939
|
+
return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : {};
|
|
11940
|
+
}
|
|
11941
|
+
function errorRecord(error) {
|
|
11942
|
+
if (!error) return void 0;
|
|
11943
|
+
return typeof error === "string" ? { message: error } : { message: error.message, code: error.code };
|
|
11944
|
+
}
|
|
10610
11945
|
function normalizeActionReadBackMetadata(params) {
|
|
10611
11946
|
const base = params.readBack && typeof params.readBack === "object" && !Array.isArray(params.readBack) ? { ...params.readBack } : {};
|
|
10612
11947
|
const kind = typeof base.kind === "string" && base.kind.trim() ? base.kind.trim() : params.actionType;
|
|
@@ -10631,14 +11966,221 @@ function normalizeActionReadBackMetadata(params) {
|
|
|
10631
11966
|
}
|
|
10632
11967
|
return normalized;
|
|
10633
11968
|
}
|
|
11969
|
+
function writeReconciliationRunRecord(params) {
|
|
11970
|
+
if (!params.yDoc) return void 0;
|
|
11971
|
+
const completedAt = params.now();
|
|
11972
|
+
const runId = makeRunId(params.now);
|
|
11973
|
+
const pendingInvocation = params.readBack.pendingInvocation;
|
|
11974
|
+
const details = {
|
|
11975
|
+
runId,
|
|
11976
|
+
output: params.output,
|
|
11977
|
+
events: params.events,
|
|
11978
|
+
startedAt: params.readBack.requestedAt || new Date(completedAt).toISOString(),
|
|
11979
|
+
completedAt: new Date(completedAt).toISOString(),
|
|
11980
|
+
actorDid: params.actorDid,
|
|
11981
|
+
invocationCid: params.readBack.invocationCid,
|
|
11982
|
+
capabilityId: params.readBack.capabilityId,
|
|
11983
|
+
error: params.error,
|
|
11984
|
+
readBack: params.readBack,
|
|
11985
|
+
reconciled: true
|
|
11986
|
+
};
|
|
11987
|
+
if (pendingInvocation) {
|
|
11988
|
+
details.fromPendingInvocationId = pendingInvocation.id;
|
|
11989
|
+
details.triggeredBy = {
|
|
11990
|
+
sourceBlockId: pendingInvocation.triggeringBlockId,
|
|
11991
|
+
eventName: pendingInvocation.eventName
|
|
11992
|
+
};
|
|
11993
|
+
details.sourceRunId = pendingInvocation.sourceRunId;
|
|
11994
|
+
}
|
|
11995
|
+
appendRunRecord(params.yDoc, params.blockId, details, params.actorDid);
|
|
11996
|
+
if (params.editor && params.events.length > 0) {
|
|
11997
|
+
reconcilePendingInvocations(params.editor);
|
|
11998
|
+
}
|
|
11999
|
+
return runId;
|
|
12000
|
+
}
|
|
12001
|
+
async function reconcileActionReadBack(params) {
|
|
12002
|
+
const now = params.now || Date.now;
|
|
12003
|
+
const yDoc = getYDoc(params.editorOrYDoc);
|
|
12004
|
+
const editor = getEditor(params.editorOrYDoc);
|
|
12005
|
+
const runtime = getRuntime(params.editorOrYDoc, params.runtime);
|
|
12006
|
+
const current = runtime.get(params.blockId);
|
|
12007
|
+
const output = asOutput(current.output);
|
|
12008
|
+
const readBack = current.readBack;
|
|
12009
|
+
if (current.state !== "awaiting_readback" || !readBack?.kind) {
|
|
12010
|
+
return {
|
|
12011
|
+
success: false,
|
|
12012
|
+
blockId: params.blockId,
|
|
12013
|
+
state: current.state === "failed" ? "failed" : "pending",
|
|
12014
|
+
output,
|
|
12015
|
+
events: [],
|
|
12016
|
+
error: `Block "${params.blockId}" is not awaiting read-back`,
|
|
12017
|
+
pendingInvocationRemoved: false,
|
|
12018
|
+
readBack
|
|
12019
|
+
};
|
|
12020
|
+
}
|
|
12021
|
+
const resolver = params.resolver || params.resolvers?.[readBack.kind];
|
|
12022
|
+
if (!resolver) {
|
|
12023
|
+
return {
|
|
12024
|
+
success: false,
|
|
12025
|
+
blockId: params.blockId,
|
|
12026
|
+
state: "pending",
|
|
12027
|
+
output,
|
|
12028
|
+
events: [],
|
|
12029
|
+
error: `No read-back resolver registered for "${readBack.kind}"`,
|
|
12030
|
+
pendingInvocationRemoved: false,
|
|
12031
|
+
readBack
|
|
12032
|
+
};
|
|
12033
|
+
}
|
|
12034
|
+
const resolution = await resolver({
|
|
12035
|
+
blockId: params.blockId,
|
|
12036
|
+
runtime: current,
|
|
12037
|
+
output,
|
|
12038
|
+
readBack
|
|
12039
|
+
});
|
|
12040
|
+
const checkedAt = now();
|
|
12041
|
+
const checkedIso = new Date(checkedAt).toISOString();
|
|
12042
|
+
const nextReadBack = {
|
|
12043
|
+
...readBack,
|
|
12044
|
+
...resolution.readBack || {},
|
|
12045
|
+
status: resolution.state,
|
|
12046
|
+
lastCheckedAt: checkedIso
|
|
12047
|
+
};
|
|
12048
|
+
if (resolution.state === "pending") {
|
|
12049
|
+
runtime.update(params.blockId, {
|
|
12050
|
+
readBack: nextReadBack
|
|
12051
|
+
});
|
|
12052
|
+
return {
|
|
12053
|
+
success: true,
|
|
12054
|
+
blockId: params.blockId,
|
|
12055
|
+
state: "pending",
|
|
12056
|
+
output,
|
|
12057
|
+
events: resolution.events || [],
|
|
12058
|
+
pendingInvocationRemoved: false,
|
|
12059
|
+
readBack: nextReadBack
|
|
12060
|
+
};
|
|
12061
|
+
}
|
|
12062
|
+
const events = resolution.events || [];
|
|
12063
|
+
const finalOutput = {
|
|
12064
|
+
...output,
|
|
12065
|
+
...resolution.output || {}
|
|
12066
|
+
};
|
|
12067
|
+
const actorDid = params.actorDid || readBack.actorDid || current.executedByDid || "system:readback";
|
|
12068
|
+
if (resolution.state === "failed") {
|
|
12069
|
+
const error = errorRecord(resolution.error) || { message: "External read-back failed" };
|
|
12070
|
+
const failedReadBack = {
|
|
12071
|
+
...nextReadBack,
|
|
12072
|
+
terminalAt: checkedIso
|
|
12073
|
+
};
|
|
12074
|
+
runtime.update(params.blockId, {
|
|
12075
|
+
state: "failed",
|
|
12076
|
+
output: finalOutput,
|
|
12077
|
+
error: { ...error, at: checkedAt },
|
|
12078
|
+
readBack: failedReadBack
|
|
12079
|
+
});
|
|
12080
|
+
const runId2 = writeReconciliationRunRecord({
|
|
12081
|
+
yDoc,
|
|
12082
|
+
editor: getReconcileEditor(params, yDoc, editor),
|
|
12083
|
+
blockId: params.blockId,
|
|
12084
|
+
actorDid,
|
|
12085
|
+
output: finalOutput,
|
|
12086
|
+
events,
|
|
12087
|
+
readBack: failedReadBack,
|
|
12088
|
+
error,
|
|
12089
|
+
now
|
|
12090
|
+
});
|
|
12091
|
+
return {
|
|
12092
|
+
success: false,
|
|
12093
|
+
blockId: params.blockId,
|
|
12094
|
+
state: "failed",
|
|
12095
|
+
output: finalOutput,
|
|
12096
|
+
events,
|
|
12097
|
+
error: error.message,
|
|
12098
|
+
runId: runId2,
|
|
12099
|
+
pendingInvocationRemoved: false,
|
|
12100
|
+
readBack: failedReadBack
|
|
12101
|
+
};
|
|
12102
|
+
}
|
|
12103
|
+
const readBackActionType = readBack.actionType || readBack.kind;
|
|
12104
|
+
const actionDef = readBackActionType ? getAction(readBackActionType) : void 0;
|
|
12105
|
+
if (actionDef) {
|
|
12106
|
+
const proofCheck = validateActionProof(actionDef, finalOutput || {});
|
|
12107
|
+
if (!proofCheck.valid) {
|
|
12108
|
+
const message = proofCheck.reason || "Read-back resolved completed without proof of execution.";
|
|
12109
|
+
const proofFailedReadBack = {
|
|
12110
|
+
...nextReadBack,
|
|
12111
|
+
terminalAt: checkedIso
|
|
12112
|
+
};
|
|
12113
|
+
runtime.update(params.blockId, {
|
|
12114
|
+
state: actionDef.sideEffect ? "needs_verification" : "failed",
|
|
12115
|
+
output: finalOutput,
|
|
12116
|
+
error: { message, code: PROOF_MISSING_CODE, at: checkedAt },
|
|
12117
|
+
readBack: proofFailedReadBack
|
|
12118
|
+
});
|
|
12119
|
+
const failedRunId = writeReconciliationRunRecord({
|
|
12120
|
+
yDoc,
|
|
12121
|
+
editor: getReconcileEditor(params, yDoc, editor),
|
|
12122
|
+
blockId: params.blockId,
|
|
12123
|
+
actorDid,
|
|
12124
|
+
output: finalOutput,
|
|
12125
|
+
events,
|
|
12126
|
+
readBack: proofFailedReadBack,
|
|
12127
|
+
error: { message, code: PROOF_MISSING_CODE },
|
|
12128
|
+
now
|
|
12129
|
+
});
|
|
12130
|
+
return {
|
|
12131
|
+
success: false,
|
|
12132
|
+
blockId: params.blockId,
|
|
12133
|
+
state: "failed",
|
|
12134
|
+
output: finalOutput,
|
|
12135
|
+
events,
|
|
12136
|
+
error: message,
|
|
12137
|
+
runId: failedRunId,
|
|
12138
|
+
pendingInvocationRemoved: false,
|
|
12139
|
+
readBack: proofFailedReadBack
|
|
12140
|
+
};
|
|
12141
|
+
}
|
|
12142
|
+
}
|
|
12143
|
+
const completedReadBack = {
|
|
12144
|
+
...nextReadBack,
|
|
12145
|
+
terminalAt: checkedIso
|
|
12146
|
+
};
|
|
12147
|
+
runtime.update(params.blockId, {
|
|
12148
|
+
state: "completed",
|
|
12149
|
+
output: finalOutput,
|
|
12150
|
+
executedAt: checkedAt,
|
|
12151
|
+
error: void 0,
|
|
12152
|
+
readBack: completedReadBack
|
|
12153
|
+
});
|
|
12154
|
+
const runId = writeReconciliationRunRecord({
|
|
12155
|
+
yDoc,
|
|
12156
|
+
editor: getReconcileEditor(params, yDoc, editor),
|
|
12157
|
+
blockId: params.blockId,
|
|
12158
|
+
actorDid,
|
|
12159
|
+
output: finalOutput,
|
|
12160
|
+
events,
|
|
12161
|
+
readBack: completedReadBack,
|
|
12162
|
+
now
|
|
12163
|
+
});
|
|
12164
|
+
const pendingInvocationRemoved = Boolean(yDoc && completedReadBack.pendingInvocation?.id) && removePendingInvocation(yDoc, params.blockId, completedReadBack.pendingInvocation.id);
|
|
12165
|
+
return {
|
|
12166
|
+
success: true,
|
|
12167
|
+
blockId: params.blockId,
|
|
12168
|
+
state: "completed",
|
|
12169
|
+
output: finalOutput,
|
|
12170
|
+
events,
|
|
12171
|
+
runId,
|
|
12172
|
+
pendingInvocationRemoved,
|
|
12173
|
+
readBack: completedReadBack
|
|
12174
|
+
};
|
|
12175
|
+
}
|
|
10634
12176
|
|
|
10635
12177
|
// src/core/lib/flowEngine/actionExecutor.ts
|
|
10636
|
-
function
|
|
12178
|
+
function isYDoc2(value) {
|
|
10637
12179
|
return value instanceof Y3.Doc;
|
|
10638
12180
|
}
|
|
10639
|
-
function
|
|
12181
|
+
function getYDoc2(editorOrYDoc) {
|
|
10640
12182
|
if (!editorOrYDoc) return void 0;
|
|
10641
|
-
if (
|
|
12183
|
+
if (isYDoc2(editorOrYDoc)) return editorOrYDoc;
|
|
10642
12184
|
return editorOrYDoc._yDoc;
|
|
10643
12185
|
}
|
|
10644
12186
|
function parseInputs2(value) {
|
|
@@ -10653,20 +12195,20 @@ function parseInputs2(value) {
|
|
|
10653
12195
|
return {};
|
|
10654
12196
|
}
|
|
10655
12197
|
}
|
|
10656
|
-
function
|
|
12198
|
+
function getRuntime2(editorOrYDoc, runtime) {
|
|
10657
12199
|
if (runtime) return runtime;
|
|
10658
|
-
const yDoc =
|
|
12200
|
+
const yDoc = getYDoc2(editorOrYDoc);
|
|
10659
12201
|
if (yDoc) return createYDocRuntimeManager(yDoc);
|
|
10660
|
-
return createRuntimeStateManager(!
|
|
12202
|
+
return createRuntimeStateManager(!isYDoc2(editorOrYDoc) ? editorOrYDoc : void 0);
|
|
10661
12203
|
}
|
|
10662
|
-
function
|
|
10663
|
-
return editorOrYDoc && !
|
|
12204
|
+
function getEditor2(editorOrYDoc) {
|
|
12205
|
+
return editorOrYDoc && !isYDoc2(editorOrYDoc) ? editorOrYDoc : void 0;
|
|
10664
12206
|
}
|
|
10665
12207
|
function findBlock(params) {
|
|
10666
12208
|
if (params.block) return params.block;
|
|
10667
12209
|
const blockId = params.blockId;
|
|
10668
12210
|
if (!blockId) return void 0;
|
|
10669
|
-
const editor =
|
|
12211
|
+
const editor = getEditor2(params.editorOrYDoc);
|
|
10670
12212
|
return (params.document || editor?.document || []).find((block) => block?.id === blockId);
|
|
10671
12213
|
}
|
|
10672
12214
|
function getFlowMetadata(editor) {
|
|
@@ -10700,8 +12242,8 @@ function getNodeOutput(runtime, nodeId) {
|
|
|
10700
12242
|
}
|
|
10701
12243
|
function buildActionRunInputs(params) {
|
|
10702
12244
|
const blockId = params.blockId || params.block?.id;
|
|
10703
|
-
const yDoc =
|
|
10704
|
-
const runtime =
|
|
12245
|
+
const yDoc = getYDoc2(params.editorOrYDoc);
|
|
12246
|
+
const runtime = getRuntime2(params.editorOrYDoc, params.runtime);
|
|
10705
12247
|
const savedInputs = parseInputs2(params.savedInputs ?? params.block?.props?.inputs);
|
|
10706
12248
|
const pendingInvocation = getPendingInvocation(yDoc, blockId, params.pendingInvocationId);
|
|
10707
12249
|
const triggerContext = pendingInvocation ? {
|
|
@@ -10740,10 +12282,10 @@ function updateRuntimeFailure(runtime, blockId, message, now) {
|
|
|
10740
12282
|
error: { message, at: now() }
|
|
10741
12283
|
});
|
|
10742
12284
|
}
|
|
10743
|
-
function
|
|
12285
|
+
function makeRunId2(now) {
|
|
10744
12286
|
return `run-${now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
10745
12287
|
}
|
|
10746
|
-
function
|
|
12288
|
+
function getReconcileEditor2(params, yDoc, editor) {
|
|
10747
12289
|
if (editor) return editor;
|
|
10748
12290
|
if (!yDoc || !params.document) return void 0;
|
|
10749
12291
|
return {
|
|
@@ -10754,7 +12296,7 @@ function getReconcileEditor(params, yDoc, editor) {
|
|
|
10754
12296
|
}
|
|
10755
12297
|
function persistEvents(params) {
|
|
10756
12298
|
if (!params.yDoc || params.events.length === 0) return void 0;
|
|
10757
|
-
const runId =
|
|
12299
|
+
const runId = makeRunId2(params.now);
|
|
10758
12300
|
const details = {
|
|
10759
12301
|
runId,
|
|
10760
12302
|
output: params.output,
|
|
@@ -10786,9 +12328,9 @@ function cleanupCompletedPendingInvocation(yDoc, blockId, pendingInvocation) {
|
|
|
10786
12328
|
async function executeActionBlock(params) {
|
|
10787
12329
|
const block = findBlock(params);
|
|
10788
12330
|
const blockId = params.blockId || block?.id;
|
|
10789
|
-
const editor =
|
|
10790
|
-
const yDoc =
|
|
10791
|
-
const runtime =
|
|
12331
|
+
const editor = getEditor2(params.editorOrYDoc);
|
|
12332
|
+
const yDoc = getYDoc2(params.editorOrYDoc);
|
|
12333
|
+
const runtime = getRuntime2(params.editorOrYDoc, params.runtime);
|
|
10792
12334
|
const now = params.now || Date.now;
|
|
10793
12335
|
if (!block || !blockId) {
|
|
10794
12336
|
return buildFailureResult({
|
|
@@ -10948,7 +12490,7 @@ async function executeActionBlock(params) {
|
|
|
10948
12490
|
});
|
|
10949
12491
|
const runId = persistEvents({
|
|
10950
12492
|
yDoc,
|
|
10951
|
-
editor:
|
|
12493
|
+
editor: getReconcileEditor2(params, yDoc, editor),
|
|
10952
12494
|
blockId,
|
|
10953
12495
|
actorDid: params.actorDid,
|
|
10954
12496
|
output,
|
|
@@ -12707,7 +14249,7 @@ var BLOCKER_DIAGNOSIS_VERSION = 2;
|
|
|
12707
14249
|
function getBlocks(context) {
|
|
12708
14250
|
return context.blocks || context.editor?.document || [];
|
|
12709
14251
|
}
|
|
12710
|
-
function
|
|
14252
|
+
function getRuntime3(yDoc, nodeId) {
|
|
12711
14253
|
const runtime = yDoc.getMap("runtime");
|
|
12712
14254
|
const value = runtime.get(nodeId);
|
|
12713
14255
|
return value && typeof value === "object" ? value : {};
|
|
@@ -12917,7 +14459,7 @@ function planRalphLoopCommands(context, options = {}) {
|
|
|
12917
14459
|
const nodeId = getBlockId(block);
|
|
12918
14460
|
if (!nodeId) continue;
|
|
12919
14461
|
const pendingInvocationCount = readPendingInvocations(context.yDoc, nodeId).length;
|
|
12920
|
-
const runtime =
|
|
14462
|
+
const runtime = getRuntime3(context.yDoc, nodeId);
|
|
12921
14463
|
const actionType = getBlockActionType(block);
|
|
12922
14464
|
const completionVerification = verifyCompletion({
|
|
12923
14465
|
runtime,
|
|
@@ -13595,6 +15137,8 @@ export {
|
|
|
13595
15137
|
replayFailedListenerRun,
|
|
13596
15138
|
VERSION_MANIFEST,
|
|
13597
15139
|
LATEST_VERSION,
|
|
15140
|
+
isTempUcanEnforcementDisabled,
|
|
15141
|
+
setTempUcanEnforcementDisabled,
|
|
13598
15142
|
getVersionPolicy,
|
|
13599
15143
|
isVersionAtLeast,
|
|
13600
15144
|
reconcilePendingInvocations,
|
|
@@ -13609,6 +15153,7 @@ export {
|
|
|
13609
15153
|
executeNode,
|
|
13610
15154
|
PROOF_MISSING_CODE,
|
|
13611
15155
|
validateActionProof,
|
|
15156
|
+
reconcileActionReadBack,
|
|
13612
15157
|
buildActionRunInputs,
|
|
13613
15158
|
executeActionBlock,
|
|
13614
15159
|
verifyCompletion,
|
|
@@ -13669,4 +15214,4 @@ export {
|
|
|
13669
15214
|
executeQueuedFlowAgentCoreCommands,
|
|
13670
15215
|
FlowAgentService
|
|
13671
15216
|
};
|
|
13672
|
-
//# sourceMappingURL=chunk-
|
|
15217
|
+
//# sourceMappingURL=chunk-EULL3QTC.js.map
|