synthpunks 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a0c5233aa985d25b010831dca85d14e481489665af2e69f428959d4db3a56228
4
+ data.tar.gz: 6f1e5ee50bb527fcdc4baa1e82673885a1883d3dc06b982d3c9f018f58045899
5
+ SHA512:
6
+ metadata.gz: 90b18b54a84d472b62c0694389ca633b948f0ac45e5f63219f08e7ce63f0994542930e29ad86c6d1a97ae1483d10995c9603aa1fc7c8212d158c139fad5d823d
7
+ data.tar.gz: b0e77cb3d73d74a124628ea7da1af8f63c9ed5f5e595dbdffbf1a126e4bc29971236f3a7443006b081a2fbac7efeddbecbb2be49047a6abdf61f1706670f16fd
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.0.1 / 2022-12-06
2
+
3
+ * Everything is new. First release
data/Manifest.txt ADDED
@@ -0,0 +1,10 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ config/spritesheet.json
6
+ config/spritesheet.png
7
+ lib/synthpunks.rb
8
+ lib/synthpunks/contract.rb
9
+ lib/synthpunks/image.rb
10
+ lib/synthpunks/version.rb
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Synth(etic) Punks - (Free Unlimited) 24×24 Pixel Punks For Everyone
2
+
3
+
4
+ synthpunks - (free unlimited) 24×24 pixel punks for everyone - yes, you can - generate / claim your own synth(etic) punks ("off-blockchain") for your own (ethereum) account 40-hexdigit addresses e.g. 0x054f3b6eadc9631ccd60246054fdb0fcfe99b322; incl. 2x/4x/8x zoom for bigger sizes
5
+
6
+
7
+ * home :: [github.com/cryptopunksnotdead/cryptopunks](https://github.com/cryptopunksnotdead/cryptopunks)
8
+ * bugs :: [github.com/cryptopunksnotdead/cryptopunks/issues](https://github.com/cryptopunksnotdead/cryptopunks/issues)
9
+ * gem :: [rubygems.org/gems/synthpunks](https://rubygems.org/gems/synthpunks)
10
+ * rdoc :: [rubydoc.info/gems/synthpunks](http://rubydoc.info/gems/synthpunks)
11
+
12
+
13
+
14
+ ## Usage
15
+
16
+ ...
17
+
18
+
19
+
20
+ ## License
21
+
22
+ The scripts are dedicated to the public domain.
23
+ Use it as you please with no restrictions whatsoever.
24
+
25
+
26
+ ## Questions? Comments?
27
+
28
+ Post them on the [D.I.Y. Punk (Pixel) Art reddit](https://old.reddit.com/r/DIYPunkArt). Thanks.
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require 'hoe'
2
+ require './lib/synthpunks/version.rb'
3
+
4
+ ###
5
+ # hack/ quick fix for broken intuit_values - overwrite with dummy
6
+ class Hoe
7
+ def intuit_values( input ); end
8
+ end
9
+
10
+
11
+
12
+ Hoe.spec 'synthpunks' do
13
+
14
+ self.version = Pixelart::Module::Synthpunks::VERSION
15
+
16
+ self.summary = 'synthpunks - (free unlimited) 24×24 pixel punks for everyone - yes, you can - generate / claim your own synth(etic) punks ("off-blockchain") for your own (ethereum) account 40-hexdigit addresses e.g. 0x054f3b6eadc9631ccd60246054fdb0fcfe99b322; incl. 2x/4x/8x zoom for bigger sizes'
17
+ self.description = summary
18
+
19
+ self.urls = { home: 'https://github.com/cryptopunksnotdead/cryptopunks' }
20
+
21
+ self.author = 'Gerald Bauer'
22
+ self.email = 'wwwmake@googlegroups.com'
23
+
24
+ # switch extension to .markdown for gihub formatting
25
+ self.readme_file = 'README.md'
26
+ self.history_file = 'CHANGELOG.md'
27
+
28
+ self.extra_deps = [
29
+ ['pixelart', '>= 1.3.6'],
30
+ ['etherlite', '>= 0.3.1'],
31
+ ]
32
+
33
+ self.licenses = ['Public Domain']
34
+
35
+ self.spec_extras = {
36
+ required_ruby_version: '>= 2.3'
37
+ }
38
+
39
+ end
@@ -0,0 +1 @@
1
+ {"attributes": [[0, "Human 1", "m", "l", "base"], [1, "Human 2", "m", "l", "base"], [2, "Human 3", "m", "l", "base"], [3, "Human 4", "m", "l", "base"], [4, "Zombie", "m", "l", "base"], [5, "Ape", "m", "l", "base"], [6, "Alien", "m", "l", "base"], [7, "Human Female 1", "f", "s", "base"], [8, "Human Female 2", "f", "s", "base"], [9, "Human Female 3", "f", "s", "base"], [10, "Human Female 4", "f", "s", "base"], [11, "Mole", "m", "l", "cheeks"], [12, "Rosy Cheeks", "m", "l", "cheeks"], [13, "Spots", "m", "l", "cheeks"], [14, "Clown Nose", "u", "l", "cheeks"], [15, "Mole", "f", "s", "cheeks"], [16, "Rosy Cheeks", "f", "s", "cheeks"], [17, "Spots", "f", "s", "cheeks"], [18, "Clown Nose", "f", "s", "cheeks"], [19, "Buck Teeth", "m", "l", "mouth"], [20, "Frown", "m", "l", "mouth"], [21, "Smile", "m", "l", "mouth"], [22, "Black Lipstick", "f", "u", "mouth"], [23, "Hot Lipstick", "f", "u", "mouth"], [24, "Purple Lipstick", "f", "u", "mouth"], [25, "Gold Chain", "m", "l", "neck"], [26, "Silver Chain", "m", "l", "neck"], [27, "Choker", "f", "u", "neck"], [28, "Gold Chain", "f", "u", "neck"], [29, "Silver Chain", "f", "u", "neck"], [30, "Big Beard", "m", "l", "beard"], [31, "Chinstrap", "m", "l", "beard"], [32, "Front Beard", "m", "l", "beard"], [33, "Front Beard Dark", "m", "l", "beard"], [34, "Goat", "m", "l", "beard"], [35, "Handlebars", "m", "l", "beard"], [36, "Luxurious Beard", "m", "l", "beard"], [37, "Mustache", "m", "l", "beard"], [38, "Muttonchops", "m", "l", "beard"], [39, "Normal Beard", "m", "l", "beard"], [40, "Normal Beard Black", "m", "l", "beard"], [41, "Shadow Beard", "m", "l", "beard"], [42, "Bandana", "m", "l", "headAccessory"], [43, "Beanie", "m", "l", "headAccessory"], [44, "Cap Forward", "u", "l", "headAccessory"], [45, "Cowboy Hat", "m", "l", "headAccessory"], [46, "Do-rag", "m", "l", "headAccessory"], [47, "Fedora", "m", "l", "headAccessory"], [48, "Headband", "u", "l", "headAccessory"], [49, "Hoodie", "m", "l", "headAccessory"], [50, "Knitted Cap", "u", "l", "headAccessory"], [51, "Police Cap", "m", "l", "headAccessory"], [52, "Top Hat", "m", "l", "headAccessory"], [53, "Cap", "u", "l", "headAccessory"], [54, "Crazy Hair", "m", "l", "headAccessory"], [55, "Frumpy Hair", "m", "l", "headAccessory"], [56, "Messy Hair", "u", "l", "headAccessory"], [57, "Mohawk", "u", "l", "headAccessory"], [58, "Mohawk Dark", "u", "l", "headAccessory"], [59, "Mohawk Thin", "u", "l", "headAccessory"], [60, "Peak Spike", "m", "l", "headAccessory"], [61, "Purple Hair", "m", "l", "headAccessory"], [62, "Shaved Head", "m", "l", "headAccessory"], [63, "Stringy Hair", "m", "l", "headAccessory"], [64, "Vampire Hair", "m", "l", "headAccessory"], [65, "Wild Hair", "m", "l", "headAccessory"], [66, "Clown Hair Green", "m", "l", "headAccessory"], [67, "Bandana", "f", "s", "headAccessory"], [68, "Beanie", "f", "s", "headAccessory"], [69, "Cap Forward", "f", "s", "headAccessory"], [70, "Cowboy Hat", "f", "s", "headAccessory"], [71, "Do-rag", "f", "s", "headAccessory"], [72, "Fedora", "f", "s", "headAccessory"], [73, "Headband", "f", "s", "headAccessory"], [74, "Hoodie", "f", "s", "headAccessory"], [75, "Knitted Cap", "f", "s", "headAccessory"], [76, "Pilot Helmet", "f", "s", "headAccessory"], [77, "Police Cap", "f", "s", "headAccessory"], [78, "Tassle Hat", "f", "s", "headAccessory"], [79, "Tiara", "f", "s", "headAccessory"], [80, "Top Hat", "f", "s", "headAccessory"], [81, "Cap", "f", "s", "headAccessory"], [82, "Blonde Short", "f", "s", "headAccessory"], [83, "Crazy Hair", "f", "s", "headAccessory"], [84, "Dark Hair", "f", "s", "headAccessory"], [85, "Frumpy Hair", "f", "s", "headAccessory"], [86, "Half Shaved", "f", "s", "headAccessory"], [87, "Messy Hair", "f", "s", "headAccessory"], [88, "Mohawk", "f", "s", "headAccessory"], [89, "Mohawk Dark", "f", "s", "headAccessory"], [90, "Mohawk Thin", "f", "s", "headAccessory"], [91, "Orange Side", "f", "s", "headAccessory"], [92, "Pigtails", "f", "s", "headAccessory"], [93, "Pink With Hat", "f", "s", "headAccessory"], [94, "Purple Hair", "f", "s", "headAccessory"], [95, "Red Mohawk", "f", "s", "headAccessory"], [96, "Shaved Head", "f", "s", "headAccessory"], [97, "Straight Hair", "f", "s", "headAccessory"], [98, "Straight Hair Blonde", "f", "s", "headAccessory"], [99, "Straight Hair Dark", "f", "s", "headAccessory"], [100, "Stringy Hair", "f", "s", "headAccessory"], [101, "Wild Blonde", "f", "s", "headAccessory"], [102, "Wild Hair", "f", "s", "headAccessory"], [103, "Wild White Hair", "f", "s", "headAccessory"], [104, "Blonde Bob", "f", "s", "headAccessory"], [105, "Clown Hair Green", "f", "s", "headAccessory"], [106, "Cigarette", "u", "l", "mouthAccessory"], [107, "Medical Mask", "u", "l", "mouthAccessory"], [108, "Pipe", "u", "l", "mouthAccessory"], [109, "Vape", "u", "l", "mouthAccessory"], [110, "Cigarette", "f", "s", "mouthAccessory"], [111, "Medical Mask", "f", "s", "mouthAccessory"], [112, "Pipe", "f", "s", "mouthAccessory"], [113, "Vape", "f", "s", "mouthAccessory"], [114, "Eyebrows", "u", "l", "eyes"], [115, "3D Glasses", "u", "l", "eyes"], [116, "Big Shades", "u", "l", "eyes"], [117, "Classic Shades", "u", "l", "eyes"], [118, "Eye Mask", "u", "l", "eyes"], [119, "Eye Patch", "u", "l", "eyes"], [120, "Horned Rim Glasses", "u", "l", "eyes"], [121, "Nerd Glasses", "u", "l", "eyes"], [122, "Regular Shades", "u", "l", "eyes"], [123, "Small Shades", "u", "l", "eyes"], [124, "VR", "u", "l", "eyes"], [125, "Clown Eyes Blue", "u", "l", "eyes"], [126, "Clown Eyes Green", "u", "l", "eyes"], [127, "3D Glasses", "f", "s", "eyes"], [128, "Big Shades", "f", "s", "eyes"], [129, "Classic Shades", "f", "s", "eyes"], [130, "Eye Mask", "f", "s", "eyes"], [131, "Eye Patch", "f", "s", "eyes"], [132, "Horned Rim Glasses", "f", "s", "eyes"], [133, "Nerd Glasses", "f", "s", "eyes"], [134, "Regular Shades", "f", "s", "eyes"], [135, "Small Shades", "f", "s", "eyes"], [136, "VR", "f", "s", "eyes"], [137, "Welding Goggles", "f", "s", "eyes"], [138, "Blue Eye Shadow", "f", "s", "eyes"], [139, "Green Eye Shadow", "f", "s", "eyes"], [140, "Clown Eyes Blue", "f", "s", "eyes"], [141, "Clown Eyes Green", "f", "s", "eyes"], [142, "Earring", "u", "l", "ears"], [143, "Earring", "f", "s", "ears"]], "ranges": {"base": [0, 7, 7, 11], "eyes": [114, 127, 127, 142], "cheeks": [11, 15, 15, 19], "ears": [142, 143, 143, 144], "mouth": [19, 22, 22, 25], "mouthAccessory": [106, 110, 110, 114], "neck": [25, 27, 27, 30], "beard": [30, 42, 42, 42], "headAccessory": [42, 67, 67, 106]}, "render_order": ["base", "cheeks", "mouth", "neck", "beard", "headAccessory", "mouthAccessory", "eyes", "ears"]}
Binary file
@@ -0,0 +1,263 @@
1
+
2
+
3
+ module Synthpunks
4
+
5
+ SPRITESHEET = Pixelart::ImageComposite.read( "#{Pixelart::Module::Synthpunks.root}/config/spritesheet.png",
6
+ width: 24, height: 24 )
7
+
8
+ SPRITESHEET_ATTRIBUTES, SPRITESHEET_RANGES = begin
9
+ ## build from spritesheet.json
10
+ config = read_json( "#{Pixelart::Module::Synthpunks.root}/config/spritesheet.json" )
11
+
12
+ attributes = []
13
+ config[ 'attributes' ].each do |rec|
14
+ attributes << rec[1] ## get attribute name
15
+ end
16
+
17
+ ranges = []
18
+ config[ 'render_order'].each do |key|
19
+ values = config[ 'ranges'][key]
20
+ ## note: use exclusive (three dot...) ranges !!!
21
+ ## e.g. 42...42 - range.size == 0 that is, MUST equal 0 !!!
22
+ ranges << [(values[0]...values[1]),
23
+ (values[2]...values[3])]
24
+ end
25
+
26
+ [attributes, ranges]
27
+ end
28
+
29
+ =begin
30
+ ## note: use exclusive (three dot...) ranges !!!
31
+ SPRITESHEET_RANGES = [
32
+ [(0...7), (7...11)], ## base archetypes (male / female)
33
+ [(11...15), (15...19)],
34
+ [(19...22), (22...25)],
35
+ [(25...27), (27...30)],
36
+ [(30...42), (42...42)],
37
+ [(42...67), (67...106)],
38
+ [(106...110), (110...114)],
39
+ [(114...127), (127...142)],
40
+ [(142...143), (143...144)]
41
+ ]
42
+
43
+ "ranges":
44
+ {"base": [0, 7, 7, 11],
45
+ "cheeks": [11, 15, 15, 19],
46
+ "mouth": [19, 22, 22, 25],
47
+ "neck": [25, 27, 27, 30],
48
+ "beard": [30, 42, 42, 42],
49
+ "headAccessory": [42, 67, 67, 106],
50
+ "mouthAccessory": [106, 110, 110, 114],
51
+ "eyes": [114, 127, 127, 142],
52
+ "ears": [142, 143, 143, 144]},
53
+ "render_order": ["base", "cheeks", "mouth",
54
+ "neck", "beard", "headAccessory",
55
+ "mouthAccessory", "eyes", "ears"]}
56
+ =end
57
+
58
+
59
+ # // Entropy 1,2-9
60
+ # function getAttributeCategories(uint256 id) public view returns (uint256[] memory) {
61
+ # uint256[4][9] memory spritesheetRanges = assets.spritesheetRanges();
62
+ # uint256 checks = 2 + randomUint(id, 1) % (spritesheetRanges.length - 3); // Number of bytes to check
63
+ # uint256[] memory attributes = new uint256[](checks);
64
+ # uint256 length = 0;
65
+ # for (uint256 i; i < checks; i++) {
66
+ # uint256 newAttribute = randomUint(id, 2+i) % (spritesheetRanges.length - 2) + 1; // Skip base category
67
+ #
68
+ # bool added = contains(attributes, newAttribute);
69
+ #
70
+ # if (added) {
71
+ # continue;
72
+ # }
73
+ #
74
+ # if (getGender(id) == Gender.Female) {
75
+ # if (!(spritesheetRanges[newAttribute][3] - spritesheetRanges[newAttribute][1] == 0)) {
76
+ # attributes[length] = newAttribute;
77
+ # length++;
78
+ # }
79
+ # } else {
80
+ # if (!(spritesheetRanges[newAttribute][2] - spritesheetRanges[newAttribute][0] == 0)) {
81
+ # attributes[length] = newAttribute;
82
+ # length++;
83
+ # }
84
+ # }
85
+ # }
86
+ #
87
+ # uint256[] memory attributesResized = new uint256[](length+1);
88
+ # attributesResized[0] = 0;
89
+ # for (uint256 i; i < length; i++) {
90
+ # attributesResized[i+1] = attributes[i];
91
+ # }
92
+ #
93
+ # return attributesResized;
94
+ # }
95
+
96
+ GENDER_MALE = 0
97
+ GENDER_FEMALE = 1
98
+
99
+
100
+ ## Entropy 1,2-9
101
+ def self.getAttributeCategories( id )
102
+ ## note: add 0 dummy for base upfront
103
+ attributes = [0]
104
+
105
+ gender = getGender(id) # note: (re)use 0-MALE, 1-FEMALE for range index
106
+
107
+ checks = 2 + randomUint(id, 1) % (SPRITESHEET_RANGES.size - 3) ## Number of bytes to check
108
+
109
+ checks.times do |i|
110
+ newAttribute = randomUint(id, 2+i) % (SPRITESHEET_RANGES.size - 2) + 1 ## Skip base category
111
+
112
+ next if attributes.include?( newAttribute )
113
+ attributes << newAttribute if SPRITESHEET_RANGES[newAttribute][gender].size != 0
114
+ end
115
+
116
+ attributes
117
+ end
118
+
119
+
120
+ # function getAttributes(uint256 id) public view returns (uint256[] memory) {
121
+ # uint256[] memory attributeCategories = getAttributeCategories(id);
122
+ # uint256[] memory layers = new uint256[](attributeCategories.length);
123
+ # for (uint256 i = 0; i < attributeCategories.length; i++) {
124
+ # layers[i] = getAttribute(id, attributeCategories[i]);
125
+ # }
126
+ # return layers;
127
+ # }
128
+
129
+ def self.getAttributes( id )
130
+ getAttributeCategories( id ).map do |attributeCategory|
131
+ getAttribute( id, attributeCategory )
132
+ end
133
+ end
134
+
135
+ ### add a extra/bonus helper for attribute metadata names
136
+ def self.getAttributeNames( id )
137
+ ## note: MUST sort first for correct rendering order!!!
138
+ getAttributes( id ).sort.map do |attribute|
139
+ SPRITESHEET_ATTRIBUTES[attribute]
140
+ end
141
+ end
142
+
143
+
144
+
145
+
146
+
147
+ # // Entropy 10
148
+ # function getAttribute(uint256 id, uint256 _attributeId) public view returns (uint256) {
149
+ # uint256[4] memory ranges = assets.spritesheetRanges()[_attributeId];
150
+ # Gender gender = getGender(id);
151
+ # if (gender == Gender.Female) {
152
+ # return ranges[1] + randomUint(id, 10+_attributeId) % (ranges[3] - ranges[1]);
153
+ # } else {
154
+ # return ranges[0] + randomUint(id, 10+_attributeId) % (ranges[2] - ranges[0]);
155
+ # }
156
+ # }
157
+
158
+
159
+ ## Entropy 10
160
+ def self.getAttribute( id, attributeId )
161
+ gender = getGender( id )
162
+ range = SPRITESHEET_RANGES[attributeId][ gender ]
163
+ range.begin + randomUint( id, 10+attributeId ) % range.size
164
+ end
165
+
166
+
167
+ # // Entropy 0
168
+ # function getGender(uint256 id) public view returns (Gender) {
169
+ # return randomUint(id, 0) % 2 == 0 ? Gender.Male : Gender.Female;
170
+ # }
171
+
172
+ ## Entropy 0
173
+ def self.getGender( id )
174
+ randomUint( id, 0 ) % 2 == 0 ? GENDER_MALE : GENDER_FEMALE
175
+ end
176
+
177
+
178
+ ## note: address is really a uint160 number
179
+ ## 160bit (is 20 bytes is 40 hexdigits)
180
+ ## convert to addr_to_uint
181
+ ## is really just hex_to_int (hexstring to big integer)
182
+
183
+ ## do the "on-chain" pure method in ruby here "off-chain"
184
+ #
185
+ # function getTokenID(address _address) public pure returns (uint256) {
186
+ # return uint256(uint160(_address));
187
+ # }
188
+
189
+ ## note: (ethereum) address as hexstring (160 bit/20 bytes/40 hexdigits)
190
+ ## e.g. 0x054f3b6eadc9631ccd60246054fdb0fcfe99b322
191
+ def self.getTokenID( address )
192
+ address.to_i( 16 )
193
+ end
194
+
195
+
196
+ # Non-standard Packed Mode
197
+ # Through abi.encodePacked(),
198
+ # Solidity supports a non-standard packed mode where:
199
+ #
200
+ # types shorter than 32 bytes are concatenated directly,
201
+ # without padding or sign extension
202
+
203
+ # // note:
204
+ # // address(this) is the address of the contract itself.
205
+ # // this keyword refers to the instance of a Contract.
206
+ ADDRESS = '0xaf9CE4B327A3b690ABEA6F78eCCBfeFFfbEa9FDf'
207
+
208
+ ## note:
209
+ ## returns a random unit number between 0-255 (0-ff)
210
+ ## use offset (0-31),that is, byte out of byte32 entropy buffer/hash
211
+
212
+ def self.randomUint( seed, offset )
213
+ ## assert( offset < 32, "Offset out of bounds")
214
+ ## 256bit hash (= 32 bytes)
215
+ entropy = keccak256( hex_to_bin( ADDRESS ) +
216
+ hex_to_bin( uint256_to_hex(seed)) )
217
+
218
+
219
+ ## convert binary bytes32 buffer to unint256 (big int)
220
+ ## uint256 = bin_to_hex(entropy).to_i(16)
221
+
222
+ # mask = 0xff << (offset*8)
223
+ # out = (uint256 & mask) >> (offset*8)
224
+ # out
225
+
226
+ ## note: pick a uint/byte (shorter version)
227
+ bytes = entropy.bytes.reverse
228
+ # puts "(random) 32 bytes (from 0 to 31):"
229
+ # pp bytes
230
+ bytes[offset]
231
+ end
232
+
233
+
234
+ ########
235
+ ## hex-to-bin/bin-to-hex helpers
236
+ def self.uint256_to_hex( num ) ## 256 bit (=32 bytes/64 hexdigits)
237
+ ## note: adds padding that is leading zeros
238
+ "0x%064x" % num
239
+ end
240
+
241
+ # puts 'unit256_to_hex:'
242
+ # pp uint256_to_hex( 699372119169819039191610289391678040975564001026 )
243
+ #=> "0x0000000000000000000000007a80ee32044f496a7bfef65af738fdda3a02cf02"
244
+
245
+ def self.hex_to_bin( hex )
246
+ raise TypeError, "Value must be an instance of String" unless hex.instance_of?( String )
247
+ ## remove/strip hex prefix e.g. 0x/0X
248
+ hex = hex[2..-1] if hex.start_with?( '0x' ) ||
249
+ hex.start_with?( '0X' )
250
+ [hex].pack("H*")
251
+ end
252
+
253
+ def self.bin_to_hex( bin )
254
+ raise TypeError, "Value must be an instance of String" unless bin.instance_of?( String )
255
+ bin.unpack("H*").first
256
+ end
257
+
258
+ def self.keccak256( bin )
259
+ Digest::KeccakLite.new(256).digest( bin )
260
+ end
261
+ end # module Synthpunks
262
+
263
+
@@ -0,0 +1,24 @@
1
+
2
+ module Synthpunks
3
+
4
+
5
+ class Image < Pixelart::Image
6
+ def self.generate( addr )
7
+ puts "==> generate SyntheticPunk for #{addr}..."
8
+ token_id = Synthpunks.getTokenID( addr )
9
+ ## note: MUST sort for correct rendering order
10
+ puts " using (derived) token_id >#{token_id}<"
11
+ attributes = Synthpunks.getAttributes( token_id ).sort
12
+ puts " using (pseudo-random derived) attributes >#{attributes}<:"
13
+ attributes.each do |attribute|
14
+ puts " #{attribute} => #{SPRITESHEET_ATTRIBUTES[attribute]}"
15
+ end
16
+
17
+ img = new( 24, 24 )
18
+ attributes.each do |attribute|
19
+ img.compose!( SPRITESHEET[ attribute ] )
20
+ end
21
+ img
22
+ end
23
+ end # class Image
24
+ end # module Synthpunks
@@ -0,0 +1,26 @@
1
+
2
+ module Pixelart
3
+ module Module
4
+ module Synthpunks
5
+
6
+ MAJOR = 0
7
+ MINOR = 0
8
+ PATCH = 1
9
+ VERSION = [MAJOR,MINOR,PATCH].join('.')
10
+
11
+ def self.version
12
+ VERSION
13
+ end
14
+
15
+ def self.banner
16
+ "synthpunks/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
17
+ end
18
+
19
+ def self.root
20
+ File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
21
+ end
22
+
23
+ end # module Synthpunks
24
+ end # module Module
25
+ end # module Pixelart
26
+
data/lib/synthpunks.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'pixelart'
2
+ require 'ethlite' ## needed for Digest::Keccak (otherwise no dep for now)
3
+
4
+
5
+ ## our own code
6
+ require_relative 'synthpunks/version'
7
+ require_relative 'synthpunks/contract'
8
+ require_relative 'synthpunks/image'
9
+
10
+
11
+
12
+ ## add some alternate names / aliases - why? why not?
13
+ Synthpunk = Synthpunks
14
+ Syntheticpunk = Synthpunks
15
+ Syntheticpunks = Synthpunks
16
+ SynthPunk = Synthpunks
17
+ SynthPunks = Synthpunks
18
+ SyntheticPunk = Synthpunks
19
+ SyntheticPunks = Synthpunks
20
+
21
+
22
+ puts Pixelart::Module::Synthpunks.banner # say hello
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: synthpunks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gerald Bauer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-12-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pixelart
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.3.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.3.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: etherlite
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '7'
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '4.0'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '7'
61
+ - !ruby/object:Gem::Dependency
62
+ name: hoe
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.23'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.23'
75
+ description: synthpunks - (free unlimited) 24×24 pixel punks for everyone - yes, you
76
+ can - generate / claim your own synth(etic) punks ("off-blockchain") for your own
77
+ (ethereum) account 40-hexdigit addresses e.g. 0x054f3b6eadc9631ccd60246054fdb0fcfe99b322;
78
+ incl. 2x/4x/8x zoom for bigger sizes
79
+ email: wwwmake@googlegroups.com
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files:
83
+ - CHANGELOG.md
84
+ - Manifest.txt
85
+ - README.md
86
+ files:
87
+ - CHANGELOG.md
88
+ - Manifest.txt
89
+ - README.md
90
+ - Rakefile
91
+ - config/spritesheet.json
92
+ - config/spritesheet.png
93
+ - lib/synthpunks.rb
94
+ - lib/synthpunks/contract.rb
95
+ - lib/synthpunks/image.rb
96
+ - lib/synthpunks/version.rb
97
+ homepage: https://github.com/cryptopunksnotdead/cryptopunks
98
+ licenses:
99
+ - Public Domain
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options:
103
+ - "--main"
104
+ - README.md
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '2.3'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubygems_version: 3.3.7
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: synthpunks - (free unlimited) 24×24 pixel punks for everyone - yes, you can
122
+ - generate / claim your own synth(etic) punks ("off-blockchain") for your own (ethereum)
123
+ account 40-hexdigit addresses e.g. 0x054f3b6eadc9631ccd60246054fdb0fcfe99b322; incl.
124
+ 2x/4x/8x zoom for bigger sizes
125
+ test_files: []