@@ -456,6 +456,45 @@ export interface GlobalFlagsInterface {
456456 tfInnerBatchTxn ?: boolean
457457}
458458
459+ /**
460+ * Enum representing sponsor flags for transaction sponsorship.
461+ * These flags indicate what type of sponsorship is being applied to a transaction.
462+ *
463+ * @category Transaction Flags
464+ */
465+ export enum SponsorFlags {
466+ /**
467+ * Indicates that the sponsor is paying the transaction fee.
468+ */
469+ tfSponsorFee = 0x00000001 ,
470+ /**
471+ * Indicates that the sponsor is paying for the reserve of any objects
472+ * created in the transaction.
473+ */
474+ tfSponsorReserve = 0x00000002 ,
475+ }
476+
477+ /**
478+ * The SponsorSignature object contains signing information for sponsored
479+ * transactions. It holds the sponsor's signature to authorize the sponsorship.
480+ */
481+ export interface SponsorSignature {
482+ /**
483+ * The public key for the sponsor's account, if single-signing.
484+ */
485+ SigningPubKey ?: string
486+ /**
487+ * A signature from the sponsor to indicate their approval of the transaction,
488+ * if single-signing.
489+ */
490+ TxnSignature ?: string
491+ /**
492+ * An array of signatures from the sponsor's signers to indicate their approval
493+ * of the transaction, if the sponsor is multi-signing.
494+ */
495+ Signers ?: Signer [ ]
496+ }
497+
459498/**
460499 * Every transaction has the same set of common fields.
461500 */
@@ -534,6 +573,23 @@ export interface BaseTransaction extends Record<string, unknown> {
534573 * The delegate account that is sending the transaction.
535574 */
536575 Delegate ?: Account
576+ /**
577+ * The account ID of the sponsor for this transaction. If this field is
578+ * included, the sponsor is co-signing the transaction to pay for the fee
579+ * and/or reserve on behalf of the transaction sender.
580+ */
581+ Sponsor ?: Account
582+ /**
583+ * Flags indicating what type of sponsorship this is. Must be included if
584+ * Sponsor is included. Valid values are tfSponsorFee (1) and/or
585+ * tfSponsorReserve (2).
586+ */
587+ SponsorFlags ?: number
588+ /**
589+ * An object containing the sponsor's signature information to authorize
590+ * the sponsorship. Must be included if Sponsor is included.
591+ */
592+ SponsorSignature ?: SponsorSignature
537593}
538594
539595/**
@@ -610,6 +666,69 @@ export function validateBaseTransaction(
610666 'BaseTransaction: Account and Delegate addresses cannot be the same' ,
611667 )
612668 }
669+
670+ // Sponsor fields validation
671+ validateOptionalField ( common , 'Sponsor' , isAccount )
672+ validateOptionalField ( common , 'SponsorFlags' , isNumber )
673+
674+ // Validate SponsorSignature if present
675+ if ( common . SponsorSignature !== undefined ) {
676+ if ( ! isRecord ( common . SponsorSignature ) ) {
677+ throw new ValidationError ( 'BaseTransaction: invalid SponsorSignature' )
678+ }
679+ const sponsorSig = common . SponsorSignature
680+ if (
681+ sponsorSig . SigningPubKey !== undefined &&
682+ ! isString ( sponsorSig . SigningPubKey )
683+ ) {
684+ throw new ValidationError (
685+ 'BaseTransaction: invalid SponsorSignature.SigningPubKey' ,
686+ )
687+ }
688+ if (
689+ sponsorSig . TxnSignature !== undefined &&
690+ ! isString ( sponsorSig . TxnSignature )
691+ ) {
692+ throw new ValidationError (
693+ 'BaseTransaction: invalid SponsorSignature.TxnSignature' ,
694+ )
695+ }
696+ if (
697+ sponsorSig . Signers !== undefined &&
698+ ( ! isArray ( sponsorSig . Signers ) ||
699+ sponsorSig . Signers . length === 0 ||
700+ ! sponsorSig . Signers . every ( isSigner ) )
701+ ) {
702+ throw new ValidationError (
703+ 'BaseTransaction: invalid SponsorSignature.Signers' ,
704+ )
705+ }
706+ }
707+
708+ // Validate that Sponsor, SponsorFlags, and SponsorSignature are all present or all absent
709+ const hasSponsor = common . Sponsor !== undefined
710+ const hasSponsorFlags = common . SponsorFlags !== undefined
711+ const hasSponsorSignature = common . SponsorSignature !== undefined
712+
713+ if ( hasSponsor || hasSponsorFlags || hasSponsorSignature ) {
714+ if ( ! hasSponsor || ! hasSponsorFlags ) {
715+ throw new ValidationError (
716+ 'BaseTransaction: Sponsor and SponsorFlags must both be included if either is present' ,
717+ )
718+ }
719+ // SponsorSignature may be omitted if using pre-funded sponsorship without signature requirement
720+ }
721+
722+ // Validate SponsorFlags has valid values
723+ if ( hasSponsorFlags ) {
724+ const validFlags = SponsorFlags . tfSponsorFee | SponsorFlags . tfSponsorReserve
725+ const flags = common . SponsorFlags as number
726+ if ( ( flags & ~ validFlags ) !== 0 || flags === 0 ) {
727+ throw new ValidationError (
728+ 'BaseTransaction: invalid SponsorFlags - must include tfSponsorFee and/or tfSponsorReserve' ,
729+ )
730+ }
731+ }
613732}
614733
615734/**
0 commit comments