@capxul/sdk-react 4.20.0-beta.35 → 4.20.0-beta.36
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/index.d.mts +2 -2
- package/dist/index.mjs +19 -37
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -360,7 +360,7 @@ type SentPayment = {
|
|
|
360
360
|
* Refusal CODES, never sentences (#1447 ruling 8). The app maps each code to
|
|
361
361
|
* the words it already prints; no English refusal string ships from here.
|
|
362
362
|
*/
|
|
363
|
-
type CapxulSendMoneyBlockedReason = "signer-not-ready" | "amount-invalid" | "recipient-unresolved" | "no-source" | "no-asset"
|
|
363
|
+
type CapxulSendMoneyBlockedReason = "signer-not-ready" | "amount-invalid" | "recipient-unresolved" | "no-source" | "no-asset";
|
|
364
364
|
/**
|
|
365
365
|
* One Budget the member can spend from — the id the payment carries, and
|
|
366
366
|
* nothing else.
|
|
@@ -999,7 +999,7 @@ interface PayrollRecipientOption {
|
|
|
999
999
|
* false fact in the fixed order below, so the same composer state always
|
|
1000
1000
|
* yields the same code.
|
|
1001
1001
|
*/
|
|
1002
|
-
type CapxulPayrollRunBlockedReason = "signer-not-ready" | "no-source" | "ambiguous-source" | "no-asset" | "no-recipients" | "amount-invalid" | "insufficient-funds"
|
|
1002
|
+
type CapxulPayrollRunBlockedReason = "signer-not-ready" | "no-source" | "ambiguous-source" | "no-asset" | "no-recipients" | "amount-invalid" | "insufficient-funds";
|
|
1003
1003
|
interface PayrollRunGroupOption {
|
|
1004
1004
|
readonly id: PayrollGroupId;
|
|
1005
1005
|
readonly label: string;
|
package/dist/index.mjs
CHANGED
|
@@ -1418,26 +1418,6 @@ function useCapxulOrganizationPayBatch(orgId) {
|
|
|
1418
1418
|
});
|
|
1419
1419
|
}
|
|
1420
1420
|
//#endregion
|
|
1421
|
-
//#region src/payments/write-names-asset.ts
|
|
1422
|
-
/**
|
|
1423
|
-
* Identity law: "A payment names an asset or inherits it from an authorized
|
|
1424
|
-
* fact. Missing asset refuses." The rule was recorded in the retired
|
|
1425
|
-
* treasury-cut handoff (removed from the current tree by the exact-asset
|
|
1426
|
-
* contraction; its record survives in Git history).
|
|
1427
|
-
*
|
|
1428
|
-
* A Capxul payment writer takes `PaymentMoney` — a peg currency, a value and
|
|
1429
|
-
* `decimals` — and settles one fixed legacy token. No `AssetId` crosses that
|
|
1430
|
-
* seam, so a payment composed from a named position cannot name the asset it
|
|
1431
|
-
* moves: a position selected as USDT authorizes a different token.
|
|
1432
|
-
*
|
|
1433
|
-
* `false` until the writer takes the command's asset. The Send and Payroll
|
|
1434
|
-
* composers read this to refuse a submission rather than authorize a token the
|
|
1435
|
-
* person did not pick.
|
|
1436
|
-
*/
|
|
1437
|
-
function writeNamesAsset() {
|
|
1438
|
-
return false;
|
|
1439
|
-
}
|
|
1440
|
-
//#endregion
|
|
1441
1421
|
//#region src/platform/signer-status.ts
|
|
1442
1422
|
const NO_SUBSCRIPTION = () => () => {};
|
|
1443
1423
|
function useSignerStatus(client) {
|
|
@@ -1592,9 +1572,6 @@ function useSendMoney(input) {
|
|
|
1592
1572
|
const client = useCapxulClientOrNull();
|
|
1593
1573
|
const signerStatus = useSignerStatus(client);
|
|
1594
1574
|
const orgId = actor.kind === "organization" ? actor.orgId : void 0;
|
|
1595
|
-
const meReading = useOrgMeReading(orgId);
|
|
1596
|
-
const sourceOptions = useMemo(() => meReading.kind === "ready" ? meReading.me.budgets.map((budget) => ({ id: budget.id })) : [], [meReading]);
|
|
1597
|
-
const [selectedSource, selectSource] = useSelectedOption(sourceOptions);
|
|
1598
1575
|
const balance = useCapxulAccountBalance({ enabled: actor.kind === "personal" });
|
|
1599
1576
|
const treasury = useCapxulOrgTreasury(orgId, { enabled: actor.kind === "organization" });
|
|
1600
1577
|
const accountQuery = actor.kind === "personal" ? balance : treasury;
|
|
@@ -1603,6 +1580,9 @@ function useSendMoney(input) {
|
|
|
1603
1580
|
const assetOptions = useMemo(() => assetSelections.map((selection) => selection.option), [assetSelections]);
|
|
1604
1581
|
const [selectedAssetOption, selectAsset] = useSelectedOption(assetOptions);
|
|
1605
1582
|
const selectedAssetMoney = useMemo(() => assetSelections.find((selection) => selection.option.id === selectedAssetOption?.id)?.money ?? null, [assetSelections, selectedAssetOption]);
|
|
1583
|
+
const meReading = useOrgMeReading(orgId);
|
|
1584
|
+
const sourceOptions = useMemo(() => meReading.kind === "ready" ? meReading.me.budgets.filter((budget) => selectedAssetOption === null || budget.asset.assetId === selectedAssetOption.id).map((budget) => ({ id: budget.id })) : [], [meReading, selectedAssetOption]);
|
|
1585
|
+
const [selectedSource, selectSource] = useSelectedOption(sourceOptions);
|
|
1606
1586
|
const [amountText, setAmountText] = useState("");
|
|
1607
1587
|
const parsed = useMemo(() => selectedAssetMoney === null || amountText.trim() === "" ? null : parseAssetAmount(amountText, requireAsset(selectedAssetMoney.asset)), [amountText, selectedAssetMoney]);
|
|
1608
1588
|
const parsedMoney = parsed !== null && !isMoneyParseError(parsed) ? parsed : null;
|
|
@@ -1616,7 +1596,7 @@ function useSendMoney(input) {
|
|
|
1616
1596
|
const personalPay = useCapxulPay();
|
|
1617
1597
|
const organizationPay = useCapxulOrganizationPay(orgId);
|
|
1618
1598
|
const pay = actor.kind === "personal" ? personalPay : organizationPay;
|
|
1619
|
-
const blockedReason = signerStatus !== "ready" ? "signer-not-ready" : actor.kind === "organization" && selectedSource === null ? "no-source" : selectedAssetOption === null ? "no-asset" : parsedMoney === null ? "amount-invalid" : resolvedReference === null ? "recipient-unresolved" :
|
|
1599
|
+
const blockedReason = signerStatus !== "ready" ? "signer-not-ready" : actor.kind === "organization" && selectedSource === null ? "no-source" : selectedAssetOption === null ? "no-asset" : parsedMoney === null ? "amount-invalid" : resolvedReference === null ? "recipient-unresolved" : null;
|
|
1620
1600
|
const submitGate = useRef(false);
|
|
1621
1601
|
const submit = useCallback(() => {
|
|
1622
1602
|
if (blockedReason !== null || submitGate.current) return;
|
|
@@ -3362,8 +3342,8 @@ function freshRunDraft(input) {
|
|
|
3362
3342
|
}
|
|
3363
3343
|
};
|
|
3364
3344
|
}
|
|
3365
|
-
function hasRequiredCompensation(frozen,
|
|
3366
|
-
return frozen ||
|
|
3345
|
+
function hasRequiredCompensation(frozen, selected, terms) {
|
|
3346
|
+
return frozen || selected.every((recipientId) => terms.has(recipientId));
|
|
3367
3347
|
}
|
|
3368
3348
|
/**
|
|
3369
3349
|
* WHICH run the composer is composing, by MEANING rather than by object shape.
|
|
@@ -3406,10 +3386,14 @@ function remainingBalanceDisplay(available, total, asset) {
|
|
|
3406
3386
|
}));
|
|
3407
3387
|
return remaining < 0n ? `-${formatted}` : formatted;
|
|
3408
3388
|
}
|
|
3409
|
-
/**
|
|
3389
|
+
/**
|
|
3390
|
+
* Persisted replay keeps its authorized Budget and asset; a prior debit cannot
|
|
3391
|
+
* block its own recovery. A restored run names its Budget, so it counts only
|
|
3392
|
+
* whether that Budget is still offered, never how many others are.
|
|
3393
|
+
*/
|
|
3410
3394
|
function runAuthorityFacts(draft, budgets, asset, money, funds) {
|
|
3411
3395
|
return {
|
|
3412
|
-
budgetCount: draft
|
|
3396
|
+
budgetCount: draft === null ? budgets.length : budgets.filter((budget) => budget.id === draft.input.permissionId).length,
|
|
3413
3397
|
hasAsset: asset !== null && (draft === null || draft.asset.id === asset.id && draft.input.asset === money?.asset),
|
|
3414
3398
|
funds: draft?.input.requestKey === void 0 ? funds : "available"
|
|
3415
3399
|
};
|
|
@@ -3426,8 +3410,7 @@ function firstFalseFact(facts) {
|
|
|
3426
3410
|
if (!facts.hasAsset) return "no-asset";
|
|
3427
3411
|
if (facts.recipientCount === 0) return "no-recipients";
|
|
3428
3412
|
if (!facts.amountsParse) return "amount-invalid";
|
|
3429
|
-
|
|
3430
|
-
return facts.writeNamesAsset ? null : "asset-unnamed";
|
|
3413
|
+
return facts.funds === "insufficient" ? "insufficient-funds" : null;
|
|
3431
3414
|
}
|
|
3432
3415
|
//#endregion
|
|
3433
3416
|
//#region src/payroll/use-run-amounts.ts
|
|
@@ -3510,14 +3493,15 @@ function useRunAmounts(input) {
|
|
|
3510
3493
|
* share one account id, and a symbol is display only (ADR-0028 R3). The run
|
|
3511
3494
|
* writer receives the selected asset explicitly.
|
|
3512
3495
|
*/
|
|
3513
|
-
function useRunAsset(account, canSelect) {
|
|
3496
|
+
function useRunAsset(account, canSelect, restoredAssetId) {
|
|
3514
3497
|
const assetSelections = useMemo(() => assetSelectionsFromAccount(account), [account]);
|
|
3515
3498
|
const assetOptions = useMemo(() => assetSelections.map((selection) => selection.option), [assetSelections]);
|
|
3516
3499
|
const [selectedAssetId, setSelectedAssetId] = useState(null);
|
|
3517
3500
|
useEffect(() => {
|
|
3518
3501
|
if (!assetOptions.some((option) => option.id === selectedAssetId)) setSelectedAssetId(assetOptions[0]?.id ?? null);
|
|
3519
3502
|
}, [assetOptions, selectedAssetId]);
|
|
3520
|
-
const
|
|
3503
|
+
const effectiveAssetId = restoredAssetId ?? selectedAssetId;
|
|
3504
|
+
const selectedAsset = assetOptions.find((option) => option.id === effectiveAssetId) ?? null;
|
|
3521
3505
|
return {
|
|
3522
3506
|
assetOptions,
|
|
3523
3507
|
selectedAsset,
|
|
@@ -3609,7 +3593,7 @@ function usePayrollRun(input) {
|
|
|
3609
3593
|
draftError
|
|
3610
3594
|
]);
|
|
3611
3595
|
const canSelectAsset = useCallback(() => !submitGate.current && !frozen, [frozen]);
|
|
3612
|
-
const { assetOptions, selectedAsset, selectAsset, assetMoney } = useRunAsset(treasury.data ?? null, canSelectAsset);
|
|
3596
|
+
const { assetOptions, selectedAsset, selectAsset, assetMoney } = useRunAsset(treasury.data ?? null, canSelectAsset, draft?.input.asset ?? null);
|
|
3613
3597
|
const { named, payableRefs, compensationTerms } = useRunRecipients({
|
|
3614
3598
|
options: roster.options,
|
|
3615
3599
|
refs: roster.refs,
|
|
@@ -3624,14 +3608,12 @@ function usePayrollRun(input) {
|
|
|
3624
3608
|
names: named,
|
|
3625
3609
|
change
|
|
3626
3610
|
});
|
|
3627
|
-
const budgets = me.data?.budgets ?? [];
|
|
3628
|
-
const writerNamesSelectedAsset = writeNamesAsset();
|
|
3611
|
+
const budgets = (me.data?.budgets ?? []).filter((budget) => selectedAsset === null || budget.asset.assetId === selectedAsset.id);
|
|
3629
3612
|
const blockedReason = firstFalseFact({
|
|
3630
3613
|
signerReady: signerStatus === "ready",
|
|
3631
3614
|
...runAuthorityFacts(draft, budgets, selectedAsset, assetMoney, funds),
|
|
3632
3615
|
recipientCount: payableRefs === null ? 0 : selected.length,
|
|
3633
|
-
amountsParse: total !== null && hasRequiredCompensation(frozen,
|
|
3634
|
-
writeNamesAsset: writerNamesSelectedAsset
|
|
3616
|
+
amountsParse: total !== null && hasRequiredCompensation(frozen, selected, compensationTerms)
|
|
3635
3617
|
});
|
|
3636
3618
|
const authorize = useAuthorizeRun({
|
|
3637
3619
|
client,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capxul/sdk-react",
|
|
3
|
-
"version": "4.20.0-beta.
|
|
3
|
+
"version": "4.20.0-beta.36",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/Xelmar-tech/infrastructure.git",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@capxul/sdk": "4.20.0-beta.
|
|
59
|
+
"@capxul/sdk": "4.20.0-beta.36"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@tanstack/react-query": "^5.66.9",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"vite": "npm:@voidzero-dev/vite-plus-core@1.0.0",
|
|
76
76
|
"vite-plus": "1.0.0",
|
|
77
77
|
"vitest": "5.0.1",
|
|
78
|
-
"@capxul/protocol": "0.2.0-beta.
|
|
78
|
+
"@capxul/protocol": "0.2.0-beta.7",
|
|
79
79
|
"@capxul/typescript-config": "0.0.0"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|