@pwngh/economy-lab
    Preparing search index...

    Variable reversePayoutConst

    reversePayout: (
        fields: FieldsOf<K>,
    ) => {
        actor: Principal;
        idempotencyKey: string;
        kind: "reversePayout";
        providerReported?: boolean;
        reason: string;
        sagaId: string;
        userId: string;
    } = ...

    Builds a reversePayout operation: undoes a payout that has not yet disbursed USD. In one transaction it marks the saga FAILED and moves the full reserve out of PAYOUT_RESERVE back to the seller's earned account. It applies to a RESERVED saga, or a SUBMITTED one aged past maxPayoutAgeMs — a younger SUBMITTED payout is still in the rail's hands and is refused with SAGA.INVALID_TRANSITION (the verified payout-failed webhook waives that gate via providerReported; never set it by hand), as is a SETTLED payout, whose USD already left trust. An already-FAILED saga returns duplicate with no posting, and the guarded state change means two racing attempts can never both return the same reserve. Restricted to an operator or system actor; userId must match the saga's own seller, since it names the account the engine locks.

    Type Declaration

      • (
            fields: FieldsOf<K>,
        ): {
            actor: Principal;
            idempotencyKey: string;
            kind: "reversePayout";
            providerReported?: boolean;
            reason: string;
            sagaId: string;
            userId: string;
        }
      • Parameters

        • fields: FieldsOf<K>

        Returns {
            actor: Principal;
            idempotencyKey: string;
            kind: "reversePayout";
            providerReported?: boolean;
            reason: string;
            sagaId: string;
            userId: string;
        }

        • actor: Principal
        • idempotencyKey: string
        • kind: "reversePayout"
        • OptionalproviderReported?: boolean

          True when the payout rail itself reported the disbursement failed (a verified payoutFailed webhook). It waives the still-live SUBMITTED refusal: the provider has said it will not settle this payout, so returning the reserve promptly cannot double-pay. An operator's manual reverse leaves this unset and stays gated until the payout ages past maxPayoutAgeMs.

        • reason: string
        • sagaId: string
        • userId: string
    const outcome = await economy.submit(reversePayout({
    idempotencyKey: idempotencyKey('unwind', 'pay_9f2c'),
    actor: operatorActor('op_7'),
    userId: 'usr_seller',
    sagaId: 'pay_9f2c',
    reason: 'fraud hold',
    }));