@@ -19,43 +19,120 @@ public class DelegateComponentInstruction {
1919 public TransactionInstruction Instruction { get ; set ; }
2020 }
2121
22- public static async Task < DelegateComponentInstruction > DelegateComponent ( PublicKey payer , PublicKey entity , PublicKey componentId , string seed = "" ) {
23- var account = WorldProgram . FindComponentPda ( componentId , entity , seed ) ;
24- var bufferPda = WorldProgram . FindBufferPda ( account , componentId ) ;
25- var delegationRecord = WorldProgram . FindDelegationProgramPda ( "delegation" , account ) ;
26- var delegationMetadata = WorldProgram . FindDelegationProgramPda ( "delegation-metadata" , account ) ;
27-
28- byte [ ] discriminator = new byte [ ] { 90 , 147 , 75 , 178 , 85 , 88 , 4 , 137 } ;
29- uint commitFrequencyMs = 0 ;
30- byte [ ] commitFrequencyBytes = BitConverter . GetBytes ( commitFrequencyMs ) ;
31- if ( ! BitConverter . IsLittleEndian ) Array . Reverse ( commitFrequencyBytes ) ;
32- var validator = new byte [ 1 ] ;
33- validator [ 0 ] = 0 ;
34-
35- var data = new byte [ discriminator . Length + commitFrequencyBytes . Length + validator . Length ] ;
36- Array . Copy ( discriminator , data , discriminator . Length ) ;
37- Array . Copy ( commitFrequencyBytes , 0 , data , discriminator . Length , commitFrequencyBytes . Length ) ;
38- Array . Copy ( validator , 0 , data , discriminator . Length + commitFrequencyBytes . Length , validator . Length ) ;
39-
40- TransactionInstruction instruction = new TransactionInstruction ( ) {
41- ProgramId = componentId ,
42- Keys = new List < AccountMeta > ( ) {
43- AccountMeta . ReadOnly ( payer , true ) ,
44- AccountMeta . ReadOnly ( entity , false ) ,
45- AccountMeta . Writable ( account , false ) ,
46- AccountMeta . ReadOnly ( componentId , false ) ,
47- AccountMeta . Writable ( bufferPda , false ) ,
48- AccountMeta . Writable ( delegationRecord , false ) ,
49- AccountMeta . Writable ( delegationMetadata , false ) ,
50- AccountMeta . ReadOnly ( WorldProgram . DelegationProgram , false ) ,
51- AccountMeta . ReadOnly ( SystemProgram . ProgramIdKey , false ) ,
52- } ,
53- Data = data ,
54- } ;
55- return new DelegateComponentInstruction ( ) {
56- Pda = WorldProgram . FindDelegationProgramPda ( seed , entity ) ,
57- Instruction = instruction ,
58- } ;
59- }
22+ public static async Task < DelegateComponentInstruction > DelegateComponent ( PublicKey payer , PublicKey entity , PublicKey componentId , string seed = "" ) {
23+ // Compute the delegated account PDA and related PDAs
24+ var account = WorldProgram . FindComponentPda ( componentId , entity , seed ) ;
25+ var bufferPda = WorldProgram . FindBufferPda ( account , componentId ) ;
26+ var delegationRecord = WorldProgram . FindDelegationProgramPda ( "delegation" , account ) ;
27+ var delegationMetadata = WorldProgram . FindDelegationProgramPda ( "delegation-metadata" , account ) ;
28+
29+ // Build instruction data per TS beet struct:
30+ // discriminator[8] + commitFrequencyMs[u32 le] + validator[COption<Pubkey>] + pdaSeeds[Vec<Bytes>]
31+ byte [ ] discriminator = new byte [ ] { 90 , 147 , 75 , 178 , 85 , 88 , 4 , 137 } ;
32+ uint commitFrequencyMs = 0 ;
33+ byte [ ] commitFrequencyBytes = BitConverter . GetBytes ( commitFrequencyMs ) ; // little-endian on most platforms
34+ byte [ ] validatorNoneTag = new byte [ ] { 0 } ; // COption None
35+
36+ // pdaSeeds = [seedBytes, entityPubkeyBytes]
37+ var seedBytes = Encoding . UTF8 . GetBytes ( seed ?? "" ) ;
38+ var entityBytes = entity . KeyBytes ;
39+ byte [ ] pdaSeeds = BuildVecOfBytes ( new byte [ ] [ ] { seedBytes , entityBytes } ) ;
40+
41+ var data = Concat ( discriminator , commitFrequencyBytes , validatorNoneTag , pdaSeeds ) ;
42+
43+ TransactionInstruction instruction = new TransactionInstruction ( ) {
44+ ProgramId = componentId ,
45+ Keys = new List < AccountMeta > ( ) {
46+ AccountMeta . ReadOnly ( payer , true ) ,
47+ AccountMeta . ReadOnly ( entity , false ) ,
48+ AccountMeta . Writable ( account , false ) ,
49+ AccountMeta . ReadOnly ( componentId , false ) ,
50+ AccountMeta . Writable ( bufferPda , false ) ,
51+ AccountMeta . Writable ( delegationRecord , false ) ,
52+ AccountMeta . Writable ( delegationMetadata , false ) ,
53+ AccountMeta . ReadOnly ( WorldProgram . DelegationProgram , false ) ,
54+ AccountMeta . ReadOnly ( SystemProgram . ProgramIdKey , false ) ,
55+ } ,
56+ Data = data ,
57+ } ;
58+ return new DelegateComponentInstruction ( ) {
59+ Pda = account ,
60+ Instruction = instruction ,
61+ } ;
62+ }
63+
64+ /// <summary>
65+ /// Overload for bundled components: seed is augmented with component name.
66+ /// Mirrors TS behavior using component.seeds(seed) for PDA seeds.
67+ /// </summary>
68+ public static async Task < DelegateComponentInstruction > DelegateComponent ( PublicKey payer , PublicKey entity , Component component , string seed = "" ) {
69+ var account = WorldProgram . FindComponentPda ( component . Program , entity , component . Seeds ( seed ) ) ;
70+ var bufferPda = WorldProgram . FindBufferPda ( account , component . Program ) ;
71+ var delegationRecord = WorldProgram . FindDelegationProgramPda ( "delegation" , account ) ;
72+ var delegationMetadata = WorldProgram . FindDelegationProgramPda ( "delegation-metadata" , account ) ;
73+
74+ byte [ ] discriminator = new byte [ ] { 90 , 147 , 75 , 178 , 85 , 88 , 4 , 137 } ;
75+ uint commitFrequencyMs = 0 ;
76+ byte [ ] commitFrequencyBytes = BitConverter . GetBytes ( commitFrequencyMs ) ;
77+ byte [ ] validatorNoneTag = new byte [ ] { 0 } ;
78+
79+ var seedBytes = Encoding . UTF8 . GetBytes ( component . Seeds ( seed ) ) ;
80+ var entityBytes = entity . KeyBytes ;
81+ byte [ ] pdaSeeds = BuildVecOfBytes ( new byte [ ] [ ] { seedBytes , entityBytes } ) ;
82+
83+ var data = Concat ( discriminator , commitFrequencyBytes , validatorNoneTag , pdaSeeds ) ;
84+
85+ TransactionInstruction instruction = new TransactionInstruction ( ) {
86+ ProgramId = component . Program ,
87+ Keys = new List < AccountMeta > ( ) {
88+ AccountMeta . ReadOnly ( payer , true ) ,
89+ AccountMeta . ReadOnly ( entity , false ) ,
90+ AccountMeta . Writable ( account , false ) ,
91+ AccountMeta . ReadOnly ( component . Program , false ) ,
92+ AccountMeta . Writable ( bufferPda , false ) ,
93+ AccountMeta . Writable ( delegationRecord , false ) ,
94+ AccountMeta . Writable ( delegationMetadata , false ) ,
95+ AccountMeta . ReadOnly ( WorldProgram . DelegationProgram , false ) ,
96+ AccountMeta . ReadOnly ( SystemProgram . ProgramIdKey , false ) ,
97+ } ,
98+ Data = data ,
99+ } ;
100+ return new DelegateComponentInstruction ( ) {
101+ Pda = account ,
102+ Instruction = instruction ,
103+ } ;
104+ }
105+
106+ private static byte [ ] BuildVecOfBytes ( byte [ ] [ ] items )
107+ {
108+ // beet array encoding: u32 count, then each element as beet.bytes => u32 length + bytes
109+ var countLe = BitConverter . GetBytes ( ( uint ) items . Length ) ;
110+ if ( ! BitConverter . IsLittleEndian ) Array . Reverse ( countLe ) ;
111+ List < byte > result = new List < byte > ( 4 ) ;
112+ result . AddRange ( countLe ) ;
113+ foreach ( var item in items )
114+ {
115+ var lenLe = BitConverter . GetBytes ( ( uint ) ( item ? . Length ?? 0 ) ) ;
116+ if ( ! BitConverter . IsLittleEndian ) Array . Reverse ( lenLe ) ;
117+ result . AddRange ( lenLe ) ;
118+ if ( item != null && item . Length > 0 )
119+ result . AddRange ( item ) ;
120+ }
121+ return result . ToArray ( ) ;
122+ }
123+
124+ private static byte [ ] Concat ( params byte [ ] [ ] arrays )
125+ {
126+ int total = 0 ;
127+ foreach ( var a in arrays ) total += a . Length ;
128+ var buf = new byte [ total ] ;
129+ int offset = 0 ;
130+ foreach ( var a in arrays )
131+ {
132+ Buffer . BlockCopy ( a , 0 , buf , offset , a . Length ) ;
133+ offset += a . Length ;
134+ }
135+ return buf ;
136+ }
60137 }
61138}
0 commit comments