Auto-generate XDR types from canonical .x definitions#72
Merged
christian-rogobete merged 51 commits intomainfrom Mar 11, 2026
Merged
Auto-generate XDR types from canonical .x definitions#72christian-rogobete merged 51 commits intomainfrom
christian-rogobete merged 51 commits intomainfrom
Conversation
Ruby-based XDR code generator that reads .x definition files via the xdrgen gem AST and produces PHP classes matching existing SDK patterns. Includes Docker-based build (Makefile), override system for name/field/ type mappings, SKIP_TYPES protection for 309 existing classes, snapshot test infrastructure, and .x XDR source files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract encode/decode into *Base.php files for types with custom SDK methods. Wrappers now extend their Base class and retain only factory methods, conversions, and helpers. Base decode() uses `new static()` for proper late static binding. Updated generator to emit `static` return types for BASE_WRAPPER_TYPES. Types: XdrSCVal, XdrHostFunction, XdrLedgerKey, XdrTransaction, XdrMuxedAccount, XdrAccountID, XdrSCAddress, XdrClaimableBalanceID, XdrMuxedAccountMed25519, XdrContractExecutable, XdrContractIDPreimage, XdrDecoratedSignature Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hand-written enums with generated versions: XdrAssetType, XdrMemoType, XdrClaimantType, XdrClaimPredicateType, XdrLiquidityPoolType, XdrRevokeSponsorshipType, XdrPreconditionType. Adds member overrides for 4 enums that strip XDR type prefixes from constant names. Fixes XdrMemoType decode() bug (was returning XdrEnvelopeType). Adds toBase64Xdr/fromBase64Xdr to all generated enums. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add MEMBER_PREFIX_STRIP feature to generator for scalable constant name mapping, regenerate 29 enum types (26 result codes + 3 simple type enums), and fix enum $value visibility to public for backward compatibility. Adds 5 missing constants from XDR spec across 3 types. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…er support (Batch 3) Add typedef chain resolution infrastructure to follow chains like PoolID → Hash → opaque[32] for correct encode/decode calls. Populate TYPE_OVERRIDES (17 entries), FIELD_OVERRIDES (5 types), and FIELD_TYPE_OVERRIDES (9 types for BigInteger fields). Generate getters/setters for backward compatibility. Fixes 3 bugs in hand-written code: - XdrClaimOfferAtom: signed/unsigned mismatch for offerID - XdrCreatePassiveSellOfferOperation: spurious $xdr argument in decode - XdrSimplePaymentResult: wrong destination type (MuxedAccount → AccountID) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… enums (Batch 4) Add factory method generation for all enum types. Each constant gets a static factory (e.g., XdrOperationType::PAYMENT()). Add FACTORY_PREFIX_STRIP for 5 types where factory names strip a prefix from constant names, FACTORY_NAME_OVERRIDES for XdrSCValType's inconsistent naming, and FACTORY_ALIASES for XdrLedgerEntryType::EXPIRATION() backward compat. Previously-generated enums (Batch 1 & 2) also receive factory methods as a purely additive change. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…and SCSymbol typedef (Batch 5) Regenerate 29 struct types including envelope types with array fields, Soroban types, ledger key types, and SCSpec types. Add XdrSCSymbol to TYPE_OVERRIDES for string typedef resolution. Add FIELD_OVERRIDES for reserved-word property name preservation (function field). Add BigInteger overrides for XdrLiabilities. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…pedef array support (Batch 6) Regenerate 28 structs and 2 enums, including SCSpec types (struct fields, enum cases, events, functions, unions), operation types (AllowTrust, SetTrustLineFlags, ClaimClaimableBalance, Clawback), entry types, and meta types. Add field name overrides for authorize→authorized, trustor→accountID, val→value. Fix signed→unsigned encoding for AccountEntryV3.seqTime and AllowTrustOperation.authorized. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…, and event types (Batch 7) Regenerate XdrBumpSequenceOperation, XdrClawbackOperation, XdrContractDataEntry, XdrPathPaymentStrictReceiveOperation, XdrPathPaymentStrictSendOperation, XdrTransactionEvent, and XdrTransactionEventStage. Adds FIELD_TYPE_OVERRIDES for BigInteger amount fields. Fixes latent silent-corruption bug in PathPayment encode() where instanceof guard could produce mismatched array length. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… and factories (Batch 8) Regenerate XdrContractCostType (fix instance decode, add 25 missing BLS12-381 constants), XdrTrustLineFlags (fix wrong decode return type), XdrInvokeHostFunctionResultCode, XdrSCEnvMetaKind, XdrSCMetaKind, XdrSCSpecEntryKind, XdrSCSpecUDTUnionCaseV0Kind, XdrSorobanAuthorizedFunctionType, and XdrSorobanCredentialsType. Adds factory prefix strips and custom factory name overrides. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…uard fixes (Batch 9) Regenerate XdrOperationMeta, XdrTransactionMetaV1, XdrTransactionMetaV2, and XdrCreateClaimableBalanceOperation. Add typedef-array inlining to the generator: when TYPE_OVERRIDES maps a typedef to "array", struct fields using that typedef are inlined as PHP arrays with encode/decode loops instead of creating a wrapper class. Fixes instanceof guard bugs in all 4 hand-written files that could produce corrupt XDR. Side-effect fix to XdrOperationMetaV2 for the same typedef-array pattern. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… alias (Batch 10) First union generation: regenerate 6 void-only result unions (XdrClawbackResult, XdrClawbackClaimableBalanceResult, XdrRevokeSponsorshipResult, XdrExtendFootprintTTLResult, XdrRestoreFootprintResult, XdrManageDataResult) and 1 struct (XdrEvictionIterator). Generator infrastructure: add union accessor generation (getters/setters for discriminant and arm fields), union discriminant field name overrides via FIELD_OVERRIDES, boolean "is" getter alias for struct fields (isFoo() instead of getIsFoo()), and fix format_case_label to resolve enum member names correctly in union switch cases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…attern (Batch 11) Regenerate 12 void-only result union types (AllowTrust, BeginSponsoring, BumpSequence, ChangeTrust, ClaimClaimableBalance, CreateAccount, EndSponsoring, LiquidityPoolDeposit, LiquidityPoolWithdraw, Payment, SetOptions, SetTrustLineFlags) and re-generate 6 Batch 10 types to pick up the optional constructor change. Infrastructure: make union constructor optional (?Type $disc = null) to support no-arg construction pattern used by existing SDK code. Fix XdrCreateAccountResult bug: hand-written code used wrong discriminant type (XdrOperationResultCode instead of XdrCreateAccountResultCode). Tests updated to match correct type. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rms (Batch 12) Generate first non-void union arm types: XdrExtensionPoint (void-only int-disc), XdrAccountMergeResult (BigInteger arm), XdrInvokeHostFunctionResult (Hash/opaque[32] arm), XdrInflationResult (InflationPayout array arm). Infrastructure: apply FIELD_TYPE_OVERRIDES to union arms for BigInteger support, add BigInteger import handling for unions, fix nullable type hint for array arms in union accessors. Fix XdrInvokeHostFunctionResult double-concat encoding bug ($bytes .= $bytes .=), XdrInflationResult instanceof guard, and XdrAccountMergeResult nullability-based encoding. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… signed/unsigned bugs (Batch 13) Generate XdrManageBuyOfferOperation, XdrManageSellOfferOperation, XdrLiquidityPoolConstantProductParameters, XdrFeeBumpTransactionExt, and XdrTransactionV0Ext. Fixes spurious $xdr argument in readBigInteger64() and signed/unsigned mismatch for offerID in both offer operations. Updates AssetTypePoolShare to pass fee explicitly after removing LIQUIDITY_POOL_FEE_V18 constant default. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ypedef (Batch 14) Generate XdrSequenceNumber (BigInteger typedef), XdrDataEntryExt, XdrOfferEntryExt, XdrLedgerEntryV1Ext (void-only int-disc unions), XdrTransactionExt and XdrSorobanTransactionDataExt (non-void int-disc unions with case 1 data arms). Migrates all XdrSequenceNumber::getValue() callers to public property access and updates 2-arg union constructors to 2-step property assignment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…g (Batch 15) Replace 9 hand-written int-discriminated ext unions with generated versions. Fixes XdrClaimableBalanceEntryExt encoding that used nullability check instead of proper discriminant switch. Updates 7 test files to use 1-arg constructor pattern with property assignment for non-void arms. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nd base/wrapper pattern (Batch 16) Fix double-?? generator bug where php_type_string() added redundant ? prefix for optional types. Add EXTENSION_POINT_FIELDS support for XdrClaimableBalanceEntryExtV1 and XdrTrustLineEntryExtensionV2. Use FIELD_TYPE_OVERRIDES for XdrDataEntry (XdrDataValueMandatory). Introduce XdrLedgerKeyAccount as first struct BASE_WRAPPER_TYPE with forAccountId() helper preserved in wrapper. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n, and field renames (Batch 17) Generate XdrLedgerEntry, XdrLiquidityPoolEntry, XdrContractCodeEntry, XdrContractEvent, XdrSignedPayload, and XdrSorobanTransactionMetaV2. Add XdrContractID to TYPE_OVERRIDES as string (Hash-based typedef). Use FIELD_OVERRIDES for hash->cHash and contractID->hash renames. Use FIELD_TYPE_OVERRIDES for XdrDataValueMandatory on ContractCodeEntry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…Batch 18) Generate 7 direct union replacements and 2 base/wrapper pairs. Fix XdrSCError where hand-written code treated SCE_WASM_VM through SCE_AUTH as void arms — XDR spec says they all carry SCErrorCode code. Add field overrides for XdrSCMetaEntry/XdrSCEnvMetaEntry discriminant renames. Update 3 test files to match generated API changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e fix (Batch 19) Replace 3 union types (XdrHashIDPreimage, XdrLedgerEntryChange, XdrRevokeSponsorshipOperation) and generate 3 base/wrapper pairs (XdrMemo, XdrSorobanAuthorizedFunction, XdrSorobanTransactionData). Fixes XdrRevokeSponsorshipOperation null-check encode bug and adds missing XdrLedgerEntryChange restored getter/setter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…bug (Batch 20) Replace 4 hand-written XDR types with generated versions. Fixes critical copy-paste bug in XdrSorobanTransactionMeta where encode() iterated $this->events twice instead of $this->diagnosticEvents, producing corrupt XDR. Also fixes instanceof guard and offerID signed/unsigned mismatch in XdrClaimOfferAtomV0. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…guard fixes (Batch 21) Regenerate XdrPreconditions (union), XdrTransactionMeta (int-disc union), XdrTransactionMetaV3 and XdrTransactionMetaV4 (structs). Fixes instanceof guards in encode() that silently skipped non-matching array entries (count/items mismatch risk). Adds switch/case to Preconditions, public field visibility, and toBase64Xdr/fromBase64Xdr. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…of fixes (Batch 22) Regenerate XdrClaimPredicate (recursive union) and XdrTrustLineEntry (struct). Fixes instanceof guards in ClaimPredicate AND/OR encode, corrects NOT arm from array-of-1 pattern to proper XDR optional (present flag). Removes XdrAccountMergeOperation from SKIP_TYPES (not an XDR-defined type, unchanged). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ides (Batch 23) XdrLedgerEntryData: 10-arm union, field override ttl→ttlEntry, consistent camelCase. XdrContractCostParams: typedef array, field override contractCostParams→entries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…iscriminant access (Batch 24) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…amed inner struct (Batch 25) XdrContractCodeEntryExt: 2-arm union (void/v1), inner struct renamed from XdrContractCodeEntryExtV1 to XdrContractCodeEntryV1 per generator naming. Old XdrContractCodeEntryExtV1.php is now orphaned (no external callers). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…26-28) Batch 26: XdrSetOptionsOperation (all-optional struct), XdrPathPaymentResultSuccess Batch 27: XdrPreconditionsV2 (Base/wrapper pattern for no-arg constructor compat) Batch 28: XdrPathPaymentStrictReceiveResult, XdrPathPaymentStrictSendResult Generator improvements: - Reorder constructor params: required first, optional last (PHP 8.1+ compliance) - Decode args reordered to match constructor signature Bug fixes in hand-written code: - PathPayment results: switch/case replaces if/else, adds missing break statements - XdrOperationResultTest: removed 4 dead-code lines masking uninitialized property bug - Test callsites updated for new constructor param order (XdrLedgerTest, XdrTransactionMetaTest) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… 29-30) Batch 29: Verify XdrContractCodeEntryExtV1, XdrContractEventBodyV0 (generated identically, removed from SKIP_TYPES). Batch 30: Regenerate XdrSCContractInstance (optional array struct), XdrLiquidityPoolBody (union), XdrInnerTransactionResultResult (union with encode bug fix — hand-written was missing switch in encode). Generator fix: Array encode/decode path now handles is_optional for TypedefArray* fields (e.g. SCMap* storage), adding the required presence flag. Config: Add XdrSCMap => "array" type override, fix LiquidityPoolEntryConstantProduct name override key. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s (Batch 31) Regenerate XdrTransactionResultResult with discriminant field override (code → resultCode) preserving all caller compatibility. Generated encode now has explicit switch cases for all 17 discriminant values including 15 void error arms. Add field name overrides for XdrOperationResult and XdrSCSpecEntry (for future use when their other blockers are resolved). Clean up SKIP_TYPES: remove 4 permanent non-XDR entries (XdrBuffer, XdrDecoder, XdrEncoder, XdrDataValueMandatory). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…h 32) Add name override ContractEventV0 → XdrContractEventBodyV0 to fix inner struct naming mismatch. Regenerate XdrContractEventBody union with proper default case and getter/setter/base64 methods. Remove XdrContractEventBody and XdrContractEventV0 from SKIP_TYPES. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nerate XdrContractEventBodyV0 (Batches 33-34) XdrSCSpecEntry: generated base handles encode/decode, wrapper preserves 6 factory methods. XdrSCSpecTypeDef: generated base handles encode/decode with 19 void + 7 arm cases, wrapper preserves 25 factory methods. XdrContractEventBodyV0: regenerated — removes instanceof guard, adds base64 helpers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…apper - XdrSignerKeyType: generated base has full XDR constant names, wrapper preserves short-name aliases (ED25519, PRE_AUTH_TX, etc.) for backward compatibility. Adds BASE_WRAPPER support to enum generator. - XdrSignerKey: regenerated with proper switch-based encode (replaces buggy truthiness-based if/else chain that would mishandle null bytes). Field override preserves signedPayload name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d XdrFeeBumpTransaction to base wrapper pattern - XdrAllowTrustOperationAsset: wrapper overrides encode/decode to preserve asset code padding and null-stripping, keeps fromAlphaNumAssetCode() factory - XdrTransactionEnvelope: wrapper preserves fromEnvelopeBase64XdrString() factory - XdrFeeBumpTransaction: wrapper preserves optional $ext constructor default Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… support - XdrConstantProduct, XdrClaimableBalanceEntry: direct regeneration with BigInteger field type overrides - XdrAssetAlphaNum4, XdrAssetAlphaNum12: base wrapper with asset code padding and null-stripping overrides - XdrChangeTrustOperation: base wrapper preserving MAX_LIMIT constant and optional limit default - XdrConfigUpgradeSetKey: base wrapper with hex encode/decode overrides - XdrLiquidityPoolDepositOperation, XdrLiquidityPoolWithdrawOperation: base wrapper with BigInteger fields and hex pool ID conversion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… and XdrManageOfferResult to base wrapper - XdrOfferEntry: direct regeneration, fix incorrect BigInteger override (was on offerID, should be on amount), fix signed/unsigned mismatch - XdrInnerTransactionResultPair: base wrapper with hex hash encoding, fixes double-dollar-sign bug and wrong fromBase64Xdr return type - XdrManageOfferResult: base wrapper preserving 2-arg constructor, proper switch-based discriminant encoding - Update 2 test files to use full XdrOfferEntry constructor Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ith BigInteger support Replace hand-written implementations with generated code using BigInteger FIELD_TYPE_OVERRIDE for feeCharged (int64). Add name overrides so both types share XdrTransactionResultResult and XdrTransactionResultExt inner types. Remove orphaned XdrInnerTransactionResultResult class. Update test call sites to use full constructors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generate *Base.php for XdrDecoratedSignature, XdrMuxedAccountMed25519, XdrClaimableBalanceID, XdrContractExecutable, and XdrHostFunction. Add encode/decode overrides in wrappers for hex conversion and XdrDataValueMandatory handling. Add TYPE_OVERRIDES for SignatureHint and Signature typedefs, FIELD_OVERRIDES for field name mappings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regenerate XdrSCEnvMetaEntry, XdrOperationResult, XdrOperation, and XdrMuxedAccount using the XDR code generator, removing them from SKIP_TYPES. Update field overrides for XdrOperationResult (code→resultCode, tr→resultTr). Add decode() override in XdrMuxedAccount wrapper for constructor signature mismatch with generated base. Update SorobanContractInfo to reflect the XDR spec change where SCEnvMetaEntry.interfaceVersion changed from uint64 to a struct with protocol and preRelease fields. BREAKING CHANGES: - SorobanContractInfo: `envInterfaceVersion` property removed, replaced with `envMetaProtocol` and `envMetaPreRelease`. Constructor signature changed from (int, array, array) to (int, int, array, array). - XdrSCAddress: `getClaimableBalanceId()` return type changed from `?string` to `?XdrClaimableBalanceID`. Callers must use `->getClaimableBalanceId()?->getHash()` to get the hex string. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…KIP_TYPES Add :optional_array encode/decode style to handle union arms where Optional * wraps an array typedef (e.g., SCVec *vec where SCVec = SCVal<>). This enables the generator to produce correct inline array loops with optional presence flags. Add TYPE_OVERRIDES for SCVec, SCBytes, SCString typedefs so they resolve to native PHP types instead of generating wrapper classes. Add FIELD_TYPE_OVERRIDE for XdrSCVal.bytes (XdrDataValueMandatory) and FIELD_OVERRIDE for nonce_key → nonceKey. Add xdr-generator vendor/ and .bundle/ to .gitignore. SKIP_TYPES reduced from 10 to 9. All remaining are permanent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…SKIP_TYPES 9 → 6) XdrAccountID: BASE_WRAPPER with StrKey conversion deferred to encode(). XdrAccountEntry: generated with BigInteger balance, Thresholds override to string. Constructor reorders inflationDest as optional last param (breaking). XdrAccountEntryV2: generated with new elements_optional support for array fields whose element type is an optional typedef (SponsorshipDescriptor = AccountID*). Per-element presence flags in encode/decode loops. Generator changes: - Add elements_optional flag for array-of-optional-typedef patterns - Distinguish from truly optional array fields via m.type.sub_type check - Add XdrThresholds → string to TYPE_OVERRIDES Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…S 6 → 4) Generate base classes for XdrManageDataOperation and XdrTransactionV0, with wrappers preserving existing public API to avoid breaking changes. XdrManageDataOperation wrapper maintains getKey()/getValue() returning XdrDataValue. XdrTransactionV0 wrapper preserves custom constructor defaults and getSequenceNumber() getter. The generated base also fixes a bug in the hand-written encode() which was missing seqNum and memo. Add XdrDataValue TYPE_OVERRIDE mapping typedef to string so the generator correctly resolves DataValue references in other types. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Break incorrect inheritance where XdrChangeTrustAsset and XdrTrustlineAsset extended XdrAsset. Per the XDR spec these are independent unions sharing the same discriminant but are not subtypes of each other. - Generate XdrAsset, XdrChangeTrustAssetBase, XdrTrustlineAssetBase - Add wrappers for XdrChangeTrustAsset and XdrTrustlineAsset with backward-compatible helpers (fromXdrAsset, getPoolId/setPoolId) - Add Asset::fromXdrChangeTrustAsset() and Asset::fromXdrTrustlineAsset() - AssetTypePoolShare::toXdr() now throws; use toXdrChangeTrustAsset() - Update callers in ChangeTrustOperation and TxRep - Add POOL_SHARE round-trip test for XdrChangeTrustAsset BREAKING CHANGE: XdrChangeTrustAsset and XdrTrustlineAsset no longer extend XdrAsset. Use Asset::fromXdrChangeTrustAsset() for ChangeTrust operations and Asset::fromXdrTrustlineAsset() for trustline ledger keys. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enum decode() methods now validate the integer value against known constants using a switch statement and throw \InvalidArgumentException on unknown values, matching the Flutter SDK's approach. This catches data corruption and protocol version mismatches early instead of silently creating enum objects with invalid values. All 86 generated enum types are updated. Tests cover standard, negative-value, and non-contiguous enum validation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a Ruby test generator (generate_tests.rb) that parses XDR specs and auto-generates PHPUnit tests for all XDR types. The generator produces 1,016 tests covering 8 patterns: round-trip encode/decode, invalid enum decode, optional fields present, non-empty arrays, edge cases, getter/ setter validation, factory method tests, and enum factory methods. Generate 158 new XDR PHP types from the spec (overlay, ledger, SCP, transaction history, survey, etc.) to complement the 309 existing hand-written types. Remove ~5,600 lines of redundant round-trip tests from hand-written test files — these are now covered by the auto-generated suite with stronger assertions. XDR test coverage: 85.2% lines (up from 72.4%), 76.2% methods (up from 47.6%). Total unit tests: 3,377. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove wrapper/base class pairs for types where the wrapper only provided constructor defaults. Callers updated to pass explicit values. Eliminated wrappers: - XdrSorobanTransactionData (empty wrapper) - XdrPreconditionsV2 (defaulted optional params) - XdrMemo (VALUE_TEXT_MAX_SIZE constant already in StellarConstants) - XdrManageOfferResult (empty wrapper, no callers) - XdrFeeBumpTransactionInnerTx (2-arg constructor shortcut) - XdrFeeBumpTransaction (defaulted ext param) BASE_WRAPPER_TYPES reduced from 39 to 33. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The generator's name_overrides.rb incorrectly collapsed two structurally different XDR unions into one PHP class. The outer TransactionResult union has FEE_BUMP_INNER_SUCCESS/FAILED arms (with InnerTransactionResultPair) that the inner InnerTransactionResult union lacks. This caused fee bump transaction results to decode incorrectly, making isSuccessful() always return false for fee bump transactions. Fix: remove the collapsing override so both classes are generated separately. Add field override for consistent resultCode naming. Also fixes AssetTypePoolShare passing extra arg to union constructor (XdrLiquidityPoolParameters) which left constantProduct null. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The generator had overwritten the hand-written file, losing the forVoidCase() and forTupleCase() factory methods. Add the type to BASE_WRAPPER_TYPES so the generator produces a Base class while the wrapper preserves the factory methods. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add GitHub Actions workflow with snapshot tests, drift detection, and validation jobs for the XDR generator - Add 8 snapshot golden files covering all generator patterns (enum, struct, union, base-wrapper, extension points) - Add xdr-generate-tests Makefile target - Fix validate_generated_types.rb (broken parse call, missing MEMBER_PREFIX_STRIP support, dedup for collapsed types) - Simplify generator: extract resolve_class_info helper, consolidate 3 typedef renderers into 1, extract build_typed_arm helper, remove dead code (-97 net lines, identical output) - Fix XdrThresholds.php incorrectly deleted by xdr-clean-generated - Untrack internal working docs (bugs.md, learnings.md, progress.md) - Add README.md for the XDR generator Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generated test count increases from 1,013 to 1,115, restoring overall line coverage from 80% back to 84%. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regenerate XDR types from stellar/stellar-xdr#298 (Merge P26 XDR into curr). Adds frozen ledger key and freeze bypass config settings, new result codes, and updates TxRep config setting parsing for the new entries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces ~309 hand-written XDR type definitions with machine-generated PHP code produced by a Ruby-based code generator that reads Stellar's canonical
.xXDR definition files. Adds 133 new XDR types not previously in the SDK (SCP, overlay, bucket, ledger close meta, exporter, survey, internal types), extracts hand-maintained helper methods into 34 wrapper classes, and adds 1,013 auto-generated round-trip unit tests covering all generated types.tools/xdr-generator/(Ruby, usesxdrgengem).xdefinition files inxdr/fromstellar/stellar-xdrSoneso/StellarSDK/Xdr/What changed
encode(),decode(),toBase64Xdr(), andfromBase64Xdr()methods. All types are produced from the canonical.xdefinitions via thexdrgengem.tools/xdr-generator/generator/generator.rbreads.xfiles via thexdrgengem and produces PHP. Override files (name_overrides.rb,field_overrides.rb,member_overrides.rb,type_overrides.rb) preserve existing SDK naming where the hand-written code diverged from XDR spec names.*Base.phpfile; the hand-maintained wrapper extends the generated base class. This separates generated encode/decode logic from SDK-specific convenience methods.xdr-generator.yml) with snapshot tests, drift detection (fails if generated files differ from committed versions), and validation against.xdefinitions.Soneso/StellarSDKTests/Unit/Xdr/Generated/covering enums, structs, unions, and typedefs — each test includes both binary encode/decode and base64 round-trip verification.decode()methods now reject unknown discriminant values withInvalidArgumentExceptioninstead of silently accepting them.Breaking changes
This PR has breaking changes. The high-level SDK APIs (operation classes, services, SEP implementations) are unchanged, with the exception listed below. The remaining breaks are in the low-level XDR layer.
High-level API
SorobanContractInfo.envInterfaceVersion replaced by two properties
SorobanContractInfo.envInterfaceVersion: intis replaced by two properties:envMetaProtocol: intandenvMetaPreRelease: int. This follows a change in the XDR spec whereXdrSCEnvMetaEntryInterfaceVersionis now a struct with twouint32fields (protocol,preRelease) instead of a singleuint64.Low-level XDR types
Most SDK consumers don't interact with XDR types directly — the SDK's operation classes, transaction builder, and service layer handle serialization internally. If your code does use XDR types, here is what changed.
XdrChangeTrustAsset / XdrTrustlineAsset no longer extend XdrAsset
Per the XDR spec,
ChangeTrustAssetandTrustLineAssetare independent unions — they are not subtypes ofAsset. The hand-written SDK hadXdrChangeTrustAsset extends XdrAssetandXdrTrustlineAsset extends XdrAsset, which is incorrect.Code that passes
XdrChangeTrustAssetorXdrTrustlineAssettoAsset::fromXdr()must use the new factory methods instead:AssetTypePoolShare::toXdr()now throws\RuntimeException. UseAssetTypePoolShare::toXdrChangeTrustAsset()instead.Union constructor changes
Generated union types now take only the discriminant in their constructor. Associated values are set via public properties after construction:
Bugs fixed
The generator found and automatically fixed bugs across that were present in the previous, hand-written XDR type definitions.
Missing enum constants
XdrLiquidityPoolDepositResultCode— missing 3 constants (LINE_FULL,BAD_PRICE,POOL_FULL)XdrOperationResultCode— missing constantTOO_MANY_SPONSORINGXdrSetOptionsResultCode— missing constantAUTH_REVOCABLE_REQUIREDXdrContractCostType— missing 25 BLS12-381 constantsIncorrect encode output
XdrInvokeHostFunctionResult— double concatenation ($bytes .= $bytes .= ...) doubled the encoded output for SUCCESS armsXdrSCError— 9 union arms incorrectly treated as void, silently dropping theSCErrorCodevalueXdrSorobanTransactionMeta— copy-paste bug:diagnosticEventsarray encoded$this->eventsinstead of$this->diagnosticEventsXdrInnerTransactionResultResult— encode() always wrote operations array regardless of result codeOther
XdrInnerTransactionResultPair—$$transactionHashBytesvariable-variable typo;fromBase64Xdr()returned wrong typeNew infrastructure
Makefilexdr-generate,xdr-clean-generated,xdr-clean-all,xdr-update,xdr-compare,xdr-generator-test,xdr-generator-update-snapshots,xdr-validate,xdr-generate-tests.github/workflows/xdr-generator.yml.gitattributeslinguist-generated=true, excludes wrappers and infrastructuretools/xdr-generator/test/generator_snapshot_test.rbtools/xdr-generator/test/generate_tests.rbtools/xdr-generator/test/validate_generated_types.rb.xdefinitions (field names, enum constants, union arms)Test plan
./vendor/bin/phpunit --testsuite unit— 3,374 tests pass (including 1,013 auto-generated XDR round-trip tests)make xdr-generator-test— 11/11 snapshot tests passmake xdr-validate— 434 types validated, 0 errorsmake xdr-update— clean regeneration matches committed files