diff --git a/Electrum.sqlite-journal b/Electrum.sqlite-journal deleted file mode 100644 index 36a5776..0000000 Binary files a/Electrum.sqlite-journal and /dev/null differ diff --git a/src/controllers/invitation-controller.ts b/src/controllers/invitation-controller.ts index 90552d6..6d34b8b 100644 --- a/src/controllers/invitation-controller.ts +++ b/src/controllers/invitation-controller.ts @@ -136,12 +136,7 @@ export class InvitationController extends EventEmitter { inputIdentifier?: string; }>, ): Promise { - // Ensure each input has an inputIdentifier (sync server requires it) - const inputsWithIds = inputs.map((input, index) => ({ - ...input, - inputIdentifier: input.inputIdentifier ?? `senderInput_${Date.now()}_${index}`, - })); - return this.flowManager.appendToInvitation(invitationId, { inputs: inputsWithIds }); + return this.flowManager.appendToInvitation(invitationId, { inputs }); } /** @@ -158,12 +153,7 @@ export class InvitationController extends EventEmitter { roleIdentifier?: string; }>, ): Promise { - // Ensure each output has an outputIdentifier (sync server may require it) - const outputsWithIds = outputs.map((output, index) => ({ - ...output, - outputIdentifier: output.outputIdentifier ?? `changeOutput_${Date.now()}_${index}`, - })); - return this.flowManager.appendToInvitation(invitationId, { outputs: outputsWithIds }); + return this.flowManager.appendToInvitation(invitationId, { outputs }); } /** diff --git a/src/tui/screens/ActionWizard.tsx b/src/tui/screens/ActionWizard.tsx index d410b5c..de815bc 100644 --- a/src/tui/screens/ActionWizard.tsx +++ b/src/tui/screens/ActionWizard.tsx @@ -276,7 +276,7 @@ export function ActionWizardScreen(): React.ReactElement { * Create invitation and add variables. */ const createInvitationWithVariables = useCallback(async () => { - if (!templateIdentifier || !actionIdentifier || !roleIdentifier) return; + if (!templateIdentifier || !actionIdentifier || !roleIdentifier || !template) return; setIsProcessing(true); setStatus('Creating invitation...'); @@ -305,6 +305,25 @@ export function ActionWizardScreen(): React.ReactElement { inv = updated.invitation; } + // Add template-required outputs for the current role + // This is critical - the template defines which outputs the initiator must create + const action = template.actions?.[actionIdentifier]; + const transaction = action?.transaction ? template.transactions?.[action.transaction] : null; + + if (transaction?.outputs && transaction.outputs.length > 0) { + setStatus('Adding required outputs...'); + + // Add each required output with its identifier + // The engine will automatically generate the locking bytecode based on the template + const outputsToAdd = transaction.outputs.map((outputId: string) => ({ + outputIdentifier: outputId, + roleIdentifier: roleIdentifier, + })); + + const updated = await invitationController.addOutputs(invId, outputsToAdd); + inv = updated.invitation; + } + setInvitation(inv); // Check if next step is inputs @@ -323,7 +342,7 @@ export function ActionWizardScreen(): React.ReactElement { } finally { setIsProcessing(false); } - }, [templateIdentifier, actionIdentifier, roleIdentifier, variables, invitationController, steps, currentStep, showError, setStatus, loadAvailableUtxos]); + }, [templateIdentifier, actionIdentifier, roleIdentifier, template, variables, invitationController, steps, currentStep, showError, setStatus, loadAvailableUtxos]); /** * Add selected inputs and change output to invitation.