@@ -17,8 +17,7 @@ class EthscriptionTransaction < T::Struct
1717 prop :content_uri , T . nilable ( String )
1818
1919 # Transfer operation fields
20- prop :ethscription_id , T . nilable ( String )
21- prop :transfer_ids , T . nilable ( T ::Array [ String ] )
20+ prop :transfer_ids , T . nilable ( T ::Array [ String ] ) # Always an array, even for single transfers
2221 prop :transfer_from_address , T . nilable ( String )
2322 prop :transfer_to_address , T . nilable ( String )
2423 prop :enforced_previous_owner , T . nilable ( String )
@@ -38,14 +37,16 @@ class EthscriptionTransaction < T::Struct
3837 TO_ADDRESS = SysConfig ::ETHSCRIPTIONS_ADDRESS
3938
4039 # Factory method for create operations
41- def self . create_ethscription (
40+ def self . build_create_ethscription (
4241 eth_transaction :,
4342 creator :,
4443 initial_owner :,
4544 content_uri :,
4645 source_type :,
4746 source_index :
4847 )
48+ return unless DataUri . valid? ( content_uri )
49+
4950 new (
5051 from_address : Address20 . from_hex ( creator . is_a? ( String ) ? creator : creator . to_hex ) ,
5152 eth_transaction : eth_transaction ,
@@ -58,22 +59,26 @@ def self.create_ethscription(
5859 )
5960 end
6061
61- # Factory method for transfer operations
62- def self . transfer_ethscription (
62+ # Transfer factory - handles single, multiple, and previous owner cases
63+ def self . build_transfer (
6364 eth_transaction :,
6465 from_address :,
6566 to_address :,
66- ethscription_id :,
67- enforced_previous_owner : nil ,
6867 source_type :,
69- source_index :
68+ source_index :,
69+ ethscription_ids :, # Can be a single ID or an array of IDs
70+ enforced_previous_owner : nil
7071 )
72+ # Normalize to array - accept either single ID or array of IDs
73+ ids = Array . wrap ( ethscription_ids )
74+
75+ # Determine operation type
7176 operation_type = enforced_previous_owner ? 'transfer_with_previous_owner' : 'transfer'
7277
7378 new (
7479 from_address : Address20 . from_hex ( from_address . is_a? ( String ) ? from_address : from_address . to_hex ) ,
7580 eth_transaction : eth_transaction ,
76- ethscription_id : ethscription_id ,
81+ transfer_ids : ids , # Always use array
7782 transfer_from_address : from_address ,
7883 transfer_to_address : to_address ,
7984 enforced_previous_owner : enforced_previous_owner ,
@@ -83,35 +88,14 @@ def self.transfer_ethscription(
8388 )
8489 end
8590
86- # Factory method for transferMultipleEthscriptions (inputs only)
87- def self . transfer_multiple_ethscriptions (
88- eth_transaction :,
89- from_address :,
90- to_address :,
91- ethscription_ids :,
92- source_type :,
93- source_index :
94- )
95- new (
96- from_address : Address20 . from_hex ( from_address . is_a? ( String ) ? from_address : from_address . to_hex ) ,
97- eth_transaction : eth_transaction ,
98- transfer_ids : ethscription_ids ,
99- transfer_from_address : from_address ,
100- transfer_to_address : to_address ,
101- source_type : source_type &.to_sym ,
102- source_index : source_index ,
103- ethscription_operation : 'transfer'
104- )
105- end
106-
10791 # Get function selector for this operation
10892 def function_selector
10993 function_signature = case ethscription_operation
11094 when 'create'
11195 'createEthscription((bytes32,bytes32,address,bytes,string,bool,(string,string,bytes)))'
11296 when 'transfer'
113- if transfer_ids && transfer_ids . any?
114- 'transferMultipleEthscriptions( bytes32[],address )'
97+ if transfer_ids . length > 1
98+ 'transferEthscriptions(address, bytes32[])'
11599 else
116100 'transferEthscription(address,bytes32)'
117101 end
@@ -145,34 +129,6 @@ def source_hash
145129 Hash32 . from_bin ( bin_val )
146130 end
147131
148- def valid_create?
149- content_uri . present? &&
150- creator . present? &&
151- initial_owner . present? &&
152- DataUri . valid? ( content_uri )
153- end
154-
155- def valid_transfer?
156- # Basic field validation - if we extracted the data properly, ABI encoding should work
157- case ethscription_operation
158- when 'transfer'
159- if transfer_ids
160- # Multiple transfer (input-based)
161- transfer_ids . is_a? ( Array ) && transfer_ids . any?
162- else
163- # Single transfer (event-based)
164- ethscription_id . present?
165- end
166- when 'transfer_with_previous_owner'
167- # Always single transfer (event-based only)
168- ethscription_id . present?
169- else
170- false
171- end &&
172- transfer_from_address . present? &&
173- transfer_to_address . present?
174- end
175-
176132 public
177133
178134 # Dynamic input method - builds calldata on demand
@@ -181,7 +137,7 @@ def input
181137 when 'create'
182138 ByteString . from_bin ( build_create_calldata )
183139 when 'transfer'
184- if transfer_ids && transfer_ids . any?
140+ if transfer_ids . length > 1
185141 ByteString . from_bin ( build_transfer_multiple_calldata )
186142 else
187143 ByteString . from_bin ( build_transfer_calldata )
@@ -267,7 +223,7 @@ def build_transfer_calldata
267223
268224 # Convert to binary for ABI
269225 to_bin = address_to_bin ( transfer_to_address )
270- id_bin = hex_to_bin ( ethscription_id )
226+ id_bin = hex_to_bin ( transfer_ids . first )
271227
272228 encoded = Eth ::Abi . encode ( [ 'address' , 'bytes32' ] , [ to_bin , id_bin ] )
273229
@@ -281,7 +237,7 @@ def build_transfer_with_previous_owner_calldata
281237
282238 # Convert to binary for ABI
283239 to_bin = address_to_bin ( transfer_to_address )
284- id_bin = hex_to_bin ( ethscription_id )
240+ id_bin = hex_to_bin ( transfer_ids . first )
285241 prev_bin = address_to_bin ( enforced_previous_owner )
286242
287243 encoded = Eth ::Abi . encode ( [ 'address' , 'bytes32' , 'address' ] , [ to_bin , id_bin , prev_bin ] )
@@ -294,10 +250,10 @@ def build_transfer_multiple_calldata
294250 # Get function selector as binary
295251 function_sig = function_selector . b
296252
297- ids_bin = ( transfer_ids || [ ] ) . map { |id | hex_to_bin ( id ) }
298253 to_bin = address_to_bin ( transfer_to_address )
254+ ids_bin = transfer_ids . map { |id | hex_to_bin ( id ) }
299255
300- encoded = Eth ::Abi . encode ( [ 'bytes32[] ' , 'address ' ] , [ ids_bin , to_bin ] )
256+ encoded = Eth ::Abi . encode ( [ 'address ' , 'bytes32[] ' ] , [ to_bin , ids_bin ] )
301257
302258 ( function_sig + encoded ) . b
303259 end
0 commit comments