diff --git a/Makefile b/Makefile index dee736475d..d4d94ea046 100644 --- a/Makefile +++ b/Makefile @@ -17,8 +17,8 @@ xdr/Stellar-exporter.x XDRGEN_COMMIT=b423e1da9504239fb3136cbcc5f9beeb37795837 -# Bumped to stellar-xdr@8521b97 for Protocol 28 (CAP-0083). -XDR_COMMIT=8521b97ba0e8e71d746bf3bd73def92110e6a21f +# Bumped to stellar-xdr@787382e for Protocol 28 (CAP-0084). +XDR_COMMIT=787382ef2099cca168ca1cb282730d6b7b9e2f16 .PHONY: xdr xdr-clean xdr-update @@ -68,7 +68,7 @@ xdr/xdr_generated.go: $(XDRS) # Optional comma-separated features for #ifdef resolution in the XDR files. # Empty = no features enabled; only unconditional definitions are emitted. -XDR_FEATURES ?= CAP_0083 +XDR_FEATURES ?= CAP_0083,CAP_0084_MUXED_CONTRACT # Generates xdr/xdr_views_generated.go via a two-step pipeline: # 1. The rust `generator-definitions-json` tool parses the .x files and diff --git a/gxdr/xdr_generated.go b/gxdr/xdr_generated.go index 4042c1d5cd..dbfca03062 100644 --- a/gxdr/xdr_generated.go +++ b/gxdr/xdr_generated.go @@ -4475,6 +4475,7 @@ const ( SC_ADDRESS_TYPE_MUXED_ACCOUNT SCAddressType = 2 SC_ADDRESS_TYPE_CLAIMABLE_BALANCE SCAddressType = 3 SC_ADDRESS_TYPE_LIQUIDITY_POOL SCAddressType = 4 + SC_ADDRESS_TYPE_MUXED_CONTRACT SCAddressType = 5 ) type MuxedEd25519Account struct { @@ -4482,6 +4483,11 @@ type MuxedEd25519Account struct { Ed25519 Uint256 } +type MuxedContract struct { + Id Uint64 + ContractId ContractID +} + type SCAddress struct { // The union discriminant Type selects among the following arms: // SC_ADDRESS_TYPE_ACCOUNT: @@ -4494,6 +4500,8 @@ type SCAddress struct { // ClaimableBalanceId() *ClaimableBalanceID // SC_ADDRESS_TYPE_LIQUIDITY_POOL: // LiquidityPoolId() *PoolID + // SC_ADDRESS_TYPE_MUXED_CONTRACT: + // MuxedContract() *MuxedContract Type SCAddressType _u interface{} } @@ -30122,6 +30130,7 @@ var _XdrNames_SCAddressType = map[int32]string{ int32(SC_ADDRESS_TYPE_MUXED_ACCOUNT): "SC_ADDRESS_TYPE_MUXED_ACCOUNT", int32(SC_ADDRESS_TYPE_CLAIMABLE_BALANCE): "SC_ADDRESS_TYPE_CLAIMABLE_BALANCE", int32(SC_ADDRESS_TYPE_LIQUIDITY_POOL): "SC_ADDRESS_TYPE_LIQUIDITY_POOL", + int32(SC_ADDRESS_TYPE_MUXED_CONTRACT): "SC_ADDRESS_TYPE_MUXED_CONTRACT", } var _XdrValues_SCAddressType = map[string]int32{ "SC_ADDRESS_TYPE_ACCOUNT": int32(SC_ADDRESS_TYPE_ACCOUNT), @@ -30129,6 +30138,7 @@ var _XdrValues_SCAddressType = map[string]int32{ "SC_ADDRESS_TYPE_MUXED_ACCOUNT": int32(SC_ADDRESS_TYPE_MUXED_ACCOUNT), "SC_ADDRESS_TYPE_CLAIMABLE_BALANCE": int32(SC_ADDRESS_TYPE_CLAIMABLE_BALANCE), "SC_ADDRESS_TYPE_LIQUIDITY_POOL": int32(SC_ADDRESS_TYPE_LIQUIDITY_POOL), + "SC_ADDRESS_TYPE_MUXED_CONTRACT": int32(SC_ADDRESS_TYPE_MUXED_CONTRACT), } func (SCAddressType) XdrEnumNames() map[int32]string { @@ -30182,12 +30192,28 @@ func (v *MuxedEd25519Account) XdrRecurse(x XDR, name string) { } func XDR_MuxedEd25519Account(v *MuxedEd25519Account) *MuxedEd25519Account { return v } +type XdrType_MuxedContract = *MuxedContract + +func (v *MuxedContract) XdrPointer() interface{} { return v } +func (MuxedContract) XdrTypeName() string { return "MuxedContract" } +func (v MuxedContract) XdrValue() interface{} { return v } +func (v *MuxedContract) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } +func (v *MuxedContract) XdrRecurse(x XDR, name string) { + if name != "" { + name = x.Sprintf("%s.", name) + } + x.Marshal(x.Sprintf("%sid", name), XDR_Uint64(&v.Id)) + x.Marshal(x.Sprintf("%scontractId", name), XDR_ContractID(&v.ContractId)) +} +func XDR_MuxedContract(v *MuxedContract) *MuxedContract { return v } + var _XdrTags_SCAddress = map[int32]bool{ XdrToI32(SC_ADDRESS_TYPE_ACCOUNT): true, XdrToI32(SC_ADDRESS_TYPE_CONTRACT): true, XdrToI32(SC_ADDRESS_TYPE_MUXED_ACCOUNT): true, XdrToI32(SC_ADDRESS_TYPE_CLAIMABLE_BALANCE): true, XdrToI32(SC_ADDRESS_TYPE_LIQUIDITY_POOL): true, + XdrToI32(SC_ADDRESS_TYPE_MUXED_CONTRACT): true, } func (_ SCAddress) XdrValidTags() map[int32]bool { @@ -30268,9 +30294,24 @@ func (u *SCAddress) LiquidityPoolId() *PoolID { return nil } } +func (u *SCAddress) MuxedContract() *MuxedContract { + switch u.Type { + case SC_ADDRESS_TYPE_MUXED_CONTRACT: + if v, ok := u._u.(*MuxedContract); ok { + return v + } else { + var zero MuxedContract + u._u = &zero + return &zero + } + default: + XdrPanic("SCAddress.MuxedContract accessed when Type == %v", u.Type) + return nil + } +} func (u SCAddress) XdrValid() bool { switch u.Type { - case SC_ADDRESS_TYPE_ACCOUNT, SC_ADDRESS_TYPE_CONTRACT, SC_ADDRESS_TYPE_MUXED_ACCOUNT, SC_ADDRESS_TYPE_CLAIMABLE_BALANCE, SC_ADDRESS_TYPE_LIQUIDITY_POOL: + case SC_ADDRESS_TYPE_ACCOUNT, SC_ADDRESS_TYPE_CONTRACT, SC_ADDRESS_TYPE_MUXED_ACCOUNT, SC_ADDRESS_TYPE_CLAIMABLE_BALANCE, SC_ADDRESS_TYPE_LIQUIDITY_POOL, SC_ADDRESS_TYPE_MUXED_CONTRACT: return true } return false @@ -30293,6 +30334,8 @@ func (u *SCAddress) XdrUnionBody() XdrType { return XDR_ClaimableBalanceID(u.ClaimableBalanceId()) case SC_ADDRESS_TYPE_LIQUIDITY_POOL: return XDR_PoolID(u.LiquidityPoolId()) + case SC_ADDRESS_TYPE_MUXED_CONTRACT: + return XDR_MuxedContract(u.MuxedContract()) } return nil } @@ -30308,6 +30351,8 @@ func (u *SCAddress) XdrUnionBodyName() string { return "ClaimableBalanceId" case SC_ADDRESS_TYPE_LIQUIDITY_POOL: return "LiquidityPoolId" + case SC_ADDRESS_TYPE_MUXED_CONTRACT: + return "MuxedContract" } return "" } @@ -30339,6 +30384,9 @@ func (u *SCAddress) XdrRecurse(x XDR, name string) { case SC_ADDRESS_TYPE_LIQUIDITY_POOL: x.Marshal(x.Sprintf("%sliquidityPoolId", name), XDR_PoolID(u.LiquidityPoolId())) return + case SC_ADDRESS_TYPE_MUXED_CONTRACT: + x.Marshal(x.Sprintf("%smuxedContract", name), XDR_MuxedContract(u.MuxedContract())) + return } XdrPanic("invalid Type (%v) in SCAddress", u.Type) } diff --git a/processors/token_transfer/helpers_test.go b/processors/token_transfer/helpers_test.go new file mode 100644 index 0000000000..c26f21c887 --- /dev/null +++ b/processors/token_transfer/helpers_test.go @@ -0,0 +1,32 @@ +package token_transfer + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/stellar/go-stellar-sdk/strkey" + "github.com/stellar/go-stellar-sdk/xdr" +) + +// TestExtractAddressMuxedContract verifies that CAP-0084 muxed contract +// destinations are parsed without panicking and yield the underlying base +// contract address. The muxed id is not surfaced here; that is deferred to +// horizon's processor. +func TestExtractAddressMuxedContract(t *testing.T) { + contractID := xdr.ContractId([32]byte{1}) + val := xdr.ScVal{ + Type: xdr.ScValTypeScvAddress, + Address: &xdr.ScAddress{ + Type: xdr.ScAddressTypeScAddressTypeMuxedContract, + MuxedContract: &xdr.MuxedContract{ + Id: 99, + ContractId: contractID, + }, + }, + } + + got, err := extractAddress(val) + require.NoError(t, err) + require.Equal(t, strkey.MustEncode(strkey.VersionByteContract, contractID[:]), got) +} diff --git a/xdr/Stellar-contract.x b/xdr/Stellar-contract.x index 0e67dc3f35..527460d95e 100644 --- a/xdr/Stellar-contract.x +++ b/xdr/Stellar-contract.x @@ -183,6 +183,8 @@ enum SCAddressType SC_ADDRESS_TYPE_MUXED_ACCOUNT = 2, SC_ADDRESS_TYPE_CLAIMABLE_BALANCE = 3, SC_ADDRESS_TYPE_LIQUIDITY_POOL = 4 + , + SC_ADDRESS_TYPE_MUXED_CONTRACT = 5 }; struct MuxedEd25519Account @@ -191,6 +193,12 @@ struct MuxedEd25519Account uint256 ed25519; }; +struct MuxedContract +{ + uint64 id; + ContractID contractId; +}; + union SCAddress switch (SCAddressType type) { case SC_ADDRESS_TYPE_ACCOUNT: @@ -203,6 +211,8 @@ case SC_ADDRESS_TYPE_CLAIMABLE_BALANCE: ClaimableBalanceID claimableBalanceId; case SC_ADDRESS_TYPE_LIQUIDITY_POOL: PoolID liquidityPoolId; +case SC_ADDRESS_TYPE_MUXED_CONTRACT: + MuxedContract muxedContract; }; %struct SCVal; diff --git a/xdr/scval.go b/xdr/scval.go index 0e65132b6e..9ec49f657a 100644 --- a/xdr/scval.go +++ b/xdr/scval.go @@ -21,6 +21,13 @@ func (address ScAddress) String() (string, error) { case ScAddressTypeScAddressTypeContract: contractID := address.MustContractId() result, err = strkey.Encode(strkey.VersionByteContract, contractID[:]) + case ScAddressTypeScAddressTypeMuxedContract: + // CAP-0084 muxed contract addresses. There is not yet a strkey + // encoding for muxed contracts in this package, so we render the + // underlying base contract address (non-panicking). Surfacing the + // muxed id is deferred to horizon's processor. + contractID := address.MustMuxedContract().ContractId + result, err = strkey.Encode(strkey.VersionByteContract, contractID[:]) case ScAddressTypeScAddressTypeMuxedAccount: payload := address.MustMuxedAccount() muxed := MuxedAccount{ @@ -148,6 +155,10 @@ func (s ScAddress) Equals(o ScAddress) bool { return sAccountID.Equals(o.MustAccountId()) case ScAddressTypeScAddressTypeContract: return s.MustContractId() == o.MustContractId() + case ScAddressTypeScAddressTypeMuxedContract: + sMuxed := s.MustMuxedContract() + oMuxed := o.MustMuxedContract() + return sMuxed.Id == oMuxed.Id && sMuxed.ContractId == oMuxed.ContractId case ScAddressTypeScAddressTypeClaimableBalance: return s.MustClaimableBalanceId().MustV0() == o.MustClaimableBalanceId().MustV0() case ScAddressTypeScAddressTypeLiquidityPool: diff --git a/xdr/scval_test.go b/xdr/scval_test.go index c2b562fd2b..bc30db7740 100644 --- a/xdr/scval_test.go +++ b/xdr/scval_test.go @@ -93,6 +93,18 @@ func TestScAddressString(t *testing.T) { }, expected: strkey.MustEncode(strkey.VersionByteContract, contractID[:]), }, + { + // CAP-0084: muxed contract renders the underlying base contract + // address; the muxed id is not yet surfaced in the string form. + address: ScAddress{ + Type: ScAddressTypeScAddressTypeMuxedContract, + MuxedContract: &MuxedContract{ + Id: 42, + ContractId: ContractId{1}, + }, + }, + expected: strkey.MustEncode(strkey.VersionByteContract, contractID[:]), + }, { address: ScAddress{ Type: ScAddressTypeScAddressTypeClaimableBalance, diff --git a/xdr/xdr_commit_generated.txt b/xdr/xdr_commit_generated.txt index 7b8ee90d8f..e728393c62 100644 --- a/xdr/xdr_commit_generated.txt +++ b/xdr/xdr_commit_generated.txt @@ -1 +1 @@ -8521b97ba0e8e71d746bf3bd73def92110e6a21f \ No newline at end of file +787382ef2099cca168ca1cb282730d6b7b9e2f16 \ No newline at end of file diff --git a/xdr/xdr_generated.go b/xdr/xdr_generated.go index 9efa54df9f..af42d47efb 100644 --- a/xdr/xdr_generated.go +++ b/xdr/xdr_generated.go @@ -37,7 +37,7 @@ var XdrFilesSHA256 = map[string]string{ "xdr/Stellar-contract-env-meta.x": "75a271414d852096fea3283c63b7f2a702f2905f78fc28eb60ec7d7bd366a780", "xdr/Stellar-contract-meta.x": "f01532c11ca044e19d9f9f16fe373e9af64835da473be556b9a807ee3319ae0d", "xdr/Stellar-contract-spec.x": "7d99679155f6ce029f4f2bd8e1bf09524ef2f3e4ca8973265085cfcfdbdae987", - "xdr/Stellar-contract.x": "dce61df115c93fef5bb352beac1b504a518cb11dcb8ee029b1bb1b5f8fe52982", + "xdr/Stellar-contract.x": "13227e56bf220a629f40cdf29e3b8c2e1c92a7098d30d12c673096fcf171b5a4", "xdr/Stellar-exporter.x": "a00c83d02e8c8382e06f79a191f1fb5abd097a4bbcab8481c67467e3270e0529", "xdr/Stellar-internal.x": "227835866c1b2122d1eaf28839ba85ea7289d1cb681dda4ca619c2da3d71fe00", "xdr/Stellar-ledger-entries.x": "65a24350a69f0d1c74c0dce61a68db2a657611ad9318cb2736860fd99a2db020", @@ -18045,7 +18045,7 @@ var _ xdrType = (*DiagnosticEvent)(nil) // // transactions, this will be `0` for failed transactions. // int64 totalRefundableResourceFeeCharged; // // Amount (in stroops) that has been charged for rent. -// // This is a part of `totalRefundableResourceFeeCharged`. +// // This is a part of `totalNonRefundableResourceFeeCharged`. // int64 rentFeeCharged; // }; type SorobanTransactionMetaExtV1 struct { @@ -59055,6 +59055,8 @@ var _ xdrType = (*ContractExecutable)(nil) // SC_ADDRESS_TYPE_MUXED_ACCOUNT = 2, // SC_ADDRESS_TYPE_CLAIMABLE_BALANCE = 3, // SC_ADDRESS_TYPE_LIQUIDITY_POOL = 4 +// , +// SC_ADDRESS_TYPE_MUXED_CONTRACT = 5 // }; type ScAddressType int32 @@ -59064,6 +59066,7 @@ const ( ScAddressTypeScAddressTypeMuxedAccount ScAddressType = 2 ScAddressTypeScAddressTypeClaimableBalance ScAddressType = 3 ScAddressTypeScAddressTypeLiquidityPool ScAddressType = 4 + ScAddressTypeScAddressTypeMuxedContract ScAddressType = 5 ) var scAddressTypeMap = map[int32]string{ @@ -59072,6 +59075,7 @@ var scAddressTypeMap = map[int32]string{ 2: "ScAddressTypeScAddressTypeMuxedAccount", 3: "ScAddressTypeScAddressTypeClaimableBalance", 4: "ScAddressTypeScAddressTypeLiquidityPool", + 5: "ScAddressTypeScAddressTypeMuxedContract", } // ValidEnum validates a proposed value for this enum. Implements @@ -59218,6 +59222,81 @@ func (s MuxedEd25519Account) xdrType() {} var _ xdrType = (*MuxedEd25519Account)(nil) +// MuxedContract is an XDR Struct defines as: +// +// struct MuxedContract +// { +// uint64 id; +// ContractID contractId; +// }; +type MuxedContract struct { + Id Uint64 + ContractId ContractId +} + +// EncodeTo encodes this value using the Encoder. +func (s *MuxedContract) EncodeTo(e *xdr.Encoder) error { + var err error + if err = s.Id.EncodeTo(e); err != nil { + return err + } + if err = s.ContractId.EncodeTo(e); err != nil { + return err + } + return nil +} + +var _ decoderFrom = (*MuxedContract)(nil) + +// DecodeFrom decodes this value using the Decoder. +func (s *MuxedContract) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { + if maxDepth == 0 { + return 0, fmt.Errorf("decoding MuxedContract: %w", ErrMaxDecodingDepthReached) + } + maxDepth -= 1 + var err error + var n, nTmp int + nTmp, err = s.Id.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding Uint64: %w", err) + } + nTmp, err = s.ContractId.DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding ContractId: %w", err) + } + return n, nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (s MuxedContract) MarshalBinary() ([]byte, error) { + b := bytes.Buffer{} + e := xdr.NewEncoder(&b) + err := s.EncodeTo(e) + return b.Bytes(), err +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (s *MuxedContract) UnmarshalBinary(inp []byte) error { + r := bytes.NewReader(inp) + o := xdr.DefaultDecodeOptions + o.MaxInputLen = len(inp) + d := xdr.NewDecoderWithOptions(r, o) + _, err := s.DecodeFrom(d, o.MaxDepth) + return err +} + +var ( + _ encoding.BinaryMarshaler = (*MuxedContract)(nil) + _ encoding.BinaryUnmarshaler = (*MuxedContract)(nil) +) + +// xdrType signals that this type represents XDR values defined by this package. +func (s MuxedContract) xdrType() {} + +var _ xdrType = (*MuxedContract)(nil) + // ScAddress is an XDR Union defines as: // // union SCAddress switch (SCAddressType type) @@ -59232,6 +59311,8 @@ var _ xdrType = (*MuxedEd25519Account)(nil) // ClaimableBalanceID claimableBalanceId; // case SC_ADDRESS_TYPE_LIQUIDITY_POOL: // PoolID liquidityPoolId; +// case SC_ADDRESS_TYPE_MUXED_CONTRACT: +// MuxedContract muxedContract; // }; type ScAddress struct { Type ScAddressType @@ -59240,6 +59321,7 @@ type ScAddress struct { MuxedAccount *MuxedEd25519Account ClaimableBalanceId *ClaimableBalanceId LiquidityPoolId *PoolId + MuxedContract *MuxedContract } // SwitchFieldName returns the field name in which this union's @@ -59262,6 +59344,8 @@ func (u ScAddress) ArmForSwitch(sw int32) (string, bool) { return "ClaimableBalanceId", true case ScAddressTypeScAddressTypeLiquidityPool: return "LiquidityPoolId", true + case ScAddressTypeScAddressTypeMuxedContract: + return "MuxedContract", true } return "-", false } @@ -59305,6 +59389,13 @@ func NewScAddress(aType ScAddressType, value interface{}) (result ScAddress, err return } result.LiquidityPoolId = &tv + case ScAddressTypeScAddressTypeMuxedContract: + tv, ok := value.(MuxedContract) + if !ok { + err = errors.New("invalid value, must be MuxedContract") + return + } + result.MuxedContract = &tv } return } @@ -59434,6 +59525,31 @@ func (u ScAddress) GetLiquidityPoolId() (result PoolId, ok bool) { return } +// MustMuxedContract retrieves the MuxedContract value from the union, +// panicing if the value is not set. +func (u ScAddress) MustMuxedContract() MuxedContract { + val, ok := u.GetMuxedContract() + + if !ok { + panic("arm MuxedContract is not set") + } + + return val +} + +// GetMuxedContract retrieves the MuxedContract value from the union, +// returning ok if the union's switch indicated the value is valid. +func (u ScAddress) GetMuxedContract() (result MuxedContract, ok bool) { + armName, _ := u.ArmForSwitch(int32(u.Type)) + + if armName == "MuxedContract" { + result = *u.MuxedContract + ok = true + } + + return +} + // EncodeTo encodes this value using the Encoder. func (u ScAddress) EncodeTo(e *xdr.Encoder) error { var err error @@ -59466,6 +59582,11 @@ func (u ScAddress) EncodeTo(e *xdr.Encoder) error { return err } return nil + case ScAddressTypeScAddressTypeMuxedContract: + if err = (*u.MuxedContract).EncodeTo(e); err != nil { + return err + } + return nil } return fmt.Errorf("Type (ScAddressType) switch value '%d' is not valid for union ScAddress", u.Type) } @@ -59541,6 +59662,17 @@ func (u *ScAddress) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { return n, fmt.Errorf("decoding PoolId: %w", err) } return n, nil + case ScAddressTypeScAddressTypeMuxedContract: + if err = xdr.TrackOutputBytesOf[MuxedContract](d); err != nil { + return n, fmt.Errorf("decoding MuxedContract: %w", err) + } + u.MuxedContract = new(MuxedContract) + nTmp, err = (*u.MuxedContract).DecodeFrom(d, maxDepth) + n += nTmp + if err != nil { + return n, fmt.Errorf("decoding MuxedContract: %w", err) + } + return n, nil } return n, fmt.Errorf("union ScAddress has invalid Type (ScAddressType) switch value '%d'", u.Type) } diff --git a/xdr/xdr_views_generated.go b/xdr/xdr_views_generated.go index 5601939766..49f27a3002 100644 --- a/xdr/xdr_views_generated.go +++ b/xdr/xdr_views_generated.go @@ -13349,7 +13349,7 @@ func (v ScAddressTypeView) Value() (ScAddressType, error) { } val := ScAddressType(int32(binary.BigEndian.Uint32(v[:4]))) switch val { - case ScAddressTypeScAddressTypeAccount, ScAddressTypeScAddressTypeContract, ScAddressTypeScAddressTypeMuxedAccount, ScAddressTypeScAddressTypeClaimableBalance, ScAddressTypeScAddressTypeLiquidityPool: + case ScAddressTypeScAddressTypeAccount, ScAddressTypeScAddressTypeContract, ScAddressTypeScAddressTypeMuxedAccount, ScAddressTypeScAddressTypeClaimableBalance, ScAddressTypeScAddressTypeLiquidityPool, ScAddressTypeScAddressTypeMuxedContract: return val, nil default: return 0, viewErrUnknownDiscriminant(0, int32(val)) @@ -13436,6 +13436,67 @@ func (v MuxedEd25519AccountView) ValidateFull() error { return val func (v MuxedEd25519AccountView) MustRaw() []byte { return must(v.Raw()) } func (v MuxedEd25519AccountView) MustCopy() MuxedEd25519AccountView { return must(v.Copy()) } +type MuxedContractView []byte + +func (v MuxedContractView) size(_ int) (int, error) { return 40, nil } +func (v MuxedContractView) Id() (Uint64View, error) { + if len(v) < 40 { + return nil, viewErrShortBuffer(0, "need 40 bytes") + } + return Uint64View(v[0:]), nil +} +func (v MuxedContractView) MustId() Uint64View { return must(v.Id()) } +func (v MuxedContractView) ContractId() (ContractIdView, error) { + if len(v) < 40 { + return nil, viewErrShortBuffer(0, "need 40 bytes") + } + off := int64(0) + off += 8 + if off > int64(len(v)) { + return nil, viewErrShortBuffer(uint32(off), "field offset exceeds data") + } + return ContractIdView(v[off:]), nil +} +func (v MuxedContractView) MustContractId() ContractIdView { return must(v.ContractId()) } +func (v MuxedContractView) valid(depth int) (int, error) { + if len(v) < 40 { + return 0, viewErrShortBuffer(0, "need 40 bytes") + } + off := int64(0) + { + sz, err := Uint64View(v[off:]).valid(depth + 1) + if err != nil { + return 0, err + } + off += int64(sz) + if off > int64(len(v)) { + return 0, viewErrShortBuffer(uint32(off), "field offset exceeds data") + } + } + { + sz, err := ContractIdView(v[off:]).valid(depth + 1) + if err != nil { + return 0, err + } + off += int64(sz) + if off > int64(len(v)) { + return 0, viewErrShortBuffer(uint32(off), "field offset exceeds data") + } + } + return int(off), nil +} + +// Raw returns the exact wire bytes for this view, trimmed from the fat slice. +func (v MuxedContractView) Raw() ([]byte, error) { return viewRaw(v) } + +// Copy returns an independent copy of this view that does not alias the original bytes. +func (v MuxedContractView) Copy() (MuxedContractView, error) { return viewCopy(v) } + +// ValidateFull checks that this view is well-formed: bounds, schema constraints, and depth limits. +func (v MuxedContractView) ValidateFull() error { return validate(v) } +func (v MuxedContractView) MustRaw() []byte { return must(v.Raw()) } +func (v MuxedContractView) MustCopy() MuxedContractView { return must(v.Copy()) } + type ScAddressView []byte func (v ScAddressView) size(depth int) (int, error) { @@ -13492,6 +13553,15 @@ func (v ScAddressView) size(depth int) (int, error) { return 0, viewErrShortBuffer(4, "arm exceeds data") } return 4 + sz, nil + case int32(ScAddressTypeScAddressTypeMuxedContract): + sz, err := MuxedContractView(v[4:]).size(depth + 1) + if err != nil { + return 0, err + } + if 4+sz > len(v) { + return 0, viewErrShortBuffer(4, "arm exceeds data") + } + return 4 + sz, nil default: return 0, viewErrUnknownDiscriminant(0, disc) } @@ -13570,6 +13640,19 @@ func (v ScAddressView) LiquidityPoolId() (PoolIdView, error) { return PoolIdView(v[4:]), nil } func (v ScAddressView) MustLiquidityPoolId() PoolIdView { return must(v.LiquidityPoolId()) } +func (v ScAddressView) MuxedContract() (MuxedContractView, error) { + if len(v) < 4 { + return nil, viewErrShortBuffer(0, "need 4 bytes for discriminant") + } + disc := int32(binary.BigEndian.Uint32(v[:4])) + switch disc { + case int32(ScAddressTypeScAddressTypeMuxedContract): + default: + return nil, viewErrWrongDiscriminant(0, disc, int32(ScAddressTypeScAddressTypeMuxedContract)) + } + return MuxedContractView(v[4:]), nil +} +func (v ScAddressView) MustMuxedContract() MuxedContractView { return must(v.MuxedContract()) } func (v ScAddressView) valid(depth int) (int, error) { if depth > maxDepth { return 0, viewErrMaxDepth(0) @@ -13624,6 +13707,15 @@ func (v ScAddressView) valid(depth int) (int, error) { return 0, viewErrShortBuffer(4, "arm exceeds data") } return 4 + sz, nil + case int32(ScAddressTypeScAddressTypeMuxedContract): + sz, err := MuxedContractView(v[4:]).valid(depth + 1) + if err != nil { + return 0, err + } + if 4+sz > len(v) { + return 0, viewErrShortBuffer(4, "arm exceeds data") + } + return 4 + sz, nil default: return 0, viewErrUnknownDiscriminant(0, disc) }