synthpunks 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0c5233aa985d25b010831dca85d14e481489665af2e69f428959d4db3a56228
4
- data.tar.gz: 6f1e5ee50bb527fcdc4baa1e82673885a1883d3dc06b982d3c9f018f58045899
3
+ metadata.gz: c0238c880c91ece2f04aaa0f63efd9709c796f135a10b83619a664bd7655fac9
4
+ data.tar.gz: b4ce29e7fcb469c83f6a642f26e5090a35c6e760e504ff87b0ba471452185e98
5
5
  SHA512:
6
- metadata.gz: 90b18b54a84d472b62c0694389ca633b948f0ac45e5f63219f08e7ce63f0994542930e29ad86c6d1a97ae1483d10995c9603aa1fc7c8212d158c139fad5d823d
7
- data.tar.gz: b0e77cb3d73d74a124628ea7da1af8f63c9ed5f5e595dbdffbf1a126e4bc29971236f3a7443006b081a2fbac7efeddbecbb2be49047a6abdf61f1706670f16fd
6
+ metadata.gz: bcc2e2999185747150907e51993ba03b8e55564bcf18d601dbd2f6d8c41b370f2189871ac28e74d0836313d9cc86d0630b4e96f78bc355d2f48f03cfc32f70d6
7
+ data.tar.gz: de49e479e2104a7695854d47617c1796867e4cadd18b4bedca25fb0d77032a9cab9730d647c042bb7501b38dbb483bf9913f5735caa73399e42ea8ec52a4ba8e
data/README.md CHANGED
@@ -11,9 +11,285 @@ synthpunks - (free unlimited) 24×24 pixel punks for everyone - yes, you can - g
11
11
 
12
12
 
13
13
 
14
- ## Usage
14
+ ## What are Synthetic (Crypto) Punks V1?
15
15
 
16
- ...
16
+ > Fully on-chain (crypto) punks for every ethereum address. Check yours out for free!
17
+ >
18
+ > -- [**syntheticpunks.com**](https://syntheticpunks.com)
19
+
20
+
21
+ [Stephan Cilliers](https://github.com/stephancill) (from South Africa)
22
+ has put together an open-source blockchain service ( - see [**stephancill/synthetic-punks**](https://github.com/stephancill/synthetic-punks) - )
23
+ to generate for free¹ 24×24 punk pixel heads for every ethereum address (account).
24
+
25
+ ¹: and optionally clain / mint a (non-fungible) token for a 0.02 ether fee.
26
+
27
+
28
+ The F.A.Q. reads:
29
+
30
+ > Q: What are Synthetic Punks?
31
+ >
32
+ > A: Synthetic Punks is inspired by the historical
33
+ > collection of 10 000 Matt & John's® Punks [Anno 2017]
34
+ > by Larva Labs and Synthetic Loot by Dom Hofmann.
35
+ > It generates a unique, fully on-blockchain punk for each Ethereum address.
36
+ >
37
+ > They are free to view for any address, but can be claimed [minted]
38
+ > as an ERC-721 non-fungible token (NFT)
39
+ > for a price of 0.02 ether.
40
+ >
41
+ > Features - Each Synthetic Punk
42
+ > - Is generated from assets stored fully on-blockchain
43
+ > - Is uniquely associated with an ethereum wallet address
44
+ > - Supports Ethereum Name Service (ENS) in its metadata
45
+
46
+
47
+
48
+
49
+ ## "Off-Chain" Usage In Your Script
50
+
51
+
52
+ Anyways, the synthpunks gem / library is inspired by Synthetic Punks V1
53
+ by Stephan Cilliers (see above)
54
+ and lets you generate punks using the "original"
55
+ Synthetic Punks V1 pseudo-random number and image generation formula
56
+ "off-blockchain"¹
57
+ using the "original" Synthetic Punks V1 spritesheet
58
+
59
+ ![](config/spritesheet.png)
60
+
61
+ and attribute categories (ranges) and names.
62
+
63
+
64
+ Let's try
65
+ the (ethereum) address 0x054f3b6eadc9631ccd60246054fdb0fcfe99b322:
66
+
67
+
68
+ ``` ruby
69
+ require 'synthpunks'
70
+
71
+ punk = Synthpunks::Image.generate('0x054f3b6eadc9631ccd60246054fdb0fcfe99b322' )
72
+ punk.save( 'punk1.png' )
73
+ punk.zoom(8).save( 'punk1@8x.png' )
74
+ ```
75
+
76
+ resulting in:
77
+
78
+ ![](i/punk1.png) 8x
79
+ ![](i/punk1@8x.png)
80
+
81
+
82
+ Tip: Use `Synthpunks.getTokenID( addr )`
83
+ to get the "official" token id
84
+ from the address (that really is only a "convenience" helper that converts the 40-digit / 20-byte hexstring to a decimal (big) integer number). Example:
85
+
86
+ ``` ruby
87
+ Synthpunks.getTokenID('0x054f3b6eadc9631ccd60246054fdb0fcfe99b322' )
88
+ #=> 30311890011735557186986086868537068337617285922
89
+
90
+ # note: yes, Synthpunks.getTokenID same as String#to_i(16)
91
+ '0x054f3b6eadc9631ccd60246054fdb0fcfe99b322'.to_i( 16 )
92
+ #=> 30311890011735557186986086868537068337617285922
93
+ ```
94
+
95
+ And use the new exclusive "off-chain" only `Synthpunks.getAssetNames( id )`
96
+ helper
97
+ to get all (random) punk attributes by name.
98
+
99
+ ``` ruby
100
+ Synthpunks.getAttributeNames( 30311890011735557186986086868537068337617285922 )
101
+ #=> ["Alien", "Clown Nose", "Frown", "Vape", "Eyebrows"]
102
+ ```
103
+
104
+
105
+ Now lookup the minted
106
+ Synthetic (Crypto) Punks V1 on the open sea (secondary)
107
+ market:
108
+
109
+ [Minted Synthetic Punk for 0xaf9ce4b327a3b690abea6f78eccbfefffbea9fdf
110
+ with Token ID #30311890011735557186986086868537068337617285922 @ Open Sea](https://opensea.io/assets/ethereum/0xaf9ce4b327a3b690abea6f78eccbfefffbea9fdf/30311890011735557186986086868537068337617285922)
111
+
112
+ Or see
113
+ [Synthetic Punk for 0xaf9ce4b327a3b690abea6f78eccbfefffbea9fdf](https://syntheticpunks.com/#/address/0xaf9ce4b327a3b690abea6f78eccbfefffbea9fdf)
114
+
115
+
116
+ And spot the differencence - hint: none other
117
+ than the "dark / black-ish" background is missing.
118
+
119
+
120
+ Let's retry and let's add the "dark / black-ish" background
121
+ that is, #1A1A1A, using the rgb hex color code:
122
+
123
+ ``` ruby
124
+ punk = Synthpunks::Image.generate('0x054f3b6eadc9631ccd60246054fdb0fcfe99b322' )
125
+ punk = punk.background( '#1A1A1A' )
126
+ punk.save( 'punk1b.png' )
127
+ punk.zoom(8).save( 'punk1b@8x.png' )
128
+ ```
129
+
130
+ resulting in:
131
+
132
+ ![](i/punk1b.png) 8x
133
+ ![](i/punk1b@8x.png)
134
+
135
+
136
+ Or for fun let's try some more new "custom" backgrounds.
137
+ Example: Stand with Ukraine / Ukraine Flag:
138
+
139
+ ``` ruby
140
+ punk = Synthpunks::Image.generate('0x054f3b6eadc9631ccd60246054fdb0fcfe99b322' )
141
+ punk = punk.background( 'ukraine' )
142
+ punk.save( 'punk1c.png' )
143
+ punk.zoom(8).save( 'punk1c@8x.png' )
144
+ ```
145
+
146
+ resulting in:
147
+
148
+ ![](i/punk1c.png) 8x
149
+ ![](i/punk1c@8x.png)
150
+
151
+
152
+ or
153
+
154
+ ``` ruby
155
+ punk = punk.background( 'rainbow' )
156
+ ```
157
+
158
+ resulting in:
159
+
160
+ ![](i/punk1d.png) 8x
161
+ ![](i/punk1d@8x.png)
162
+
163
+ and so on.
164
+
165
+ Tip: Looking for left-looking phunks? Try `Image#mirror`.
166
+ Example:
167
+
168
+ ``` ruby
169
+ punk = Synthpunks::Image.generate('0x054f3b6eadc9631ccd60246054fdb0fcfe99b322' )
170
+ phunk = punk.mirror
171
+ phunk.save( 'phunk1.png' )
172
+ phunk.zoom(8).save( 'phunk1@8x.png' )
173
+ ```
174
+
175
+ resulting in:
176
+
177
+ ![](i/phunk1.png) 8x
178
+ ![](i/phunk1@8x.png)
179
+
180
+
181
+ Bonus Tip: Derive your own custom default profile pictures
182
+ using `Image#silhouette`. Example:
183
+
184
+
185
+ ``` ruby
186
+ punk = Synthpunks::Image.generate('0x054f3b6eadc9631ccd60246054fdb0fcfe99b322' )
187
+ punk = punk.silhouette( '0x647785' ).background( '0xCCD5DE' )
188
+ punk.save( 'punk1-default1.png' )
189
+ punk.zoom(8).save( 'punk1-default1@8x.png' )
190
+ ```
191
+
192
+ resulting in:
193
+
194
+ ![](i/punk1-default1.png) 8x
195
+ ![](i/punk1-default1@8x.png)
196
+
197
+ or is blue the new gray?
198
+
199
+ ``` ruby
200
+ punk = punk.silhouette( '0x4474E0' ).background( '0xA0C2FF' )
201
+ ```
202
+
203
+ resulting in:
204
+
205
+ ![](i/punk1-default2.png) 8x
206
+ ![](i/punk1-default2@8x.png)
207
+
208
+ and so on.
209
+
210
+
211
+
212
+
213
+ Yes, you can.
214
+ Let's try some more
215
+ the (ethereum) addresses.
216
+
217
+ ``` ruby
218
+ punk = Synthpunks::Image.generate( '0x7a80ee32044f496a7bfef65af738fdda3a02cf02' )
219
+ punk.save( "punk2.png" )
220
+ punk.zoom(8).save( "punk2@8x.png" )
221
+ ```
222
+
223
+ resulting in:
224
+
225
+ ![](i/punk2.png) 8x
226
+ ![](i/punk2@8x.png)
227
+
228
+
229
+ and the attributes
230
+
231
+ ``` ruby
232
+ tokenID = Synthpunks.getTokenID( '0x7a80ee32044f496a7bfef65af738fdda3a02cf02' )
233
+ #=> 699372119169819039191610289391678040975564001026
234
+ Synthpunks.getAttributeNames( tokenID )
235
+ #=> ["Human 1", "Rosy Cheeks", "Shadow Beard", "Wild Hair", "VR"]
236
+ ```
237
+
238
+ and compare with the "original" with the attributes:
239
+ - Human 1
240
+ - Rosy Cheeks
241
+ - Wild Hair
242
+ - VR
243
+ - Shadow Beard
244
+
245
+
246
+ [Minted Synthetic Punk for 0x7a80Ee32044F496A7bFeF65Af738FddA3a02CF02
247
+ with Token ID #699372119169819039191610289391678040975564001026 @ Open Sea](https://opensea.io/assets/ethereum/0xaf9ce4b327a3b690abea6f78eccbfefffbea9fdf/699372119169819039191610289391678040975564001026)
248
+
249
+ Or see [Synthetic Punk for 0x7a80Ee32044F496A7bFeF65Af738FddA3a02CF02](https://syntheticpunks.com/#/address/0x7a80Ee32044F496A7bFeF65Af738FddA3a02CF02)
250
+
251
+ and so on.
252
+
253
+
254
+
255
+
256
+
257
+
258
+ ¹: Yes, the (on-chain) solidity contract code
259
+ got translated "by-hand" to (off-chain) ruby script.
260
+
261
+ Example - the entropy pseudo-random number generator source:
262
+
263
+ ``` solidity
264
+ function randomUint(uint256 seed, uint256 offset) public view returns (uint256)
265
+ {
266
+ require(offset < 32, "Offset out of bounds");
267
+ bytes32 entropy = keccak256(abi.encodePacked(address(this), seed));
268
+ bytes32 mask = bytes32(0xff << (offset * 8));
269
+ uint256 out = uint256((entropy & mask) >> (offset * 8));
270
+ return out;
271
+ }
272
+ ```
273
+
274
+ and the matching ruby version:
275
+
276
+ ``` ruby
277
+ ADDRESS = '0xaf9CE4B327A3b690ABEA6F78eCCBfeFFfbEa9FDf'
278
+
279
+ ## note:
280
+ ## returns a random unit number between 0-255 (0-ff)
281
+ ## use offset (0-31),that is, byte out of byte32 entropy buffer/hash
282
+
283
+ def randomUint( seed, offset )
284
+ # assert( offset < 32, "Offset out of bounds")
285
+ entropy = keccak256( hex_to_bin( ADDRESS ) +
286
+ hex_to_bin( uint256_to_hex(seed)) )
287
+
288
+ ## note: pick a uint/byte (shorter version)
289
+ bytes = entropy.bytes.reverse
290
+ bytes[offset]
291
+ end
292
+ ```
17
293
 
18
294
 
19
295
 
data/Rakefile CHANGED
@@ -27,6 +27,7 @@ Hoe.spec 'synthpunks' do
27
27
 
28
28
  self.extra_deps = [
29
29
  ['pixelart', '>= 1.3.6'],
30
+ ['backgrounds'],
30
31
  ['etherlite', '>= 0.3.1'],
31
32
  ]
32
33
 
@@ -4,8 +4,8 @@ module Module
4
4
  module Synthpunks
5
5
 
6
6
  MAJOR = 0
7
- MINOR = 0
8
- PATCH = 1
7
+ MINOR = 1
8
+ PATCH = 0
9
9
  VERSION = [MAJOR,MINOR,PATCH].join('.')
10
10
 
11
11
  def self.version
data/lib/synthpunks.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'pixelart'
2
+ require 'backgrounds'
2
3
  require 'ethlite' ## needed for Digest::Keccak (otherwise no dep for now)
3
4
 
4
5
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synthpunks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.3.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: backgrounds
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: etherlite
29
43
  requirement: !ruby/object:Gem::Requirement