@ixo/editor 5.20.0-experimental.5 → 5.20.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.
@@ -31897,6 +31897,7 @@ function emptyPaymentRowFields() {
31897
31897
  accountName: "",
31898
31898
  accountNumber: "",
31899
31899
  accountType: "",
31900
+ bankName: "",
31900
31901
  networkId: "",
31901
31902
  country: "",
31902
31903
  bvn: "",
@@ -31920,7 +31921,9 @@ function emptyPaymentSender() {
31920
31921
  address: "",
31921
31922
  dob: "",
31922
31923
  idType: "",
31923
- idNumber: ""
31924
+ idNumber: "",
31925
+ additionalIdType: "",
31926
+ additionalIdNumber: ""
31924
31927
  };
31925
31928
  }
31926
31929
  function emptyPaymentFieldTemplate() {
@@ -31928,6 +31931,7 @@ function emptyPaymentFieldTemplate() {
31928
31931
  accountName: "",
31929
31932
  accountNumber: "",
31930
31933
  accountType: "",
31934
+ bankName: "",
31931
31935
  networkId: "",
31932
31936
  country: "",
31933
31937
  bvn: "",
@@ -31939,14 +31943,7 @@ function emptyPaymentFieldTemplate() {
31939
31943
  outcomeCurrency: ""
31940
31944
  };
31941
31945
  }
31942
- var DEFAULT_REQUIRED_FIELDS = [
31943
- "accountName",
31944
- "accountNumber",
31945
- "accountType",
31946
- "country",
31947
- "amount",
31948
- "currency"
31949
- ];
31946
+ var DEFAULT_REQUIRED_FIELDS = ["accountName", "accountNumber", "accountType", "bankName", "country", "amount", "currency", "recipientDid"];
31950
31947
  function emptyPaymentInputs() {
31951
31948
  return {
31952
31949
  collectionId: "",
@@ -31989,7 +31986,9 @@ function parsePaymentInputs(json) {
31989
31986
  address: asString(parsed.sender?.address),
31990
31987
  dob: asString(parsed.sender?.dob),
31991
31988
  idType: asString(parsed.sender?.idType),
31992
- idNumber: asString(parsed.sender?.idNumber)
31989
+ idNumber: asString(parsed.sender?.idNumber),
31990
+ additionalIdType: asString(parsed.sender?.additionalIdType),
31991
+ additionalIdNumber: asString(parsed.sender?.additionalIdNumber)
31993
31992
  },
31994
31993
  defaultReason: asString(parsed.defaultReason, "other"),
31995
31994
  customerType: asString(parsed.customerType, "retail"),
@@ -31997,6 +31996,7 @@ function parsePaymentInputs(json) {
31997
31996
  accountName: asString(parsed.fieldTemplate?.accountName),
31998
31997
  accountNumber: asString(parsed.fieldTemplate?.accountNumber),
31999
31998
  accountType: asString(parsed.fieldTemplate?.accountType),
31999
+ bankName: asString(parsed.fieldTemplate?.bankName),
32000
32000
  networkId: asString(parsed.fieldTemplate?.networkId),
32001
32001
  country: asString(parsed.fieldTemplate?.country),
32002
32002
  bvn: asString(parsed.fieldTemplate?.bvn),
@@ -32026,21 +32026,19 @@ function parsePaymentInputs(json) {
32026
32026
  // intent. If a flow needs the old behaviour, surface it on the row UI
32027
32027
  // (e.g. ban empty networkId at propose time inside the action def
32028
32028
  // itself, not via requiredFields). For now no flow needs that.
32029
- requiredFields: Array.isArray(parsed.requiredFields) ? parsed.requiredFields.filter(
32030
- (f) => typeof f === "string" && // Drop the oracle-resolved fields from any persisted list.
32031
- f !== "networkId" && f !== "channelId" && [
32032
- "accountName",
32033
- "accountNumber",
32034
- "accountType",
32035
- "country",
32036
- "bvn",
32037
- "amount",
32038
- "currency",
32039
- "reason",
32040
- "recipientDid",
32041
- "outcomeCurrency"
32042
- ].includes(f)
32043
- ) : [...DEFAULT_REQUIRED_FIELDS]
32029
+ requiredFields: (() => {
32030
+ if (!Array.isArray(parsed.requiredFields)) {
32031
+ return [...DEFAULT_REQUIRED_FIELDS];
32032
+ }
32033
+ const cleaned = parsed.requiredFields.filter(
32034
+ (f) => typeof f === "string" && // Drop the oracle-resolved fields from any persisted list.
32035
+ f !== "networkId" && f !== "channelId" && ["accountName", "accountNumber", "accountType", "bankName", "country", "bvn", "amount", "currency", "reason", "recipientDid", "outcomeCurrency"].includes(f)
32036
+ );
32037
+ if (!cleaned.includes("recipientDid")) {
32038
+ cleaned.push("recipientDid");
32039
+ }
32040
+ return cleaned;
32041
+ })()
32044
32042
  };
32045
32043
  }
32046
32044
  function serializePaymentInputs(inputs) {
@@ -32073,6 +32071,7 @@ function parsePaymentRows(raw) {
32073
32071
  accountName: asString(entry.fields?.accountName),
32074
32072
  accountNumber: asString(entry.fields?.accountNumber),
32075
32073
  accountType: asString(entry.fields?.accountType),
32074
+ bankName: asString(entry.fields?.bankName),
32076
32075
  networkId: asString(entry.fields?.networkId),
32077
32076
  country: asString(entry.fields?.country),
32078
32077
  bvn: asString(entry.fields?.bvn),
@@ -32096,9 +32095,7 @@ function parsePaymentRows(raw) {
32096
32095
  }).filter((r) => r !== null);
32097
32096
  }
32098
32097
  function missingRequiredFields(row, required) {
32099
- return required.filter(
32100
- (key) => !row.fields[key] || String(row.fields[key]).trim() === ""
32101
- );
32098
+ return required.filter((key) => !row.fields[key] || String(row.fields[key]).trim() === "");
32102
32099
  }
32103
32100
  function checkCurrencyCompatibility(row) {
32104
32101
  const outcomeRaw = row.fields.outcomeCurrency?.trim() ?? "";
@@ -32129,6 +32126,10 @@ var FIELD_LABEL = {
32129
32126
  label: "Account type",
32130
32127
  hint: '"bank" or "momo" \u2014 usually fixed per flow, not from claim'
32131
32128
  },
32129
+ bankName: {
32130
+ label: "Recipient bank name (required)",
32131
+ hint: "e.g. {{claim.surveyAnswers.umuzi:bankName}} \u2014 must match a YellowCard network name (Capitec Bank, FNB, MTN, \u2026). The oracle resolves this to a networkId at propose time. WRONG-bank routes funds to the wrong clearing system, so this MUST be accurate."
32132
+ },
32132
32133
  networkId: {
32133
32134
  label: "Network / bank UUID (optional)",
32134
32135
  hint: "Leave empty \u2014 the oracle resolves the network UUID at propose time via the worker's `/channels` discovery. Only set this if you want to pin a specific bank."
@@ -32158,8 +32159,8 @@ var FIELD_LABEL = {
32158
32159
  hint: "Falls back to block-level Default Reason when empty"
32159
32160
  },
32160
32161
  recipientDid: {
32161
- label: "Recipient DID (optional)",
32162
- hint: "e.g. {{claim.agentDid}} \u2014 falls back to invoker DID server-side"
32162
+ label: "Recipient DID (required)",
32163
+ hint: "e.g. {{claim.agentDid}} \u2014 DID of the person being paid out to. Worker uses this as YC customerUID for per-user KYC tracking. NEVER falls back to invoker \u2014 that would attribute the payout to the operator, not the actual recipient."
32163
32164
  },
32164
32165
  outcomeCurrency: {
32165
32166
  label: "Outcome currency",
@@ -32170,6 +32171,7 @@ var REQUIRED_FIELD_OPTIONS = [
32170
32171
  { value: "accountName", label: "Recipient account name" },
32171
32172
  { value: "accountNumber", label: "Recipient account number" },
32172
32173
  { value: "accountType", label: "Account type" },
32174
+ { value: "bankName", label: "Bank name" },
32173
32175
  { value: "country", label: "Country" },
32174
32176
  { value: "bvn", label: "BVN" },
32175
32177
  { value: "amount", label: "Amount" },
@@ -32178,12 +32180,7 @@ var REQUIRED_FIELD_OPTIONS = [
32178
32180
  { value: "recipientDid", label: "Recipient DID" },
32179
32181
  { value: "outcomeCurrency", label: "Outcome currency" }
32180
32182
  ];
32181
- var PaymentConfig = ({
32182
- inputs,
32183
- onInputsChange,
32184
- editor,
32185
- blockId
32186
- }) => {
32183
+ var PaymentConfig = ({ inputs, onInputsChange, editor, blockId }) => {
32187
32184
  const [local, setLocal] = useState140(() => parsePaymentInputs(inputs));
32188
32185
  useEffect112(() => {
32189
32186
  setLocal(parsePaymentInputs(inputs));
@@ -32203,16 +32200,7 @@ var PaymentConfig = ({
32203
32200
  [local.fieldTemplate, update]
32204
32201
  );
32205
32202
  const editorDocument = editor?.document || [];
32206
- return /* @__PURE__ */ React288.createElement(Stack205, { gap: "lg" }, /* @__PURE__ */ React288.createElement(Alert61, { color: "blue", variant: "light" }, /* @__PURE__ */ React288.createElement(Text180, { size: "xs" }, /* @__PURE__ */ React288.createElement("strong", null, "Sender details are NOT set here."), " Each operator running this flow fills in their own org name + KYC at runtime, in the payment block's side panel. Templates ship clean \u2014 no operator PII. The worker URL below is a default; operators can override it per-flow.")), /* @__PURE__ */ React288.createElement(Stack205, { gap: "xs" }, /* @__PURE__ */ React288.createElement(Text180, { size: "sm", fw: 600 }, "Claim source"), /* @__PURE__ */ React288.createElement(Text180, { size: "xs", c: "dimmed" }, "The Claims tab in the flow-mode UI pulls approved claims from this collection so the payer can pick which ones to pay out. Use the same collection ID that the claim and evaluation blocks point at."), /* @__PURE__ */ React288.createElement(
32207
- TextInput9,
32208
- {
32209
- size: "xs",
32210
- label: "Claim collection ID",
32211
- placeholder: "e.g. 781",
32212
- value: local.collectionId,
32213
- onChange: (e) => update({ collectionId: e.currentTarget.value })
32214
- }
32215
- )), /* @__PURE__ */ React288.createElement(Divider25, { variant: "dashed" }), /* @__PURE__ */ React288.createElement(Stack205, { gap: "xs" }, /* @__PURE__ */ React288.createElement(Text180, { size: "sm", fw: 600 }, "Default YellowCard worker URL"), /* @__PURE__ */ React288.createElement(Text180, { size: "xs", c: "dimmed" }, "The template-author's default. Used when an operator hasn't set a flow-level override. Operators running self-hosted workers paste their own URL in the flow-mode Payout setup panel \u2014 that override wins. Leave empty to force every operator to choose their own."), /* @__PURE__ */ React288.createElement(
32203
+ return /* @__PURE__ */ React288.createElement(Stack205, { gap: "lg" }, /* @__PURE__ */ React288.createElement(Alert61, { color: "blue", variant: "light" }, /* @__PURE__ */ React288.createElement(Text180, { size: "xs" }, /* @__PURE__ */ React288.createElement("strong", null, "Sender details are NOT set here."), " Each operator running this flow fills in their own org name + KYC at runtime, in the payment block's side panel. Templates ship clean \u2014 no operator PII. The worker URL below is a default; operators can override it per-flow.")), /* @__PURE__ */ React288.createElement(Stack205, { gap: "xs" }, /* @__PURE__ */ React288.createElement(Text180, { size: "sm", fw: 600 }, "Claim source"), /* @__PURE__ */ React288.createElement(Text180, { size: "xs", c: "dimmed" }, "The Claims tab in the flow-mode UI pulls approved claims from this collection so the payer can pick which ones to pay out. Use the same collection ID that the claim and evaluation blocks point at."), /* @__PURE__ */ React288.createElement(TextInput9, { size: "xs", label: "Claim collection ID", placeholder: "e.g. 781", value: local.collectionId, onChange: (e) => update({ collectionId: e.currentTarget.value }) })), /* @__PURE__ */ React288.createElement(Divider25, { variant: "dashed" }), /* @__PURE__ */ React288.createElement(Stack205, { gap: "xs" }, /* @__PURE__ */ React288.createElement(Text180, { size: "sm", fw: 600 }, "Default YellowCard worker URL"), /* @__PURE__ */ React288.createElement(Text180, { size: "xs", c: "dimmed" }, "The template-author's default. Used when an operator hasn't set a flow-level override. Operators running self-hosted workers paste their own URL in the flow-mode Payout setup panel \u2014 that override wins. Leave empty to force every operator to choose their own."), /* @__PURE__ */ React288.createElement(
32216
32204
  TextInput9,
32217
32205
  {
32218
32206
  size: "xs",
@@ -32221,25 +32209,7 @@ var PaymentConfig = ({
32221
32209
  value: local.defaultWorkerBaseUrl,
32222
32210
  onChange: (e) => update({ defaultWorkerBaseUrl: e.currentTarget.value })
32223
32211
  }
32224
- )), /* @__PURE__ */ React288.createElement(Divider25, { variant: "dashed" }), /* @__PURE__ */ React288.createElement(Stack205, { gap: "xs" }, /* @__PURE__ */ React288.createElement(Text180, { size: "sm", fw: 600 }, "Defaults"), /* @__PURE__ */ React288.createElement(Group111, { grow: true }, /* @__PURE__ */ React288.createElement(
32225
- TextInput9,
32226
- {
32227
- size: "xs",
32228
- label: "Default reason",
32229
- placeholder: "other",
32230
- value: local.defaultReason,
32231
- onChange: (e) => update({ defaultReason: e.currentTarget.value })
32232
- }
32233
- ), /* @__PURE__ */ React288.createElement(
32234
- TextInput9,
32235
- {
32236
- size: "xs",
32237
- label: "Customer type",
32238
- placeholder: "retail",
32239
- value: local.customerType,
32240
- onChange: (e) => update({ customerType: e.currentTarget.value })
32241
- }
32242
- ))), /* @__PURE__ */ React288.createElement(Divider25, { variant: "dashed" }), /* @__PURE__ */ React288.createElement(Stack205, { gap: "xs" }, /* @__PURE__ */ React288.createElement(Text180, { size: "sm", fw: 600 }, "Row template \u2014 claim & evaluation mapping"), /* @__PURE__ */ React288.createElement(Text180, { size: "xs", c: "dimmed" }, "Each value is a reference expression that the payment bridge resolves against the approved claim's survey answers and the evaluator's outcome. Use the variable picker (V icon) to insert refs like ", /* @__PURE__ */ React288.createElement("code", null, "{{claim.surveyAnswers.<field>}}"), " or", " ", /* @__PURE__ */ React288.createElement("code", null, "{{evaluation.amount}}"), ". Operators can override any field inline before proposing."), Object.keys(FIELD_LABEL).map((key) => /* @__PURE__ */ React288.createElement(
32212
+ )), /* @__PURE__ */ React288.createElement(Divider25, { variant: "dashed" }), /* @__PURE__ */ React288.createElement(Stack205, { gap: "xs" }, /* @__PURE__ */ React288.createElement(Text180, { size: "sm", fw: 600 }, "Defaults"), /* @__PURE__ */ React288.createElement(Group111, { grow: true }, /* @__PURE__ */ React288.createElement(TextInput9, { size: "xs", label: "Default reason", placeholder: "other", value: local.defaultReason, onChange: (e) => update({ defaultReason: e.currentTarget.value }) }), /* @__PURE__ */ React288.createElement(TextInput9, { size: "xs", label: "Customer type", placeholder: "retail", value: local.customerType, onChange: (e) => update({ customerType: e.currentTarget.value }) }))), /* @__PURE__ */ React288.createElement(Divider25, { variant: "dashed" }), /* @__PURE__ */ React288.createElement(Stack205, { gap: "xs" }, /* @__PURE__ */ React288.createElement(Text180, { size: "sm", fw: 600 }, "Row template \u2014 claim & evaluation mapping"), /* @__PURE__ */ React288.createElement(Text180, { size: "xs", c: "dimmed" }, "Each value is a reference expression that the payment bridge resolves against the approved claim's survey answers and the evaluator's outcome. Use the variable picker (V icon) to insert refs like ", /* @__PURE__ */ React288.createElement("code", null, "{{claim.surveyAnswers.<field>}}"), " or ", /* @__PURE__ */ React288.createElement("code", null, "{{evaluation.amount}}"), ". Operators can override any field inline before proposing."), Object.keys(FIELD_LABEL).map((key) => /* @__PURE__ */ React288.createElement(
32243
32213
  DataInput,
32244
32214
  {
32245
32215
  key,
@@ -32365,6 +32335,7 @@ function resolvePaymentRowFields(fieldTemplate, editorDocument, scope) {
32365
32335
  accountName: r(fieldTemplate.accountName),
32366
32336
  accountNumber: r(fieldTemplate.accountNumber),
32367
32337
  accountType: r(fieldTemplate.accountType),
32338
+ bankName: r(fieldTemplate.bankName),
32368
32339
  networkId: r(fieldTemplate.networkId),
32369
32340
  country: r(fieldTemplate.country),
32370
32341
  bvn: r(fieldTemplate.bvn),
@@ -32438,9 +32409,7 @@ function appendManualPaymentRow(editor, paymentBlock, fields) {
32438
32409
  }
32439
32410
  function patchPaymentRow(editor, paymentBlock, rowId, patch) {
32440
32411
  const rows = readPaymentRows(paymentBlock);
32441
- const next = rows.map(
32442
- (r) => r.id === rowId ? { ...r, ...patch, fields: { ...r.fields, ...patch.fields ?? {} } } : r
32443
- );
32412
+ const next = rows.map((r) => r.id === rowId ? { ...r, ...patch, fields: { ...r.fields, ...patch.fields ?? {} } } : r);
32444
32413
  writePaymentRows(editor, paymentBlock, next);
32445
32414
  }
32446
32415
  function removePaymentRow(editor, paymentBlock, rowId) {
@@ -32906,7 +32875,8 @@ var PaymentFlowDetail = ({ inputs, editor, block, runtime, isDisabled, executeAc
32906
32875
  }, [block, chainClaims, checkedClaimIds, editor, parsed.fieldTemplate]);
32907
32876
  const [setupOpen, setSetupOpen] = useState141(() => {
32908
32877
  const initial = parsePaymentInputs(inputs);
32909
- return !initial.workerBaseUrl.trim() || !initial.sender.name.trim() || !initial.sender.country.trim();
32878
+ const initialIsNG = initial.sender.country.trim().toUpperCase() === "NG";
32879
+ return !initial.workerBaseUrl.trim() || !initial.sender.name.trim() || !initial.sender.country.trim() || initialIsNG && (!initial.sender.idNumber.trim() || !initial.sender.additionalIdNumber.trim());
32910
32880
  });
32911
32881
  const [submitting, setSubmitting] = useState141(false);
32912
32882
  const [error, setError] = useState141(null);
@@ -32952,6 +32922,9 @@ var PaymentFlowDetail = ({ inputs, editor, block, runtime, isDisabled, executeAc
32952
32922
  if (!parsed.sender.name.trim() || !parsed.sender.country.trim()) {
32953
32923
  return "Sender name and country are required. Open Payout setup above and fill them in.";
32954
32924
  }
32925
+ if (parsed.sender.country.trim().toUpperCase() === "NG" && (!parsed.sender.idNumber.trim() || !parsed.sender.additionalIdNumber.trim())) {
32926
+ return "NG senders must supply both NIN (idNumber) and BVN (additionalIdNumber). Open Payout setup above and fill them in \u2014 the worker auto-stamps the type fields.";
32927
+ }
32955
32928
  if (oracleResolving) return "Resolving the oracle DID \u2014 try again in a moment.";
32956
32929
  if (!oracleDid) return "Cannot determine the chat oracle DID.";
32957
32930
  if (!selectedDelegationCid) return "Select a UCAN delegation (or create one).";
@@ -32964,7 +32937,17 @@ var PaymentFlowDetail = ({ inputs, editor, block, runtime, isDisabled, executeAc
32964
32937
  }
32965
32938
  }
32966
32939
  return null;
32967
- }, [effectiveWorkerBaseUrl, parsed.sender.name, parsed.sender.country, oracleDid, oracleResolving, selectedDelegationCid, usableDelegations]);
32940
+ }, [
32941
+ effectiveWorkerBaseUrl,
32942
+ parsed.sender.name,
32943
+ parsed.sender.country,
32944
+ parsed.sender.idNumber,
32945
+ parsed.sender.additionalIdNumber,
32946
+ oracleDid,
32947
+ oracleResolving,
32948
+ selectedDelegationCid,
32949
+ usableDelegations
32950
+ ]);
32968
32951
  const rowValidity = useMemo117(() => {
32969
32952
  const out = /* @__PURE__ */ new Map();
32970
32953
  for (const r of rows) {
@@ -33149,7 +33132,8 @@ var PaymentFlowDetail = ({ inputs, editor, block, runtime, isDisabled, executeAc
33149
33132
  }
33150
33133
  const oracleUnavailable = !oracleResolving && !oracleDid;
33151
33134
  const workerUrlMissing = !effectiveWorkerBaseUrl;
33152
- const senderIncomplete = !parsed.sender.name.trim() || !parsed.sender.country.trim();
33135
+ const senderIsNG = parsed.sender.country.trim().toUpperCase() === "NG";
33136
+ const senderIncomplete = !parsed.sender.name.trim() || !parsed.sender.country.trim() || senderIsNG && (!parsed.sender.idNumber.trim() || !parsed.sender.additionalIdNumber.trim());
33153
33137
  const setupIncomplete = workerUrlMissing || senderIncomplete;
33154
33138
  const noUsableDelegation = usableDelegations.length === 0;
33155
33139
  const delegationNotSelected = !selectedDelegationCid;
@@ -33189,7 +33173,7 @@ var PaymentFlowDetail = ({ inputs, editor, block, runtime, isDisabled, executeAc
33189
33173
  onChange: (e) => patchInputs({ workerBaseUrl: e.currentTarget.value }),
33190
33174
  error: workerUrlMissing ? "Required" : void 0
33191
33175
  }
33192
- ), /* @__PURE__ */ React289.createElement(Divider26, { variant: "dashed", my: 4 }), /* @__PURE__ */ React289.createElement(Text181, { size: "xs", fw: 600, c: "dimmed" }, "Sender (organisation paying out)"), /* @__PURE__ */ React289.createElement(Text181, { size: "xs", c: "dimmed" }, "These details go with every row you propose. YellowCard requires full KYC (address, dob, idType, idNumber) once cumulative payments per recipient cross $200 USD \u2014 set them now to avoid mid-batch rejections."), /* @__PURE__ */ React289.createElement(Group112, { grow: true }, /* @__PURE__ */ React289.createElement(
33176
+ ), /* @__PURE__ */ React289.createElement(Divider26, { variant: "dashed", my: 4 }), /* @__PURE__ */ React289.createElement(Text181, { size: "xs", fw: 600, c: "dimmed" }, "Sender (organisation paying out)"), /* @__PURE__ */ React289.createElement(Text181, { size: "xs", c: "dimmed" }, "These details go with every row you propose. YellowCard requires full KYC (address, dob, idType, idNumber) once cumulative payments per recipient cross $200 USD \u2014 set them now to avoid mid-batch rejections. NG senders additionally need NIN + BVN (extra fields appear when Country is set to NG)."), /* @__PURE__ */ React289.createElement(Group112, { grow: true }, /* @__PURE__ */ React289.createElement(
33193
33177
  TextInput10,
33194
33178
  {
33195
33179
  size: "xs",
@@ -33217,7 +33201,27 @@ var PaymentFlowDetail = ({ inputs, editor, block, runtime, isDisabled, executeAc
33217
33201
  value: parsed.sender.dob,
33218
33202
  onChange: (e) => patchSender({ dob: e.currentTarget.value })
33219
33203
  }
33220
- ), /* @__PURE__ */ React289.createElement(TextInput10, { size: "xs", label: "ID type", placeholder: "passport", value: parsed.sender.idType, onChange: (e) => patchSender({ idType: e.currentTarget.value }) }), /* @__PURE__ */ React289.createElement(TextInput10, { size: "xs", label: "ID number", value: parsed.sender.idNumber, onChange: (e) => patchSender({ idNumber: e.currentTarget.value }) }))))), /* @__PURE__ */ React289.createElement(Divider26, null), /* @__PURE__ */ React289.createElement(Stack206, { gap: "xs" }, /* @__PURE__ */ React289.createElement(Group112, { justify: "space-between", align: "flex-end" }, /* @__PURE__ */ React289.createElement(Stack206, { gap: 2, style: { flex: 1 } }, /* @__PURE__ */ React289.createElement(Text181, { size: "xs", fw: 600, c: "dimmed" }, "UCAN Authorization"), /* @__PURE__ */ React289.createElement(Text181, { size: "xs", c: "dimmed" }, "Sign once \u2014 the oracle mints per-call invocations against the worker for every row.")), /* @__PURE__ */ React289.createElement(
33204
+ ), parsed.sender.country.trim().toUpperCase() === "NG" ? /* @__PURE__ */ React289.createElement(TextInput10, { size: "xs", label: "ID type", value: "NIN", readOnly: true, description: "Auto-set for NG senders" }) : /* @__PURE__ */ React289.createElement(TextInput10, { size: "xs", label: "ID type", placeholder: "passport", value: parsed.sender.idType, onChange: (e) => patchSender({ idType: e.currentTarget.value }) }), /* @__PURE__ */ React289.createElement(
33205
+ TextInput10,
33206
+ {
33207
+ size: "xs",
33208
+ label: parsed.sender.country.trim().toUpperCase() === "NG" ? "NIN (National Identification Number)" : "ID number",
33209
+ value: parsed.sender.idNumber,
33210
+ onChange: (e) => patchSender({ idNumber: e.currentTarget.value }),
33211
+ error: parsed.sender.country.trim().toUpperCase() === "NG" && !parsed.sender.idNumber.trim() ? "Required for NG" : void 0
33212
+ }
33213
+ )), parsed.sender.country.trim().toUpperCase() === "NG" && /* @__PURE__ */ React289.createElement(React289.Fragment, null, /* @__PURE__ */ React289.createElement(Text181, { size: "xs", c: "dimmed" }, "YellowCard requires NG senders to supply both NIN and BVN. The ID type is fixed by regulation \u2014 only fill in the BVN number below."), /* @__PURE__ */ React289.createElement(
33214
+ TextInput10,
33215
+ {
33216
+ size: "xs",
33217
+ label: "BVN (Bank Verification Number)",
33218
+ value: parsed.sender.additionalIdNumber,
33219
+ onChange: (e) => patchSender({
33220
+ additionalIdNumber: e.currentTarget.value
33221
+ }),
33222
+ error: !parsed.sender.additionalIdNumber.trim() ? "Required for NG" : void 0
33223
+ }
33224
+ ))))), /* @__PURE__ */ React289.createElement(Divider26, null), /* @__PURE__ */ React289.createElement(Stack206, { gap: "xs" }, /* @__PURE__ */ React289.createElement(Group112, { justify: "space-between", align: "flex-end" }, /* @__PURE__ */ React289.createElement(Stack206, { gap: 2, style: { flex: 1 } }, /* @__PURE__ */ React289.createElement(Text181, { size: "xs", fw: 600, c: "dimmed" }, "UCAN Authorization"), /* @__PURE__ */ React289.createElement(Text181, { size: "xs", c: "dimmed" }, "Sign once \u2014 the oracle mints per-call invocations against the worker for every row.")), /* @__PURE__ */ React289.createElement(
33221
33225
  Button62,
33222
33226
  {
33223
33227
  variant: "light",
@@ -33376,10 +33380,16 @@ var FIELD_DISPLAY = [
33376
33380
  { key: "accountName", label: "Recipient account name" },
33377
33381
  { key: "accountNumber", label: "Account number" },
33378
33382
  { key: "accountType", label: "Account type", placeholder: "bank or momo" },
33383
+ {
33384
+ key: "bankName",
33385
+ label: "Bank name (required)",
33386
+ placeholder: "e.g. Capitec Bank, FNB, MTN",
33387
+ description: "Must match a YellowCard network name for the recipient's country. The oracle resolves this to a networkId \u2014 a wrong bank routes funds to the wrong clearing system."
33388
+ },
33379
33389
  {
33380
33390
  key: "networkId",
33381
- label: "Network / bank UUID (optional)",
33382
- description: "Leave empty \u2014 oracle resolves via /channels discovery."
33391
+ label: "Network / bank UUID (optional override)",
33392
+ description: "Leave empty \u2014 oracle resolves via /channels discovery using Bank name. Only set to override resolution."
33383
33393
  },
33384
33394
  { key: "country", label: "Country (ISO 3166-1 alpha-2)" },
33385
33395
  { key: "bvn", label: "BVN (NG, optional)" },
@@ -33401,7 +33411,11 @@ var FIELD_DISPLAY = [
33401
33411
  description: "Local currency the recipient receives \u2014 never USD."
33402
33412
  },
33403
33413
  { key: "reason", label: "Reason (optional)" },
33404
- { key: "recipientDid", label: "Recipient DID (optional)" }
33414
+ {
33415
+ key: "recipientDid",
33416
+ label: "Recipient DID (required)",
33417
+ description: "DID of the person being paid out to \u2014 used as YC customerUID for per-user KYC tracking. NEVER inferred from the operator: a missing value fails the row at propose time."
33418
+ }
33405
33419
  ];
33406
33420
  var PaymentRowDetail = ({ row, missing, compat, onBack, onPatch, onRemove, onPropose, onExecute, onCheck, onReset, submitting }) => {
33407
33421
  const isFilled = row.status === "filled";
@@ -44928,4 +44942,4 @@ export {
44928
44942
  getExtraSlashMenuItems,
44929
44943
  useCreateIxoEditor
44930
44944
  };
44931
- //# sourceMappingURL=chunk-EOOKJV32.mjs.map
44945
+ //# sourceMappingURL=chunk-DJHCUHR5.mjs.map