Skip to content

Commit 823f06e

Browse files
committed
Generic protocol framework
1 parent 88d6def commit 823f06e

24 files changed

+3895
-1616
lines changed

app/models/generic_protocol_extractor.rb

Lines changed: 363 additions & 87 deletions
Large diffs are not rendered by default.

app/models/protocol_extractor.rb

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,6 @@ class ProtocolExtractor
2222
\}\z
2323
/x.freeze
2424

25-
# Generic JSON protocol - has p and op fields
26-
# More flexible format for new protocols
27-
GENERIC_PROTOCOL_REGEX = /\A
28-
data:,\{
29-
(?:.*?)
30-
"p":"([a-z0-9\-_]+)",
31-
(?:.*?)
32-
"op":"([a-z0-9\-_]+)"
33-
(?:.*?)
34-
\}
35-
\z/x.freeze
36-
3725
# Default return values for different scenarios
3826
TOKEN_DEFAULT_PARAMS = TokenParamsExtractor::DEFAULT_PARAMS
3927
GENERIC_DEFAULT_PARAMS = GenericProtocolExtractor::DEFAULT_PARAMS
@@ -66,8 +54,19 @@ def self.matches_token_protocol?(content_uri)
6654
end
6755

6856
def self.matches_generic_protocol?(content_uri)
69-
# Check if it has p and op fields (any protocol)
70-
content_uri.match?(GENERIC_PROTOCOL_REGEX)
57+
# Check if it has p and op fields by parsing JSON
58+
# This supports multi-line JSON and is more reliable than regex
59+
begin
60+
json_str = content_uri[6..] # Remove 'data:,'
61+
data = JSON.parse(json_str, max_nesting: 10)
62+
63+
# Must be an object with p and op fields
64+
data.is_a?(Hash) &&
65+
data.key?('p') && data['p'].is_a?(String) &&
66+
data.key?('op') && data['op'].is_a?(String)
67+
rescue JSON::ParserError
68+
false
69+
end
7170
end
7271

7372
def self.extract_token_protocol(content_uri)
@@ -166,12 +165,18 @@ def self.encode_token_data(params)
166165
op, _protocol, tick, val1, val2, val3 = params
167166

168167
# Encode based on operation type (operation is passed separately now)
168+
# Use tuple encoding for struct compatibility with contracts
169+
# IMPORTANT: Field order must match TokenManager's struct definitions!
169170
if op == 'deploy'.b
170-
# Deploy: tick, max, lim
171-
Eth::Abi.encode(['string', 'uint256', 'uint256'], [tick, val1, val2])
171+
# DeployOperation struct: tick, maxSupply, mintAmount
172+
# Our params: tick, max (val1), lim (val2)
173+
# So: tick, maxSupply=val1, mintAmount=val2
174+
Eth::Abi.encode(['(string,uint256,uint256)'], [[tick.b, val1, val2]])
172175
elsif op == 'mint'.b
173-
# Mint: tick, id, amt
174-
Eth::Abi.encode(['string', 'uint256', 'uint256'], [tick, val1, val3])
176+
# MintOperation struct: tick, id, amount
177+
# Our params: tick, id (val1), amt (val3)
178+
# So: tick, id=val1, amount=val3
179+
Eth::Abi.encode(['(string,uint256,uint256)'], [[tick.b, val1, val3]])
175180
else
176181
''.b
177182
end

contracts/script/L2Genesis.s.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,20 @@ contract GenesisEthscriptions is Ethscriptions {
5555
creator: creator,
5656
initialOwner: params.initialOwner,
5757
previousOwner: creator,
58-
ethscriptionNumber: totalSupply,
58+
ethscriptionNumber: totalSupply(),
5959
createdAt: createdAt,
6060
l1BlockNumber: l1BlockNumber,
6161
l2BlockNumber: 0, // Genesis ethscriptions have no L2 block
6262
l1BlockHash: l1BlockHash
6363
});
6464

6565
// Use ethscription number as token ID
66-
tokenId = totalSupply;
66+
tokenId = totalSupply();
6767

6868
// Store the mapping from token ID to transaction hash
6969
tokenIdToTransactionHash[tokenId] = params.transactionHash;
7070

71-
totalSupply++;
71+
// Token count is automatically tracked by enumerable's _update
7272

7373
// If initial owner is zero (burned), mint to creator then burn
7474
if (params.initialOwner == address(0)) {

0 commit comments

Comments
 (0)