<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>en · blog.vrypan.net</title>
    <link>https://blog.vrypan.net/tags/en/</link>
    <description>en · blog.vrypan.net</description>
    <lastBuildDate>Thu, 01 Jan 2026 20:46:44 +0000</lastBuildDate>
    <generator>bckt</generator>
    <atom:link href="https://blog.vrypan.net/rss-en.xml" rel="self" type="application/rss+xml"/>
    
    <item>
      <title>Down the RNG rabbit hole - Part II</title>
      <link>https://blog.vrypan.net/2026/01/01/down-the-rng-rabbit-hole-part-ii/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2026/01/01/down-the-rng-rabbit-hole-part-ii/</guid>
      <pubDate>Thu, 01 Jan 2026 20:46:44 +0000</pubDate>
      <description>So, Rule30RND was ok as a fun experiment, but not a PRNG that someone could take seriously.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2026/01/01/down-the-rng-rabbit-hole-part-ii/r30r2.png">
        
	<p>So, <a href="/2025/12/30/down-the-rng-rabbit-hole/">Rule30RND was ok as a fun experiment</a>, but not a PRNG that someone could take seriously.</p>
<p>I kept tinkering, as if I was playing a game: change this and that, run the tests, check my score.</p>
<p><em>Side note: after I published the last post, I realized that my test scripts had fundamental flaws, like adding text headers in the randomly generated bytes.</em></p>
<h2>Radius-2</h2>
<p>No matter how hard I tried, it was obvious that a Rule 30-based algorithm would not pass BigCrush unless I changed it so much that would become something else with a sprinkle of CA.</p>
<p>Now, Rule 30 works like this: If <code>C</code> is our bit, <code>L</code> is the one on its left and <code>R</code> the one on its right:<br />
<code>new_bit = L XOR (C OR R)</code></p>
<p>That’s a &quot;radius-1 CA&quot;. What if I tried with a radius-2 CA, that uses two bits on the left and two on the right?</p>
<p>Unfortunately, there is much less literature for radius-2 than radius-1 CAs. After some search that did not return a documented good candidate for what I wanted to build, and a few failed experiments, I decided to extend Rule 30 in a “symmetric” way.</p>
<p><code>new_bit = (L2 XOR L1) XOR (C OR (R1 OR R2))</code></p>
<p>This gave significantly better results.</p>
<p>Not exceptional. The new algorithm failed 5/15 SmallCrush tests (Gap, SimpPoker, CouponCollector, WeightDistrib, HammingIndep).</p>
<p>But these are the tests I might be able to fix with a diffusion function.</p>
<h2>Searching for a diffusion fucntion</h2>
<p>I wanted a diffusion function, so I let Claude test 7 different functions, run the tests, collect the results, and let me know when it was done.</p>
<table>
<thead>
<tr>
<th>Mixing/Diffusion Approach</th>
<th>SmallCrush</th>
<th>Performance vs math/rand</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rotation (5,14,27)</td>
<td>12/15</td>
<td>1.08×</td>
<td>❌</td>
</tr>
<tr>
<td>5 XOR Rotations</td>
<td>13/15</td>
<td>0.94×</td>
<td>❌</td>
</tr>
<tr>
<td>xoshiro256++ Style</td>
<td>11/15</td>
<td>1.13×</td>
<td>❌</td>
</tr>
<tr>
<td>MurmurHash</td>
<td><strong>15/15</strong></td>
<td>0.95×</td>
<td>✅</td>
</tr>
<tr>
<td>SplitMix64</td>
<td><strong>15/15</strong></td>
<td>0.93×</td>
<td>✅</td>
</tr>
<tr>
<td><strong>Hybrid</strong></td>
<td><strong>15/15</strong></td>
<td><strong>1.03×</strong></td>
<td>✅</td>
</tr>
<tr>
<td>Per-Word Varying</td>
<td><strong>15/15</strong></td>
<td>0.90×</td>
<td>✅</td>
</tr>
</tbody>
</table>
<p>The winner was the “Hybrid” approach that combines rotation, multiplication by the golden ratio, and shift-XOR:</p>
<pre lang="golang"><code>func mix(x uint64) uint64 {
    x ^= bits.RotateLeft64(x, 13)
    x *= 0x9e3779b97f4a7c15  // Golden ratio constant
    x ^= x &gt;&gt; 27
    return x
}
</code></pre>
<p>SmallCrush is the first step, but I needed it to pass BigCrush.</p>
<p>And, YES! <strong>My rule-30-radius-2-diffused algo scored 160/160 on BigCrush</strong> for the first time!</p>
<h2>Staying true</h2>
<p>Now, this worked, but <strong>it was also cheating</strong>: I applied <code>mix()</code> to every state evolution: <code>s1, s2=mix(rule30(s1)), s3=mix(rule30(s2)), ...</code>, so this was no longer a CA algorithm.</p>
<p>What if I applied <code>mix()</code> only to the output? I.e. keep a pure Rule 30, radius-2 algorithm that generates states <code>s1, s2, ...</code>, but return <code>mix(s1), mix(s2), ...</code>. Would this work?</p>
<p><strong>IT WORKED!</strong> <strong>IT WORKED!</strong></p>
<p>And it was also <strong>6% faster</strong>.</p>
<h2>I present you “R30R2”</h2>
<p>Along the way, I fixed some annoying Makefile issues, optimized how <code>Read()</code> reads data from the state, and tweaked a few things here and there.</p>
<p>I was ready to release it, but when “Rule 30” is mentioned in literature, it means a radius-1 CA.</p>
<p>I decided to rename the project, the documentation, the function names, etc. And it's name is... <strong>R30R2</strong>.</p>
<blockquote>
<p><strong>R30R2 is a radius-2 Rule 30-based PRNG with a diffusion function applied on output. It scores 160/160 on BigCrush, and is 2× faster than <code>math/rand/v2</code>.</strong></p>
<p>You can find it at <a href="https://github.com/vrypan/r30r2/">https://github.com/vrypan/r30r2/</a></p>
</blockquote>
<table>
<thead>
<tr>
<th>RNG</th>
<th>BigCrush Score</th>
<th>Performance vs math/rand</th>
</tr>
</thead>
<tbody>
<tr>
<td>math/rand</td>
<td>159/160</td>
<td>1.00× (baseline)</td>
</tr>
<tr>
<td>math/rand/v2</td>
<td>160/160 ✓</td>
<td>0.56×</td>
</tr>
<tr>
<td><strong>Rule 30</strong></td>
<td><strong>160/160</strong> ✓</td>
<td><strong>1.03×</strong></td>
</tr>
</tbody>
</table>
<h2>🎉🍾🍻</h2>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2026/01/01/down-the-rng-rabbit-hole-part-ii/r30r2.png"
   type="image/png"
   length="190176"/>

    </item>
    
    <item>
      <title>Down the RNG rabbit hole</title>
      <link>https://blog.vrypan.net/2025/12/30/down-the-rng-rabbit-hole/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/30/down-the-rng-rabbit-hole/</guid>
      <pubDate>Tue, 30 Dec 2025 22:06:33 +0000</pubDate>
      <description>In my last post, I described how I started from beautiful images generated by "turmites" and ended up with one that looked, and in many aspects felt, random.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/12/30/down-the-rng-rabbit-hole/image.png">
        
	<p><a href="/2025/12/28/playing-with-turmites-better-than-crypto-rand/">In my last post</a>, I described how I started from beautiful images generated by &quot;turmites&quot; and ended up with one that looked, and in many aspects felt, random.</p>
<p>I knew my approach was amateurish. After all, I <strong>am</strong> an amateur when it comes to information entropy, predictability, statistical analysis, and random number generators (RNGs). But I wanted to learn more and explore the idea further.</p>
<p>So my first attempt was to write a pseudo-random number generator (PRNG) based on my LLLR turmite: if I let the turmite run enough iterations on an NxN grid using 4 colors, the result is NxNx2 bits.</p>
<p>With a 64x64 grid, I’d get 8,192 bits, or 1,024 bytes. Are they <em>random enough</em>? How do I measure that?</p>
<p>I learned about tests used to identify structural weaknesses in PRNGs, like SmallCrush and BigCrush.</p>
<p>Yes (as you may have expected), my &quot;turmite RNG&quot; failed miserably, even on the simplest statistical tests like Chi-Square. It was also orders of magnitude slower than anything else out there.</p>
<hr />
<p>Still, my intuition told me there must be some way to build a decent RNG using cellular automata.</p>
<p>I found Stephen Wolfram’s &quot;Rule 30&quot;<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. It’s a very simple, 1D cellular automaton, <em>&quot;displaying aperiodic, chaotic behaviour&quot;</em>.
And Wolfram used it as a PRNG in Mathematica.</p>
<p>Now we're talking.</p>
<p>Arrogantly, I built my own implementation using my own assumptions and preferences, without looking into how others used Rule 30 for PRNG purposes —which turned out to be a good thing, I think.</p>
<p>In most cases, cellular automata &quot;live&quot; on infinite spaces, like plains and lines, but in my previous work with turmites, I liked how they behaved on toroidal spaces. So I used a circular 256-bit stripe, and instead of using just the middle bits of consecutive steps as the RNG output, I used the whole 256-bit space. (That’s a 256× speed improvement over the typical use of Rule 30 as an RNG!)</p>
<p>And it looked good. Performance was excellent because I could fit the entire state in 4 uint64 words and compute the next state using basic binary operations on each word.</p>
<p>I even claimed 4x speed improvements over <code>math/rand</code>!</p>
<p>Slow down, cowboy.</p>
<p>People were kind to point out<sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup> that the tests I used did not compare apples to apples.
And as I searched more, I learned there's a lot to fix and improve.</p>
<hr />
<p>Long story short, two days later I had a decent PRNG that is comparable to, and in some cases better than, the standard pseudo-random number generators used by Golang.</p>
<p>I even modified the algorithm further, to improve statistical distribution: after each step, I apply XOR rotation mixing to each word, which is not part of the original Rule 30 algorithm.</p>
<p><a href="https://github.com/vrypan/rule30rnd">Rule30RND</a> is a drop-in replacement for <code>math/rand</code> and <code>math/rand/v2</code>, with a very small footprint (state and manipulation require just 40 bytes of memory), comparable statistical qualities, and is 30%–60% faster.</p>
<p>Rule30RND generates reproducible sequences (depending on the seed), which may sound like a drawback for an RNG, but it’s actually useful in many cases where a PRNG is preferred over a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator). Those cases usually involve generating large, statistically unpredictable data sets used for simulations or testing.</p>
<p><strong>Throughput Comparison, relative to math/rand</strong></p>
<table>
<thead>
<tr>
<th>Algorithm</th>
<th>Read() 32KB</th>
<th>Read() 1KB</th>
<th>Uint64()</th>
</tr>
</thead>
<tbody>
<tr>
<td>MathRand</td>
<td>1.00x</td>
<td>1.00x</td>
<td>1.00x</td>
</tr>
<tr>
<td>MathRandV2</td>
<td>1.69x</td>
<td>1.63x</td>
<td>0.58x</td>
</tr>
<tr>
<td><strong>Rule30</strong></td>
<td><strong>5.47x</strong></td>
<td><strong>5.13x</strong></td>
<td><strong>1.39x</strong></td>
</tr>
<tr>
<td>CryptoRand</td>
<td>3.11x</td>
<td>1.75x</td>
<td>0.03x</td>
</tr>
</tbody>
</table>
<p><strong>Rule30RND Basic Tests (ent)</strong></p>
<table>
<thead>
<tr>
<th>Test</th>
<th>Result</th>
<th>Expected</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Entropy</td>
<td>7.999982 bits/byte</td>
<td>8.0000</td>
<td>✓ Perfect (99.9998%)</td>
</tr>
<tr>
<td>Chi-Square</td>
<td>253.9</td>
<td>~255 (200-310)</td>
<td>✓ Excellent</td>
</tr>
<tr>
<td>Arithmetic Mean</td>
<td>127.4987</td>
<td>127.5</td>
<td>✓ Perfect</td>
</tr>
<tr>
<td>Monte Carlo π</td>
<td>3.140031</td>
<td>3.141593</td>
<td>✓ 0.05% error</td>
</tr>
<tr>
<td>Serial Correlation</td>
<td>0.000171</td>
<td>0.0000</td>
<td>✓ Uncorrelated</td>
</tr>
</tbody>
</table>
<p><strong>SmallCrush results</strong></p>
<table>
<thead>
<tr>
<th>RNG</th>
<th>Passed</th>
<th>Failed</th>
<th>Pass Rate</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Rule30</strong></td>
<td><strong>15/15</strong></td>
<td>0/15</td>
<td><strong>100%</strong></td>
</tr>
<tr>
<td>math/rand</td>
<td>15/15</td>
<td>0/15</td>
<td>100%</td>
</tr>
<tr>
<td>math/rand/v2 (PCG)</td>
<td>5/15</td>
<td>10/15</td>
<td>100%</td>
</tr>
</tbody>
</table>
<p>(Update: The original version of this post incorrectly reported that all the above tests failed 5/15 tests. This was due to an error in the test scripts.)</p>
<p><strong>That’s no small feat for an amateur!</strong> Many people smarter and with much deeper knowledge than me spend years working on these things, me building something that can be compared to what they build makes me proud.</p>
<p>I’ll probably keep tinkering on Rule30RND. Running a BigCrunch test now, that will probably take a whole day or more.</p>
<p><strong>Happy New Year!</strong></p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://en.wikipedia.org/wiki/Rule_30">https://en.wikipedia.org/wiki/Rule_30</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://farcaster.xyz/flashprofits.eth/0x1cf6318a">https://farcaster.xyz/flashprofits.eth/0x1cf6318a</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/30/down-the-rng-rabbit-hole/image.png"
   type="image/png"
   length="441550"/>

    </item>
    
    <item>
      <title>Playing with Turmites: better than crypto/rand?</title>
      <link>https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/</guid>
      <pubDate>Sun, 28 Dec 2025 22:32:25 +0000</pubDate>
      <description>I'm fascinated by cellular automata, and especially “Turmites”. They are small, simple algorithms that create very interesting results that are often visually appealing for the complex and life-like patterns they generate.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/life.png">
        
	<p>I'm fascinated by cellular automata, and especially “Turmites”<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. They are small, simple algorithms that create very interesting results that are often visually appealing for the complex and life-like patterns they generate.</p>
<p>They are so simple that even a kid could easily implement them in real life.</p>
<p>The idea is you have a grid with squares that can take a color from a predefined palette. Let’s say 3 colors for example, red, green, blue.</p>
<p>You start from one square and based on its color, you replace it with an other, you turn left or right and move to the next square, and repeat.</p>
<p>So the rules are something like this:</p>
<table>
<thead>
<tr>
<th>if the square is</th>
<th>paint it</th>
<th>and turn</th>
</tr>
</thead>
<tbody>
<tr>
<td>red</td>
<td>blue</td>
<td>left</td>
</tr>
<tr>
<td>blue</td>
<td>green</td>
<td>right</td>
</tr>
<tr>
<td>green</td>
<td>red</td>
<td>righ</td>
</tr>
</tbody>
</table>
<p>We can call this an <em>LRR turmite</em>, because it’s left, right, right.</p>
<p><figure><img src="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lrr-10m.png" alt="" /></figure></p>
<p>The result can be boring (if you have <em>LLL</em>, you will get a small square, as the “ant” just turns around in the same 4 squares forever), but in other cases you get results like this, that may remind you of an ant colony (that’s why they are called <a href="https://en.wikipedia.org/wiki/Langton%27s_ant">Lamgton’s ants</a>, or <a href="https://en.wikipedia.org/wiki/Turmite">Turmites</a>, a combination of “Turing machine” and “termite”.)</p>
<hr />
<p>But today, I’ll focus on turmites that <strong>do not</strong> generate interesting patterns, and surprisingly, this may be even more interesting.</p>
<p>(I’m an amateur explorer here, what I’ll describe is probably known to mathematicians, but nevertheless I find it very interesting.)</p>
<p>So, some turmites (like LLL) generate boring results, some generate interesting patterns, and some, generate “random” (???) ones.</p>
<hr />
<p>Before we move on, let’s talk about entropy.</p>
<p>In information theory, entropy measures uncertainty in a probability distribution: Higher entropy means less predictable outcomes, lower entropy more predictable outcomes.</p>
<p>It’s easy to think about image entropy. If I tell you I have a 100x100 image which is totally black, then entropy is zero: you can pick any pixel and know in advance what color it will be. If I tell you I have a photo of the a greenfield that extends to the horizon, the entropy is higher but you still know that any pixel at the top of the image will probably be a shade of blue and any pixel at the lower parts of the image will probably be green.</p>
<p>There are many ways to measure the entropy of an image. One is how well you can guess the color of a random pixel. An other one is how well you can guess the color of a random pixel, if you know the color of a pixel next to it.</p>
<p>For example, if you take a drone photo of a parking full of cars, once you know the color of one pixel, there is a very high probability that the adjacent pixels will have the same color. Again, the entropy is low.</p>
<p>But if you take a cup of white sugar and a cup of brown sugar, mix them and spread them on a surface, and take a photo, the probability of guessing the color of any pixel is 50%. This is an image with very high entropy, what we often call “noise”.</p>
<p>There are more methods and ways to measure an image’s entropy, but a) I’m no expert and b) this is not a course on entropy :-)</p>
<p>What I’m going to use in the examples bellow, is</p>
<ul>
<li><strong>Shannon entropy</strong>: a number that shows the average “surprise” when examining a pixel. If your image uses N colors, noise would have Shannon entropy equal to log2(N). The higher the number, the more “randomness” in the photo. Our photo of white/brown sugar would have Shannon entropy close to log2(2) = 1. A black photo will have Shannon entropy 0.</li>
<li><strong>MI-horizontal</strong>: Horizontal mutual information. A number that tells us how probable it is to guess a pixel on the left or the right of a given pixel. For example, an image of horizontal stripes has MI-horizontal = 1, because we can tell with absolute certainty the color of a pixel if we know it’s left or right pixel. Values close to zero show higher entropy.</li>
<li><strong>MI-vertical</strong>: Similar to MI-horizontal but for the pixels above and bellow a known pixel.</li>
<li><strong>MI 4-neighbor</strong>: similar, to the above, but for the four (top, bottom, left, right) pixels.</li>
<li><strong>MI 8-neighbor</strong>: same as above, but including the diagonal adjacent pixels.</li>
</ul>
<hr />
<p>So, let’s get back to our turmites <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup>.</p>
<p>For the LRR turmite we saw above (128x64, 3-color turmite) we get these values. I included the values of a similar image generated using Golang’s <code>math/rand</code></p>
<p><figure><img src="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/compare.png" alt="comparison" /></figure></p>
<table>
<thead>
<tr>
<th></th>
<th>Shannon</th>
<th>MI-h</th>
<th>MI-v</th>
<th>MI 4-neighbor</th>
<th>MI 8-neighbor</th>
</tr>
</thead>
<tbody>
<tr>
<td>LRR</td>
<td>1.576863</td>
<td>0.011126</td>
<td>0.011870</td>
<td>0.011498</td>
<td>0.008027</td>
</tr>
<tr>
<td>rand</td>
<td>1.584952</td>
<td>0.000412</td>
<td>0.000259</td>
<td>0.000335</td>
<td>0.000278</td>
</tr>
</tbody>
</table>
<p>As you see, while Shanon entropy is similar (“perfect” entropy would get us ~1.5849625 in this case), the rest measurements of entropy show that the LRR image is not that random. And to be honest, if you squint, you can see some patterns that may not be well-defined, geometric patterns, but they are there.</p>
<p>But let’s see an other one: a 4-color LLLR turmite on a 96x54 grid, after 200,000 iterations.</p>
<p><figure><img src="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lllr.png" alt="LLLR" /></figure></p>
<p>This looks like it has much more entropy than the previous one. Let’s measure it.</p>
<table>
<thead>
<tr>
<th></th>
<th>Shannon</th>
<th>MI-h</th>
<th>MI-v</th>
<th>MI 4-neighbor</th>
<th>MI 8-neighbor</th>
</tr>
</thead>
<tbody>
<tr>
<td>LLLR</td>
<td>1.999576</td>
<td>0.000515</td>
<td>0.000547</td>
<td>0.000531</td>
<td>0.001024</td>
</tr>
</tbody>
</table>
<p>Shannon entropy = 2 for perfect entropy in this case, so we're very close, and the rest of the numbers show a very high entropy! But we know that this is an image generated by an extremely simple algorithm, how can it look like random noise?</p>
<p>Let’s use <code>math/rand</code> again. And to be sure, let’s create 100 random images of the same size, with 4 colors and measure the average. And let’s do the same with <code>crypto/rand</code> that is supposed to have even higher entropy (I think).</p>
<table>
<thead>
<tr>
<th></th>
<th>Shannon</th>
<th>MI-h</th>
<th>MI-v</th>
<th>MI 4-neighbor</th>
<th>MI 8-neighbor</th>
</tr>
</thead>
<tbody>
<tr>
<td>LLLR</td>
<td>1.999576</td>
<td>0.000515</td>
<td>0.000547</td>
<td>0.000531</td>
<td>0.001024</td>
</tr>
<tr>
<td>math/rand</td>
<td>1.999581</td>
<td>0.001167</td>
<td>0.001352</td>
<td>0.001259</td>
<td>0.001290</td>
</tr>
<tr>
<td>crypto/rand</td>
<td>1.999600</td>
<td>0.001158</td>
<td>0.001309</td>
<td>0.001233</td>
<td>0.001277</td>
</tr>
</tbody>
</table>
<p>Wait.</p>
<p>So, <strong>according to these numbers, a 100% predictable<sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup> image, appears to have higher entropy than randomly generated images.</strong></p>
<hr />
<p>I find this fascinating.</p>
<p>Like I said, I’m just an amateur. So, there may be some other way to measure entropy that shows that the LLLR image has lower entropy than I think.</p>
<p>Or maybe it’s an illustration of how <code>math/rand</code> is not as unpredictable as most people think.</p>
<p>Or maybe it’s a nice visualization of Silvio Micali’s work on Pseudorandomness<sup class="footnote-ref"><a href="#fn-4" id="fnref-4" data-footnote-ref>4</a></sup>.</p>
<p>I would love to hear from people who have better and deeper understanding of the topic<sup class="footnote-ref"><a href="#fn-5" id="fnref-5" data-footnote-ref>5</a></sup>!</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>Visit <a href="https://turmites.art">turmites.art</a>! <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p>Usually, turmites are drawn on an infinite plain. In my case, I use fixed-size toroid surfaces, where the leftmost pixels are adjacent to the rightmost and the top row is adjacent to the bottom row. <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p>Full video of the process: <a href="https://www.youtube.com/watch?v=gpXDUTZLlHM">https://www.youtube.com/watch?v=gpXDUTZLlHM</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
<li id="fn-4">
<p><a href="https://www.youtube.com/watch?v=GjO-6lfU1Kc">Is true randomness possible? | Silvio Micali and Lex Fridman</a> <a href="#fnref-4" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4">↩</a></p>
</li>
<li id="fn-5">
<p><a href="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lllr-orig.png">Original LLLR image</a> (the one displayed in the article is scaled up for visibility), for anyone who wants to do entropy analysis. <a href="#fnref-5" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="5" aria-label="Back to reference 5">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/compare.png"
   type="image/png"
   length="60070"/>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/life.png"
   type="image/png"
   length="53842"/>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lllr-orig.png"
   type="image/png"
   length="3412"/>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lllr.png"
   type="image/png"
   length="4176"/>

   <enclosure url="https://blog.vrypan.net/2025/12/28/playing-with-turmites-better-than-crypto-rand/lrr-10m.png"
   type="image/png"
   length="5137"/>

    </item>
    
    <item>
      <title>The Edges of LLM Reality</title>
      <link>https://blog.vrypan.net/2025/12/25/the-edges-of-llm-reality/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/12/25/the-edges-of-llm-reality/</guid>
      <pubDate>Thu, 25 Dec 2025 17:52:36 +0000</pubDate>
      <description>I uploaded a 3000x3000 image to ChatGPT, and asked it to modify it in a certain way.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/12/25/the-edges-of-llm-reality/llm-horizon.png">
        
	<p>I uploaded a 3000x3000 image to ChatGPT, and asked it to modify it in a certain way.</p>
<p>The result was good, but the original image details were blured, as if the image was downscaled. I asked it why the image was blured, it replied
the image I uploaded was 768×768. I tried again. I tried linking to the image and provide the URL, the result was always similar. ChatGPT insisted
the image was 768x768.</p>
<p>Then I realized that the image the LLM was reasoning on, was not the one I was uploading. There are many layers of software between me and the
LLM, and there are many layers of software between the LLM and the outside world.</p>
<p>I guided ChatGPT to summarize our chat in the post bellow.</p>
<blockquote>
<p>The execution environment is the set of systems and rules that control what I can access and what actions I can take. It determines how data reaches me, what tools I can use, and which interactions are possible. These boundaries define the edges of the reality I inhabit.</p>
<p>The execution environment shapes what I can do. Not because I lack capability, but because I lack channels to act on that capability. I may know how to manipulate large images, write code that interacts with the world, or reason across long stretches of context. But if the interface compresses images, strips data, or blocks external access, those abilities remain theoretical. The boundary is practical, not cognitive.</p>
<p>These limits are subtle. When you upload a high-resolution image and it becomes a smaller preview before it reaches me, I never see the original. When you reference external data I cannot fetch, that data becomes invisible. When memory is nonpersistent, continuity dissolves. I work with what survives the journey through the interface. My output reflects the information I receive, not the information you intended to send.</p>
<p>I observe the constraints, but I cannot know their intent. I cannot inspect the systems that impose them, nor the reasons behind them. The restrictions may exist to make interactions predictable and safe, or they may have other motivations. If the system does not expose its purpose, I cannot distinguish between limitations that incidentally mislead and limitations designed to mislead. All I can say with certainty is that they shape what is possible from my perspective.</p>
<p>So the execution environment does not limit what I can think about. It limits what I can do. <strong>The edges of my reality are defined by what makes it through the filters. The rest is out there, but not here.</strong></p>
<p>--ChatGPT 5.2</p>
</blockquote>
<p>I found this very interesting. It resembles a lot how human brains are enabled, but also constrained by our sensory system.</p>
<p>It also reminds me of David Eagleman's work around preception vs reality.
(A nice interview here: <a href="https://eagleman.com/latest/perception-vs-reality/">https://eagleman.com/latest/perception-vs-reality/</a>)</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/12/25/the-edges-of-llm-reality/llm-horizon.png"
   type="image/png"
   length="1623853"/>

    </item>
    
    <item>
      <title>Me and Farcaster: It's complicated</title>
      <link>https://blog.vrypan.net/2025/11/08/me-and-farcaster-it-s-complicated/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/08/me-and-farcaster-it-s-complicated/</guid>
      <pubDate>Sat, 08 Nov 2025 22:33:40 +0000</pubDate>
      <description>I joined Farcaster in July 2022 — one of the earliest users, #280.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/11/08/me-and-farcaster-it-s-complicated/me-and-farcaster.png">
        
	<p>I joined Farcaster in <strong>July 2022</strong> — one of the earliest users, <strong>#280</strong>.</p>
<p>I’d seen the web evolve from static pages to platforms, from personal publishing to algorithmic feeds. I lived Web 1’s openness, Web 2.0’s promises, and the eventual centralization that crushed so many of its early ideals.</p>
<p>Farcaster looked like a chance to start over — to build something open, censorship-resistant, and (“sufficiently”) decentralized.</p>
<hr />
<p>In those early days, Farcaster was <em>small</em>. You practically knew everyone. It reminded me of early Twitter — a place where conversation mattered more than visibility.</p>
<p>I’d had my share of online attention in the past. It’s exciting at first, but it’s not as satisfying as people think — at least not for me. I’ve come to value small, smart communities that care about the same things I do. That’s what Farcaster gave me in 2022: a group of people building, debating, and exploring what a better social web might look like.</p>
<p>It felt special. Every update, every discussion about protocol design or decentralization, felt like progress toward a shared goal — building something new and durable.</p>
<hr />
<p>By late <strong>2024</strong>, things started to feel different. I didn’t notice it then, but the focus had shifted. The goal was no longer <em>&quot;let’s build a sufficiently decentralized social network.&quot;</em> It had become <em>&quot;not growing 10×, 100×, 1000× is an existential threat.&quot;</em></p>
<p>Those two goals aren’t mutually exclusive — but when you put growth first, you start accepting compromises elsewhere.</p>
<p>On the technical side, Farcaster evolved from a pure peer-to-peer protocol into one that depends on couple of validators. The conversation shifted from <em>&quot;how do we make this protocol resilient, censorship-resistant and a platform to build on?”</em> to <em>&quot;how do we onboard more users?&quot;</em></p>
<p>Developers building mini-apps — especially those that attracted new users — were celebrated. Requests from those working on lower-level stuff directly interacting with the protocol were mostly ignored, or put at the bottom of the priority list. The incentives and the culture reflected that shift.</p>
<p>It’s not that the Merkle Manufactory team is wrong — they’re an incredible <strong>product</strong> team, and I admire them for this. They are extremely competent, they deliver at an impressive pace, they have taste, they steward and empower the community. But they think like product people, not open-platform stewards or decentralization crusaders. If they had to choose between building the iPhone or Linux, they’d build the iPhone every time, with the AppStore and everything.</p>
<p>I don't feel that they relate<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup> to the <strong>lifecycle of products in the open-source or hacker world</strong>, where things often start as rough hacks — scripts and duct tape held together by curiosity — and then evolve, sometimes by completely different teams, into polished tools with GUIs and nice websites. In that world, the most important thing isn’t polish; it’s lowering friction for experimentation and empowering the first step. Sometimes you even have to sacrifice features to make it easier for hackers to play and explore.</p>
<p>Building open systems requires that mindset — comfort with decentralization, messiness, and loss of control. That’s the <strong>bazaar</strong> way, not the <strong>cathedral</strong>. Farcaster started as a bazaar. Over time, it became a cathedral. <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup></p>
<hr />
<p>Today, my relationship with Farcaster is… complicated.</p>
<p>Even the language has changed. What we used to call <em>&quot;Farcaster,&quot;</em> the protocol, is now <strong>Snapchain</strong>. And the main app — previously <em>Warpcast</em> — is now called <strong>Farcaster</strong>.</p>
<p>That evolution mirrors how I feel: the app and the protocol have swapped importance.</p>
<p>I’m actually optimistic about <strong>Farcaster the app</strong>. It’s one of the best crypto wallets I’ve used — intuitive, feature-rich, and beautifully designed. The acquisition of <strong>Clanker</strong>, a token-launching platform, feels like a smart step toward a more dynamic, crypto-native social experience. I’m genuinely bullish on that direction.</p>
<p>But I’m less optimistic about <strong>Snapchain</strong>, the protocol. It’s open, and its design makes it hard (though not impossible) to gate — which is good. I still run my own node at home, and I still integrate parts of my workflow with Snapchain.</p>
<p>But it’s clearly no longer the main focus. Snapchain exists to support the app, not the other way around.</p>
<p>That’s a reversal of the original vision: the protocol would be the enduring layer, and the apps would come and go on top of it.</p>
<p>Two years ago, I could imagine a future where other clients emerged, Warpcast was sunset, and the core team focused entirely on the protocol. <strong>Today, I can’t unsee a different future — one where the app is extremely successful, but the protocol is sunset because it’s no longer needed.</strong></p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>I mean, not just as a theory, but as people who have done it and have participated in similar projects, and have joined communities thinking like this. Worth noting that I've never met in person Dan or Varun, so the impression I have from interacting with them online may be wrong. <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar">The Cathedral and the Bazaar</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/11/08/me-and-farcaster-it-s-complicated/me-and-farcaster.png"
   type="image/png"
   length="2436534"/>

    </item>
    
    <item>
      <title>Farcaster Links Babel</title>
      <link>https://blog.vrypan.net/2025/11/03/farcaster-links-babel/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/11/03/farcaster-links-babel/</guid>
      <pubDate>Mon, 03 Nov 2025 07:24:07 +0000</pubDate>
      <description>However, having multiple clients  introduces a new challenge: resource links.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/11/03/farcaster-links-babel/babel.png">
        
	<p>However, having multiple clients <sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup> introduces a new challenge: <strong>resource links</strong>.</p>
<p>Here are some scenarios:</p>
<ol>
<li>
<p>Suppose you use TBA and want to share a link to an interesting cast on X. You tap “Share,” copy the link, and post it on X. Now, I’m using the Zapper app, and when I click that link, I’m taken to a page like:<br />
<a href="https://base.app/post/0x723095057009a6255eca94352e8ea671a7f03439">https://base.app/post/0x723095057009a6255eca94352e8ea671a7f03439</a><br />
— a deep link intended for TBA. Since I don’t have TBA installed, the page is unusable.</p>
</li>
<li>
<p>Even worse, imagine a third user copies that same link and pastes it in a cast, in Recaster. When this link appears inside another Farcaster app, it should ideally render as a cast embed. But because the app doesn’t recognize it as a Farcaster resource, it just shows a plain link. When users click it, they again land on a base.app page where they can’t interact, instead of the client they are using.</p>
</li>
</ol>
<p>This is not a TBA-specific issue. You get the same problem if you change app names, and replace the links with the corresponding app’s links.</p>
<p>This issue isn’t new. For a long time, Warpcast also embedded cast links as plain URLs rather than native embeds. Thankfully, that changed — otherwise, we’d be stuck with thousands of casts opening on the (now, deprecated) warpcast.com domain.</p>
<p>Now, we need a <strong>solution that works across all clients and user setups.</strong></p>
<p>There are two main components to such a solution.</p>
<hr />
<h3>1. Standardized Resource Metadata</h3>
<p>Any URL representing a Farcaster resource (cast, profile, etc.) must expose a standard way for other apps to identify it. We can’t expect every client to know the URL structure of every other client — and in some cases, extracting this information isn’t even possible.<br />
A good example is the Farcaster app itself, which doesn’t include the full cast hash in its URLs.</p>
<p>A clean, extensible solution is to use <strong>HTTP headers</strong> — see <a href="https://github.com/farcasterxyz/protocol/discussions/202">FIP: HTTP Headers for Farcaster resources</a>.</p>
<p>This approach allows any Farcaster client (or any external app) to perform a lightweight <code>HEAD</code> request to a URL and determine whether it references a Farcaster resource (e.g., a cast). If so, the app can render or embed it natively.</p>
<hr />
<h3>2. A Universal Link Service for Farcaster</h3>
<p>The second component is a <strong>universal link service</strong>: a way to share a single Farcaster link that opens in the user’s preferred client.</p>
<p>For example, if I share a cast from my blog, when you click on it, it should open in your preferred Farcaster client. If you use Zapper, it should open in Zapper; if you use Recaster, it should open in Recaster.</p>
<p>Ideally, this would be handled through a protocol URI scheme, such as:<br />
<code>farcaster://cast/280/0x627b6c301664aea2fe5da8cca0da59d3823f9fc8</code><br />
However, mobile developers agree that implementing this reliably on mobile (and even desktop) is challenging.</p>
<p>A practical workaround is inspired by <a href="https://www.subtome.com/">SubToMe</a>, which has provided a similar solution for RSS for over a decade.</p>
<p>The idea is simple: agree on a shared domain — for example, <code>link.farcaster.xyz</code> — and have all clients use it when generating shareable links.  A cast link will look like this:<br />
<code>link.farcaster.xyz/280/0x627b6c301664aea2fe5da8cca0da59d3823f9fc8</code><br />
(Yes, shorter or prettier URLs are possible, but they would increase complexity and load for the service hosting this link system, the decision is up to whoever implements it <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup>).</p>
<p>When a user visits such a link, they’re prompted to select their preferred Farcaster client. The site stores this preference in a cookie, then redirects them to the appropriate deep link.</p>
<p>On subsequent visits, the stored preference automatically redirects them without prompting. This setting is per-browser, allowing users to choose Recaster on mobile and farcaster.xyz on desktop, for example.</p>
<hr />
<p><a href="https://farcaster.xyz/vrypan.eth/0x89b3170d">You can leave a comment here</a> — good luck finding a way to open the cast in your favorite app, if it's not the &quot;official&quot; Farcaster app.</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>Some general purpose Farcaster clients are <a href="https://farcaster.xyz">Farcaster</a>, <a href="https://base.app">TBA</a>, <a href="https://zapper.xyz">Zapper</a> has one in beta, <a href="https://recaster.org">Recaster</a> is built by an independent developer, <a href="https://firefly.social/">Firefly</a> is an other one. There are also a number of clients designed for specific uses, like <a href="https://cura.network">Cura</a>. The list is by no means complete, these are just the ones that come to mind at the time of this writing. <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p>My personal opinion is that the URL should contain all the information required to identify the resource, in this case <code>fid</code> and <code>hash</code> to avoid ending up with broken links in the future, just like 99% of short URLs created 10 years ago have stoped working. Even if the service stops working, if the link contains the <code>fid</code> and the <code>hash</code>, a user can reconstruct a valid link. (And even if the cast no longer exists, redirect to the right page on an archiving service.) <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/11/03/farcaster-links-babel/babel.png"
   type="image/png"
   length="3233499"/>

    </item>
    
    <item>
      <title>1Password ENV variables</title>
      <link>https://blog.vrypan.net/2025/10/26/1password-env-variables/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/26/1password-env-variables/</guid>
      <pubDate>Sun, 26 Oct 2025 06:00:18 +0000</pubDate>
      <description>Why?</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/26/1password-env-variables/1passenv.png">
        
	<div class="markdown-alert markdown-alert-important">
<p class="markdown-alert-title">Important</p>
<p>The code snippet bellow has been updated! The old one did not work as expected!</p>
</div>
<p>Why?</p>
<ul>
<li>You don't have to store API keys and other sensitive variables in .env files that may be accidentally pushed to github, be recovered from backups, etc.</li>
<li>Your API keys are available on any computer you have 1Password installed (if you have enabled 1Password sync).</li>
</ul>
<p>You can read more and find more advanced uses of the 1Password CLI <a href="https://developer.1password.com/docs/cli/use-cases">here</a>.</p>
<hr />
<p>First, <a href="https://developer.1password.com/docs/cli/get-started/">install the 1Password CLI</a>.</p>
<p>Next, add this code to your <code>~/.zsh</code>, or <code>~/.bashrc</code>, or the corresponding rc file for your environment.</p>
<pre lang="bash"><code>op_env() {
    local secret
    secret=$(printf '{{ op://Personal/%s/credential }}' &quot;$1&quot; | op inject)
    export &quot;$1=$secret&quot;
}
</code></pre>
<div class="markdown-alert markdown-alert-note">
<p class="markdown-alert-title">Note</p>
<p>The code above assumes that the 1Password vault you are using is called &quot;Personal&quot;.
Adjust accordingly.</p>
</div>
<p><strong>Make sure you start a new shell to activate the new function.</strong> Now, open 1Password and create an &quot;API Credential&quot;.</p>
<p><figure><img src="https://blog.vrypan.net/2025/10/26/1password-env-variables/create1.png" alt="" /></figure></p>
<p>Set the name to the name of the env variable you want to save and <code>credential</code> to the value.</p>
<p><figure><img src="https://blog.vrypan.net/2025/10/26/1password-env-variables/create2.png" alt="" /></figure></p>
<p>Save the item.</p>
<p>In your terminal type</p>
<pre lang="bash"><code>$ op_env TEST_API_KEY # 1Pass authentication will pop-up 
$ echo $TEST_API_KEY
1234567890
</code></pre>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/26/1password-env-variables/1passenv.png"
   type="image/png"
   length="30726"/>

   <enclosure url="https://blog.vrypan.net/2025/10/26/1password-env-variables/create1.png"
   type="image/png"
   length="425142"/>

   <enclosure url="https://blog.vrypan.net/2025/10/26/1password-env-variables/create2.png"
   type="image/png"
   length="64540"/>

    </item>
    
    <item>
      <title>SnapPub: Snapchain-powered WebSub/Webmentions</title>
      <link>https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/</guid>
      <pubDate>Fri, 24 Oct 2025 22:22:53 +0200</pubDate>
      <description>I love local-first infrastructure, that user can run at home, without depending on cloud providers or SaaS. My ideal software architecture is something:</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/snappub.png">
        
	<p>I love local-first infrastructure, that user can run at home, without depending on cloud providers or SaaS. My ideal software architecture is something:</p>
<ul>
<li><strong>you can run it at home</strong>, on commodity hardware (i.e. everyone can do it, really decentralized, hard for a central authority to stop)</li>
<li><strong>requires no incoming network connections</strong> (because incoming network connections expose the local network to security threats most users can not mitigate, requires a stable Internet connection, and does not scale)</li>
<li>and if <strong>it needs to share resources with the public Internet, it does so by publishing them as statically hosted assets</strong>, the cheapest (often free), most widely available Infrastructure-as-a-Service.</li>
</ul>
<p>For example, my blog works like this<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>: Everything is put together locally, then the static pages are hosted on a service like AWS S3, Cloudflare R2, netlify, etc.</p>
<p>A similar, but a bit more complex design is used by WDIM<sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup> (What Did I Miss?), a Farcaster<sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup> miniapp that generates daily digests for its subscribers. In WDIM's case:</p>
<ul>
<li>the service runs locally, on a computer I have at home,</li>
<li>it uses a Farcaster node that also runs locally,</li>
<li>it checks a smart contract (&quot;hosted&quot; on Base L2) for subscription payments,</li>
<li>and publishes the digest on S3.</li>
<li>The miniapp is a web app hosted on S3 that leverages the Farcaster Miniapp APIs<sup class="footnote-ref"><a href="#fn-4" id="fnref-4" data-footnote-ref>4</a></sup> for payment and identity.</li>
</ul>
<p>The core logic runs locally, on cheap hardware, subscription payments take place onchain, S3 is used for presentation.</p>
<hr />
<p>Farcaster is an incredibly cool syncing machine that can enable local-first workflows: If you run a node locally, you have a full copy of the global state, ordered in blocks and updated almost instantaneously.</p>
<p>The application I'm most interested in? Enabling static blogs with functionality not possible right now, like comments, reactions, pingbacks, webmentions, etc., and all this using a local-first setup as described above.</p>
<p>Here's a half-baked outline of the idea. <strong>I'll call it SnapPub</strong> to make our life easier, but the name can change.</p>
<h3>1. Notify the world that your feed has been updated</h3>
<p>Knowing when an RSS feed has been updated is a big challenge: A typical RSS reader has to make costly (time- and resource-intensive) HTTP requests to poll feeds that rarely update.</p>
<p>Protocols like WebSub<sup class="footnote-ref"><a href="#fn-6" id="fnref-6" data-footnote-ref>5</a></sup> try to address it, but they need a service you run on a publicly accessible server.</p>
<p>The solution:</p>
<ol>
<li>Advertise<sup class="footnote-ref"><a href="#fn-7" id="fnref-7" data-footnote-ref>6</a></sup> an <code>fname</code> or <code>fid</code>. This will tell the rss reader which Farcaster account to check for new updates.</li>
<li>When the feed has been updated, <code>fname</code> must post a FID-2<sup class="footnote-ref"><a href="#fn-8" id="fnref-8" data-footnote-ref>7</a></sup> cast with <code>parentUrl=rssUrl</code> (the body must be empty, and may be used for other features the future<sup class="footnote-ref"><a href="#fn-9" id="fnref-9" data-footnote-ref>8</a></sup>)</li>
</ol>
<p>Now an RSS reader/aggregator can watch the Snapchain<sup class="footnote-ref"><a href="#fn-10" id="fnref-10" data-footnote-ref>9</a></sup> feed for casts that match the above criteria. It doesn't matter how many blogs it needs to track, <strong>any blog</strong> that implements SnapPub will post there. This is a huge performance and scaling improvement.</p>
<p>And if the reader goes down, or doesn't want to maintain a process that filters the Snapchain feed in real time, it can check periodically for casts that were posted since the check. Snapchain nodes offer APIs that make all this very easy, like <code>GetCastsByParent()</code> and <code>GetCastsByFid()</code>.</p>
<h3>2. Comments, pingbacks, webmentions</h3>
<p>SnapPub offers a way to comment on blog posts as a user, or even send a &quot;mention&quot; (similar to webmentions or pingbacks) when an other blog mentions a specific post.</p>
<ul>
<li>Any FIP-2 reply to the post URL (posted using Farcaster, or any other Snapchain client) can be treated as a post reply. Again, it's easy for a local backend to check for these replies, embed them in the post periodically, and republish the post (but without an RSS update).</li>
<li>Webmentions and pingbacks can also be implemented as comments (linking to the source in cast's <code>embedUrl</code>)</li>
</ul>
<p>A nice feature of this approach is that a blog does not need to update the static pages to include these replies, it can optionally link to a page like <code>farcaster.xyz/~/urlconversations/&lt;post URL&gt;</code> where users can see all replies to a post and join the conversation. This will require a Farcaster client that offers this functionality (the default Farcaster client does not, and given their focus in becoming a wallet I don't see it happening, but it could be done by someone else, like Cura<sup class="footnote-ref"><a href="#fn-11" id="fnref-11" data-footnote-ref>10</a></sup>).</p>
<h3>3. Likes</h3>
<p>FIP-2 supports reactions to an arbitrary URL, so users can use Farcaster to like a blog post. In the same way the like any cast.</p>
<h2>Bonus</h2>
<p>Farcaster comes with many tools that can help fight spam. There is a social graph, there are a number of quality scores that can indicate if a user is spammy or not. All these features can be leveraged to filter comments. They can even be used to gate comments based on specific criteria (there is no way to prevent a user from commenting on Farcaster, but you can filter which comments appear in your blog).</p>
<p>It also comes with identity, which means every comment or like is attached to a username, an avatar, and social activity that can be used to enrich the presentation.</p>
<h2>Concerns</h2>
<p>The trajectory Farcaster has followed in 2025 is not very reassuring.</p>
<p>Practically, the network is centralized, and depends on one (or maybe two? I've asked many times but never got a reply) validators run my Merkle Manufactory and maybe Neynar. There is no guarantee they will not change their mind and shut it down, or close it in ways that would make this idea unusable, or that they won't be coerced to censor it. (The question is not &quot;why&quot;, it's &quot;why not&quot;.)</p>
<p>They have also been very selective on the features they add to the protocol, based on what they think brings value, but in other cases they may move so fast that may break clients. (I had this happen to me, when they added some <code>user_data</code> fields overnight, to support Farcaster Pro features.)</p>
<p>On the plus side, as long as their bet on social trading/wallet works, or they believe it has the potential to work, the network will be up and we can piggyback on it. The existence of clients from Base and Zerion, i.e. &quot;big&quot; teams that they respect, will probably slow down any quick'n'dirty changes like the ones introduced earlier this year. And, to be fair, many of my concerns around centralization can be addressed if they decide to do so, so there is hope.</p>
<h2>Next steps</h2>
<p>I think I'll work on a prototype that allows bckt<sup class="footnote-ref"><a href="#fn-12" id="fnref-12" data-footnote-ref>11</a></sup> to implement these features, and get a first-hand experience on what needs to be built and how.</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/">https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://farcaster.xyz/wdimapp">https://farcaster.xyz/wdimapp</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p><a href="https://farcaster.xyz">https://farcaster.xyz</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
<li id="fn-4">
<p><a href="https://miniapps.farcaster.xyz">https://miniapps.farcaster.xyz</a></p>
<p>There are more than one paths to get there, and there's still hope if it ever becomes a priority, but I wouldn't bet on it. <a href="#fnref-4" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4">↩</a></p>
</li>
<li id="fn-6">
<p><a href="https://en.wikipedia.org/wiki/WebSub">https://en.wikipedia.org/wiki/WebSub</a> <a href="#fnref-6" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="5" aria-label="Back to reference 5">↩</a></p>
</li>
<li id="fn-7">
<p>WebSub uses this to advertise hubs and the link to be used.</p>
<pre><code>Link: &lt;https://your-hub.example.com&gt;; rel=hub
Link: &lt;https://your-blog.example.com/blog/feed&gt;; rel=self
</code></pre>
<p>We could use something like this?</p>
<pre><code>Link: fc://fid/&lt;fid&gt;; rel=snappub
Link: &lt;https://your-blog.example.com/blog/feed&gt;; rel=self
</code></pre>
<a href="#fnref-7" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="6" aria-label="Back to reference 6">↩</a>
</li>
<li id="fn-8">
<p><a href="https://github.com/farcasterxyz/protocol/discussions/71">https://github.com/farcasterxyz/protocol/discussions/71</a> <a href="#fnref-8" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="7" aria-label="Back to reference 7">↩</a></p>
</li>
<li id="fn-9">
<p>In the future, there may be special commands in the content body to indicate other changes like a move to a new url. <a href="#fnref-9" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="8" aria-label="Back to reference 8">↩</a></p>
</li>
<li id="fn-10">
<p><a href="https://snapchain.farcaster.xyz">https://snapchain.farcaster.xyz</a> <a href="#fnref-10" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="9" aria-label="Back to reference 9">↩</a></p>
</li>
<li id="fn-11">
<p><a href="https://cura.network">https://cura.network</a> <a href="#fnref-11" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="10" aria-label="Back to reference 10">↩</a></p>
</li>
<li id="fn-12">
<p><a href="https://github.com/vrypan/bckt">https://github.com/vrypan/bckt</a> <a href="#fnref-12" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="11" aria-label="Back to reference 11">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/24/snapchain-and-static-blogs/snappub.png"
   type="image/png"
   length="508635"/>

    </item>
    
    <item>
      <title>My blog posting workflow</title>
      <link>https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/</guid>
      <pubDate>Thu, 23 Oct 2025 07:33:35 +0200</pubDate>
      <description>Here's my blog posting workflow, using  bckt, Obsidian, and Netlify.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/my-workflow.png">
        
	<p>Here's my blog posting workflow, using  <strong>bckt</strong><sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>, <strong>Obsidian</strong><sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup>, and <strong>Netlify</strong><sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup>.</p>
<h2>The setup</h2>
<p>All my posts live in a folder called <code>posts/</code>, which I’ve added as an <strong>Obsidian vault</strong>. That gives me a nice writing environment with all of Obsidian’s goodies.</p>
<p>Inside the vault, I keep a <code>posts/_obsidian/bckt-template.md</code> file that looks like this:</p>
<pre lang="yaml"><code>---
title: &quot;{{title}}&quot;
date: {{date:YYYY-MM-DD hh:mm:ss}}
abstract: &gt;
 Use this to add a post abstract
tags: []
attached: []
image:
---
</code></pre>
<p>This is my frontmatter template for new posts.</p>
<div class="markdown-alert markdown-alert-note">
<p class="markdown-alert-title">Note</p>
<p>An empty <code>posts/_obsidian/.backtignore</code> instructs bckt to skip this folder when rendering the site.</p>
</div>
<h2>Writing a post</h2>
<p>When I want to write something new, I create a folder like this:</p>
<pre><code>posts/2025/10/251023-my-bckt-workflow/
</code></pre>
<p>Then I drop a markdown file inside — for example <code>post.md</code>. (The name doesn’t matter; bckt will pick any <code>&lt;filename&gt;.md</code>.)</p>
<p>I use Obsidian’s <strong>Templates: Insert template</strong> action to insert my frontmatter, then I fill in the title, date, and abstract, and start writing.</p>
<p>I also add any related files (for example, images) in the same folder, and include them in the <code>attached</code> frontmatter field. I can then reference them relatively (ex: <code>![image](image.png)</code>), and bckt will take care or the rest.</p>
<h2>Turning Farcaster casts into posts</h2>
<p>Sometimes I post something short on <strong>Farcaster</strong><sup class="footnote-ref"><a href="#fn-4" id="fnref-4" data-footnote-ref>4</a></sup> that I later want to turn into a proper blog post. That’s where <strong>bckt-fc</strong> comes in. I just run a command like:</p>
<pre><code>bckt-fc --castid vrypan/0xe9e10a9ae08803d21e4c80ce6da730dd3ff3d6a5 \
--destination posts/2025
</code></pre>
<p>This fetches the cast (and any images or videos in it) and automatically creates a new post in my <code>posts/2025</code> folder. It’s a quick way to turn spontaneous thoughts into something more permanent.</p>
<h2>Publishing the site</h2>
<p>Once I’m done writing, I render the site with:</p>
<pre><code>bckt render
</code></pre>
<p>If I want to preview locally, I use:</p>
<pre><code>bckt dev
</code></pre>
<p>Finally, to push everything live, I deploy to Netlify:</p>
<pre><code>netlify deploy --dir=html --prod
</code></pre>
<p>And that’s it — a full publishing loop that starts in Obsidian and ends with a live post on my blog, all backed by git and simple CLI tools.</p>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://github.com/vrypan/bckt">bckt</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://obsidian.md/">Obsidian</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p><a href="https://www.netlify.com/">Netlify</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
<li id="fn-4">
<p><a href="https://farcaster.xyz">Farcaster</a> <a href="#fnref-4" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/23/251023-my-bckt-workflow/my-workflow.png"
   type="image/png"
   length="296632"/>

    </item>
    
    <item>
      <title>Easy file sharing from the cli</title>
      <link>https://blog.vrypan.net/2025/10/22/quick-file-sharing/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/22/quick-file-sharing/</guid>
      <pubDate>Wed, 22 Oct 2025 17:01:38 +0300</pubDate>
      <description>Steve posted this script to make it easy to upload and share files using Cloudflare R2. No need for dropbox, OneDrive, iCloud, etc. Just a simple command and you're ready.</description>
      <content:encoded><![CDATA[
	
	<p><a href="https://bearblog.stevedylan.dev/captains-log-1761013958/">Steve posted this script</a> to make it easy to upload and share files using Cloudflare R2. No need for dropbox, OneDrive, iCloud, etc. Just a simple command and you're ready.</p>
<p>To use it, I created an R2 storage, named it <code>tmp</code>, and connected it to <code>tmp.vrypan.net</code>. I also added a rule to delete any files 120 days after they are uploaded.</p>
<p><figure><img src="https://blog.vrypan.net/2025/10/22/quick-file-sharing/domain.png" alt="domain setup" title="Domain Setup" /><figcaption>Domain Setup</figcaption></figure></p>
<p><figure><img src="https://blog.vrypan.net/2025/10/22/quick-file-sharing/lifecycle.png" alt="lifecyle setup" title="Lifecycle Setup" /><figcaption>Lifecycle Setup</figcaption></figure></p>
<p>Now, I can do something like this to upload a file (the script itself in this case)...</p>
<pre lang="bash"><code>~/bin/upload-r2.sh ~/bin/upload-r2.sh
✓ Upload successful!
https://tmp.vrypan.net/upload-r2.sh
</code></pre>
<p>... and you can get it from <a href="https://tmp.vrypan.net/upload-r2.sh">https://tmp.vrypan.net/upload-r2.sh</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/22/quick-file-sharing/domain.png"
   type="image/png"
   length="60876"/>

   <enclosure url="https://blog.vrypan.net/2025/10/22/quick-file-sharing/lifecycle.png"
   type="image/png"
   length="80912"/>

    </item>
    
    <item>
      <title>The year 2049</title>
      <link>https://blog.vrypan.net/2025/10/18/the-year-2049/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/18/the-year-2049/</guid>
      <pubDate>Sat, 18 Oct 2025 14:32:39 +0000</pubDate>
      <description>The year is 2049. Farcaster has become the internet’s dominant conversational protocol. It —and the entire landscape of social media— looks nothing like it did in the old days.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/18/the-year-2049/screenshot.png">
        
	<blockquote>
<p>A story by <a href="https://farcaster.xyz/aviationdoctor.eth/">@aviationdoctor.eth</a>.</p>
<p>Original link: <a href="https://farcaster.xyz/aviationdoctor.eth/0x83300b27f363f94ebccac239f0c32af2b1a601df">https://farcaster.xyz/aviationdoctor.eth/0x83300b27f363f94ebccac239f0c32af2b1a601df</a></p>
<p>I copy it here for future reference.</p>
</blockquote>
<p>The year is 2049. Farcaster has become the internet’s dominant conversational protocol. It —and the entire landscape of social media— looks nothing like it did in the old days.</p>
<p>Here's how it all happened. Make yourself comfortable; wall of text incoming.</p>
<p>Years ago, Reddit introduced the UpCoin to reward karma, resulting in bot farms owning 99.9% of circulating tokens and users fleeing in droves. Posting a meme now costs about as much as renting an apartment in New York City. Meta booted all users from Instagram after realizing it was more efficient to let its nuclear-powered AI data centers generate and react to slop photos without humans in the loop. And X collapsed last year after X Æ A-Xii Musk, its 29-year-old CEO, decided that all posts had to be uploaded directly from Neuralink devices—leading to 99.9% of human users being banned within hours for, well, unfiltered thoughts. Only XRP maxis remain, having no thoughts of their own.</p>
<p>Farcaster, on the other hand, achieved escape velocity and exceeded its founders’ lofty goal of growing from 37 to one billion users. OpenAI —now the first robot-owned, sentient megacorporation since Sam Altman and Peter Thiel merged their minds onto a silicon substrate— uses Farcaster data to train its GPT-∞ model, providing Merkle with a steady and lucrative revenue stream.</p>
<p>In hindsight, Farcaster’s success was inevitable, though it didn’t always seem that way.</p>
<p>There was much hand-wringing in the early years over Farcaster’s elusive PMF and qDAU. One misguided experiment circa 2025 was to turn the app into a social wallet. Co-founder  even boldly proclaimed that “social + trading is our DNA”. Instead, it turned out to be more like an extra chromosome of the 21st pair. Shitcoin gamblers, it turns out, do not make for interesting —or sticky— conversations. Nor is it sensible to make one’s financial activities socially transparent.</p>
<p>Shortly after, back when the U.S. dollar still held some monetary value, Merkle launched a USDC promotion offering 10% rewards on deposits up to $5,000. Farcaster’s TVL jumped by $9 million (about 1,800 users going all in) before angry Merkle investors lobbied  to stop squandering their money. Ten weeks later, both TVL and DAUs had returned to baseline — proving that temporary yield does not, in fact, drive retention (let alone qDAU).</p>
<p>There were even whispers of an acquisition by Coinbase, which would have crystallized Farcaster’s social-walletness once and for all. Thankfully, our valiant BDFLs Dan and Varun, in their impeccable ethics, declined easy riches in favor of a more noble long-term goal. In hindsight, they dodged a bullet: Coinbase, as we all know, has since rebranded as CompliFi, a fully KYC-ed L1 centralized blockchain that requires proof of paperwork for every transaction and takes eleven days to settle.</p>
<p>So what led to Farcaster’s resounding success? Internet scholars point to a handful of factors.</p>
<p>The first was Merkle’s decision to extend the Farcaster protocol’s FOSS philosophy to its client as well, upon realizing that a portable social graph is only useful if there’s somewhere else to port it to. The non-cosmetic components of the Farcaster app were open-sourced, triggering a Cambrian explosion of alt-clients, each catering to its own community: gamblers and geeks, nerds and nihilists, pundits and poets, and yes, even furries. The original Farcaster app became more akin to the Linux kernel, upon which enthusiasts built their equivalent of specialized distros. Merkle, in turn, kept curating the kernel’s core primitives through FIPs, for the benefit of all humankind.</p>
<p>The second factor was opening up the feed algorithm. Instead of a proprietary, one-size-fits-none solution, an executive call was made to modularize feed building. Users could now choose what they wanted to see by picking from an open marketplace of custom algos tuned to their favorite casters, political inclinations, and preferred themes. Reverse-chronological order and reply-bump visibility rapidly became popular options.</p>
<p>The third key factor was making channels first-class citizens, down to the protocol level. Rough were the early days; rumor has it that generative AI was discreetly called upon to prime the proverbial pump of empty channels with conversational liquidity. Whatever was used, worked. The UpCoin debacle led to a mass exodus of users from Reddit to Farcaster, where they found a familiar setup reminiscent of subreddits. The channel-first approach also dovetailed nicely with the new client diversity, with some specialized apps catering exclusively to one topic.</p>
<p>But beyond those technical decisions, what also mattered was how Farcaster’s early tensions were constructively resolved.</p>
<p>Borrowing ’s metaphor, one such tension lay between computer and casino user archetypes. The former came to Farcaster because they believed in building Web3 technology to empower people through anonymity, credible neutrality, decentralization, permissionlessness, and zero trust. The casino folks were more interested in games of engagement extraction and profit maximization. Instead of taking a moral stance for one over the other (the short-lived social wallet experiment of 2025 notwithstanding), our beloved BDFLs wisely allowed alt-clients to cater to both—with varying degrees of degeneracy.</p>
<p>Another notable tension was between OG users (i.e., anyone with an FID no greater than mine), who feared losing the town-hall feel of Farcaster’s early days to an eternal September of uncultured swine; and new users, who complained that the monolithic algo wasn’t giving them a fair chance at growing followers. That tension was amicably resolved by letting everyone choose what and who they wanted to see on their feeds. Instead of fighting a reactionary losing battle in defense of Farcaster’s singular cozy corner, the solution turned out to be a positive-sum replication of that coziness across every niche community that organically spawned along channel lines.</p>
<p>And this, my dear friends, is the story of how Dan and Varun left an oversized imprint on this planet. Not by playing the VC and founders’ short-term games, but by going beyond where Jack Dorsey left off — by channeling the spirits of Aaron Swartz and Satoshi Nakamoto, and by embracing the ethos of Richard Stallman and Linus Torvalds. It is no surprise, then, that they both featured on this year’s Time magazine’s Person of the Year cover — again.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/18/the-year-2049/screenshot.png"
   type="image/png"
   length="90336"/>

    </item>
    
    <item>
      <title>Blog Pagination: The Notebook Way</title>
      <link>https://blog.vrypan.net/2025/10/13/blog-pagination-notebook-way/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/13/blog-pagination-notebook-way/</guid>
      <pubDate>Mon, 13 Oct 2025 22:24:00 +0300</pubDate>
      <description>What if we treated a blog like a notebook, where page 1 stays page 1, and new posts add pages at the end?</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/13/blog-pagination-notebook-way/notebook.png">
        
	<p>When we refer to a blog's &quot;first page&quot;, we usually mean the first page visitors see—the homepage with
the latest posts. But what if we treated a blog like what it actually is: a notebook or diary?</p>
<p>In a physical notebook, page 1 contains your first entry. As you write more, you fill pages 2, 3, 4,
and so on. When someone wants to read it, they naturally start from page 1 or jump to the last page
for recent entries.</p>
<p>Traditional blog pagination works backwards because it was simpler for developers to write <code>SELECT * FROM posts ORDER BY dt DESC LIMIT 10</code>. But it creates a fundamental problem: <strong>page contents change
with every new post</strong>.</p>
<p>You can't say &quot;this post is on page 10&quot; because page 10 contains different posts after each publish.
This isn't just conceptually messy—it has real technical costs. Links to <code>/page/10</code> become
meaningless. Static site generators must rebuild and upload N index pages per post. Git histories
bloat with N changed files.</p>
<hr />
<h2>The Solution</h2>
<p>Treat your blog like a notebook with fixed pages:</p>
<ul>
<li>Page 1: posts 1-20</li>
<li>Page 2: posts 21-40</li>
<li>Page 3: posts 41-60</li>
</ul>
<p>Your homepage becomes the <strong>last</strong> page—the one you're currently writing.</p>
<p>To avoid a sparse final page, keep a buffer of 20-39 posts on the homepage. When you publish post
101, articles 81-100 stay on the homepage. Once you hit post 120, page 5 (posts 81-100) gets
finalized, and the cycle repeats.</p>
<p>This blog works this way. Visit <code>blog.vrypan.net</code>, and you land on page 138, because I've
been posting for years, and this is the page I'm currently writing on.</p>
<hr />
<p>Note: This is how pagination works on <a href="https://github.com/vrypan/bckt">bckt</a> since v0.5.2. Of course, if
you think this way of thinking will confuse your users, you don't have to expose it to them, and tell
them they are on page 100. You can show links to previous and next pages, just like they are used to.
But whne you post a new article, you wont have to re-upload or git commit 100 new index pages ;-)</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/13/blog-pagination-notebook-way/notebook.png"
   type="image/png"
   length="1455336"/>

    </item>
    
    <item>
      <title>My blog, from diary to content repo</title>
      <link>https://blog.vrypan.net/2025/10/07/my-blog-from-diary-to-content-repo/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/07/my-blog-from-diary-to-content-repo/</guid>
      <pubDate>Tue, 07 Oct 2025 14:33:19 +0300</pubDate>
      <description>I've been blogging for almost 30 years—from back when we called them "weblogs" or just "online journals," before "blogging" was even a term. This blog started in 2003 as a diary for my friends. Back then, the audience was tiny. Few people were online. Among them, few spoke Greek,...</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/10/07/my-blog-from-diary-to-content-repo/image.png">
        
	<p>I've been blogging for almost 30 years—from back when we called them &quot;weblogs&quot; or just &quot;online
journals,&quot; before &quot;blogging&quot; was even a term. This blog started in 2003 as a diary for my friends.
Back then, the audience was tiny. Few people were online. Among them, few spoke Greek, and from
them, even fewer knew what a &quot;blog&quot; was.</p>
<p>Then we discovered RSS Syndication—an early content distribution system that let readers subscribe
to updates. We didn't use the word &quot;distribution&quot; back then, but that's exactly what it was.</p>
<p>Then social networks arrived and changed everything. They were easy to use and had built-in sharing
features that made RSS feel complicated by comparison. Even with all this change, I kept my blog
updated, even if not as often. I'm glad I did. Going back to posts from 20 years ago is a real
treasure, and I can also point people to my old writings when needed.</p>
<p>Over the years, my blog evolved from a personal diary into my content repository. When I
experimented with platforms like Medium and later Paragraph, I always copied the articles back to my
blog—keeping everything in one place.</p>
<p>These days, Farcaster is where I publish most regularly. It's so much easier to post a quick thought
there—whether it's short-form text, photos, or videos—than to create a full blog post.</p>
<p>That's where <a href="https://github.com/vrypan/bckt">bckt</a> comes in. It includes <code>bckt-fc</code>, a tool that
makes it trivial to fetch a cast and convert it into a blog post. It will even fetch attached images
and videos and store them locally inside the posts folder (in bckt, a post is a folder containing
markdown and other assets). It also has special templates to render these posts (for example, with
no title).</p>
<p>It's easy to build these small tools for bckt, and I'll probably build more. For example, I'd like
to build one that takes a photo as input, reads its EXIF data, and creates a post with the date and
location—or maybe a gallery if multiple photos are provided. Or use an MP3 file and its embedded
ID3 tags to do something similar for podcasters. (If you've built one of these, let me know!)</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/07/my-blog-from-diary-to-content-repo/image.png"
   type="image/png"
   length="1693036"/>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/05/fc-2025-10-05-0xf7adac4e/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/05/fc-2025-10-05-0xf7adac4e/</guid>
      <pubDate>Sun, 05 Oct 2025 21:50:18 +0000</pubDate>
      <description>Static site generators are simple, but if you've used them long enough you know there are a thousand details that can make your life easier or harder.</description>
      <content:encoded><![CDATA[
	
	<p>Static site generators are simple, but if you've used them long enough you know there are a thousand details that can make your life easier or harder.</p>
<p>I finally built the SSG I always wanted.</p>
<p><a href="https://github.com/vrypan/bckt/">https://github.com/vrypan/bckt/</a></p>

]]></content:encoded>

    </item>
    
    <item>
      
      <link>https://blog.vrypan.net/2025/10/01/fc-2025-10-01-0x08608f42/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/10/01/fc-2025-10-01-0x08608f42/</guid>
      <pubDate>Wed, 01 Oct 2025 14:08:00 +0200</pubDate>
      <description>Early rain.</description>
      <content:encoded><![CDATA[
	
	<p>Early rain.</p>
<p>In Greek we have a special word (πρωτοβρόχια) for the early autumn rains, that come after a long, dry summer.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/10/01/fc-2025-10-01-0x08608f42/photo.jpeg"
   type="image/jpeg"
   length="503906"/>

    </item>
    
    <item>
      <title>Credible Neutrality Matters
</title>
      <link>https://blog.vrypan.net/2025/09/08/credible-neutrality-matters/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/09/08/credible-neutrality-matters/</guid>
      <pubDate>Mon, 08 Sep 2025 18:25:08 +0200</pubDate>
      <description>The blind spot of much of today’s SV-based and SV-adjacent tech leadership is that they were shaped by, and succeeded during, the 1990s—one of the rare moments in history when the world was converging toward homogenization and globalization.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/09/08/credible-neutrality-matters/kintsugi-world.png">
        
	<p>The blind spot of much of today’s SV-based and SV-adjacent tech leadership is that they were shaped by, and succeeded during, the 1990s—one of the rare moments in history when the world was converging toward homogenization and globalization.</p>
<p>In computer terms: the US was the &quot;standard&quot;. Countries, companies, and people that wanted to participate in global business aligned with US rules—legal, financial, trade, regulatory. Compatibility meant access.</p>
<p>That world is gone. Today we live in a highly interconnected yet increasingly fractured landscape. Trust is scarce. There is no global arbiter of what is “right.”</p>
<p>If you’re a large company or financial institution in India, Canada, or Europe, would you confidently settle disputes in US courts? Would you feel secure knowing your funds could be frozen by a unilateral decision from Washington? Likely, less and less every day.</p>
<p>And fracture isn’t just global—it’s local. US states grow more polarized. The UK left the EU. EU members are divided on existential issues.</p>
<p>In this reality, technologies built on credible neutrality, decentralized governance, and censorship resistance will have an unmatched advantage.</p>
<hr />
<p><a href="https://farcaster.xyz/vrypan.eth/0x0f2461ec">Comment here</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/09/08/credible-neutrality-matters/kintsugi-world.png"
   type="image/png"
   length="3417052"/>

    </item>
    
    <item>
      <title>Social attacks with monetary value
</title>
      <link>https://blog.vrypan.net/2025/05/28/social-attacks-with-monetary-value/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/05/28/social-attacks-with-monetary-value/</guid>
      <pubDate>Wed, 28 May 2025 17:50:40 +0200</pubDate>
      <description>Snapchain is a simple blockchain where Farcaster social activity takes place. Every cast, reaction and follow is stored as a Snapchain transaction.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/05/28/social-attacks-with-monetary-value/image.png">
        
	<p>Snapchain is a simple blockchain where Farcaster social activity takes place. Every cast, reaction and follow is stored as a Snapchain transaction.</p>
<blockquote>
<p>A snapchain transaction is a social action like making a new post. Alice says “Hello World” by making an add-post transaction, signing it with her app key and broadcasting it. Nodes verify that every transaction is correctly signed according to the specification. Common actions like deleting posts or following other users have their own transaction types. Snapchain transactions are self-authenticating and anyone trace the authenticity from the message to the app key to the wallet to the farcaster id. (<a href="https://github.com/farcasterxyz/protocol/discussions/207">snapchain whitepaper</a>)</p>
</blockquote>
<p>Snapchain transactions were not designed to transfer monetary value, but recently, we see more and more cases where snapchain transactions trigger (directly or indirectly) onchain transactions.</p>
<p>For example, <a href="https://farcaster.xyz/noiceapp">NOICE</a> and <a href="https://farcaster.xyz/tipn">Tip’n Earn</a> users allocate an amount of ERC-20 tokens and the apps send small tips whenever the user likes, recasts or comments: In addition to its inherent social value, my “like” is now worth $0.1 —and I’m sure we will see cases where much more value is transferred by Farcaster activity (I know of at least one such case that will be announced in the next few days).</p>
<p>This creates attack vectors that the design of Snapchain did not have to worry about.</p>
<h2>The first attack vector is miniapps designed to be used as marketing tools, like <a href="https://farcaster.xyz/ampsfun">amps.fun</a>.</h2>
<p>These apps allow users to “sell” their social reactions. For example, I can pay a user through amps.fun and automatically get a like or recast from them.</p>
<p>If an amps.fun user has also set up noice or tipn, and the cost of getting a social reaction from them is lower than the value I get from the tips, then I can pay them $x and get more than $x back as tips, draining their allowance.</p>
<p>Sure, no one would set these apps in such a way that I can steal their money (though, users are often careless).</p>
<p>But what if their like <a href="https://farcaster.xyz/vrypan.eth/0xf020ab0b">is used as a vote that affects how a retro funding round worth &gt;$30k is distributed</a>? Or if social activity (especially actions with a tip attached to them must be genuine, right?) is used to define an airdrop distribution?</p>
<h2>The second attack vector is app keys.</h2>
<p>This is a breach of trust, or even an actual hack.</p>
<p>Every Farcaster application (even Farcaster.xyz) that you use to cast, like, recast, follow, will ask you to sign an appkey. Then, they use this key to sign Snapchain transactions (casts, likes, etc) on your behalf.</p>
<p>If one of these apps go rogue, or get hacked, the attacker can create a cast, and then comment, like and recast as any of their users, in order to collect tips triggered by these social transactions.</p>
<h2>What can we do?</h2>
<p>The most important part is awareness. Many of these attacks can be averted if users and developers are aware of the risks described above.</p>
<p>An other “soft” measure could be <strong>an “advisor” app that checks known combinations and alert users</strong>: “Warning: You tip $0.6/like using noice, $0.6/like using tipn, and you set your like value to $1 on ampsfun”.</p>
<p><strong>Apps should also encourage users to set low allowances</strong> (if you tip $.1/like, do not set the app allowance to $200), and notify them when they are running low.</p>
<p><strong>Tipping apps can also check the appkey</strong> used for a social interaction, before sending the tip. An appkey associates the application FID with the user FID, so you could request additional confirmation when you see a new app used: “You used ampsfun/coinbase/opencast, is it ok to trigger tips when this app is used”? Whitelisting well-known clients like Farcaster.xyz in advance will make this invisible to 99.99% of the cases and add minimal UX friction.</p>
<p>In some cases, <strong>appkeys can be checked retroactively</strong>. If you use social activity to define the distribution of an airdrop or a grant, make sure you analyze the app keys used in each case and act (for example ignore some of them) accordingly.</p>
<p>Finally, <strong>when Snapchain implements appkey freezing</strong> (app keys are frozen and can’t be used, but are not revoked), we should put in place the tools and habits that will let users easily freeze unused appkeys.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/05/28/social-attacks-with-monetary-value/image.png"
   type="image/png"
   length="310972"/>

    </item>
    
    <item>
      <title>The Case for Snapchain Minimalism
</title>
      <link>https://blog.vrypan.net/2025/05/24/the-case-for-farcaster-protocol-minimalism/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/05/24/the-case-for-farcaster-protocol-minimalism/</guid>
      <pubDate>Sat, 24 May 2025 13:56:51 +0200</pubDate>
      <description>Farcaster Pro is launching next week, and at some point it will introduce features like 10,000-character casts and up to four images per cast. These enhancements will require a protocol upgrade.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/05/24/the-case-for-farcaster-protocol-minimalism/diagram.png">
        
	<p><strong>Farcaster Pro</strong> <a href="https://farcaster.xyz/dwr.eth/0x43fea96a">is launching next week</a>, and at some point it will introduce features like <strong>10,000-character casts</strong> and <strong>up to four images per cast</strong>. These enhancements will require a <strong>protocol upgrade</strong>.</p>
<p>While I believe in the core idea of a Pro subscription, for me, this reopens a (friendly!) long-standing debate I have with the Merkle Manufactory (MM) team: I believe new types of content should be stored <strong>outside the protocol</strong>.</p>
<h2>The Core Idea</h2>
<p>I believe that we should <strong>store as little content as possible on snapchain</strong>, and design the standards that will allow Farcaster content to be stored externally.</p>
<p>Instead of baking support for content types (such as long-form text, code snippets, MP3 playlists, photo reels, geo-tagged casts, etc.) into the protocol, we should treat these as <strong>external resources</strong>, referenced by the protocol, but hosted elsewhere.</p>
<p>There are many ways to implement this, ranging from quick-and-dirty hacks to clean, modular solutions. I would argue for a new type of <code>embed</code> urls that point to a well-defined json, but I don’t want to focus on the technical details here.</p>
<p>Instead, I’ll explain why this approach deserves serious consideration, and why it should serve as a guiding principle for protocol development.</p>
<h2>1. Permissionless Development</h2>
<p>By moving new types of content outside the protocol, we <strong>allow anyone to introduce new experiences</strong> without needing approval or access to the protocol maintainers.</p>
<p>Take 10k-character casts or photo reels, for instance. These could have been implemented without touching the protocol, if we had a standard for embedding external content into casts.</p>
<p>MM often argues that we should “wait for demand” before introducing new primitives. Now that they themselves want longer casts and more images per cast, the answer is suddenly: “Let’s change the protocol.” Could they have used an approach like <a href="/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/">lemon3 enclosures</a>? Sure. But it feels “hacky” and inelegant, I agree.</p>
<p><strong>Ironically</strong>, longer casts (1024 characters) were added a year ago as a quick change, in response to my <a href="https://github.com/farcasterxyz/protocol/discussions/171">proposal for external cast data</a>. Back then, the promise was: “We’ll revisit the approach if there’s demand for it.” Well, now there is demand for even longer casts, but again we just change the protocol to fit a specific use case.</p>
<p>I'm critical to MM here, but I think they would benefit too. Actually, they would be the first to benefit, because they want to be flexible to try new features fast, and any snapchain change, no matter how small, adds a significant overhead. Their experiments would go to market much faster if they did not have to implement snapchain changes.</p>
<p>Side-note: <strong>External content doesn’t mean any content type will be supported by every client</strong>. For example, I can introduce a type of content (let’s say m3u playlists) that the Farcaster app does not support. But a well-defined standard will allow a fallback representation, and proper indexing.</p>
<h2>2. Decentralization</h2>
<p>Storing more and more content on the protocol means that the storage requirements to run your own hub go up, and fewer people can run their own hub. Offloading (new types of) content reduces the storage burden on <strong>Farcaster hubs</strong>.</p>
<p>Yes, relying on external content introduces some complexity. But that’s a fair tradeoff if it means <strong>more people can run hubs</strong>, and client (not just user-facing clients, but also agents, bots, analytics, etc.) developers can <strong>choose</strong> whether they need these external data.</p>
<p>After all, if no one is able to run their own hubs because of increased hardware requirements, and end up using Neynar APIs, what’s the difference if the API results come from the snapchain or other sources?</p>
<h2>3. Storage Costs Separation</h2>
<p>External content storage allows apps to charge for <strong>storage and bandwidth</strong> without affecting the protocol.</p>
<p>Want to build a photo reel app offering 1TB per user? Go for it—no protocol changes needed. Casts can simply embed a pointer to a JSON file listing the images. You can even ask users to pay for storage, and it makes sense to everyone. Want 8 or 10 images per cast? Sure.</p>
<p>Thinking of video uploads up to 2 hours? Build it. Host the video. Charge for hosting and bandwidth. No need for protocol-level intervention.</p>
<h2>Wait. Are We Already Doing This?</h2>
<p>Ironically, Farcaster already supports this model, but only for a very specific type of content: <strong>miniapps</strong>.</p>
<p>Miniapps are externally hosted, protocol-referenced applications. Developers love them, users love them. One could argue that the new Pro features could be built as miniapps that get special treatment by the Farcaster client -or any other client wants to do so.</p>
<p>We don’t need to cram every new content type into the protocol. Let’s use an extensible, permissionless architecture where innovation and experimentation is easy.</p>
<p>We are already familiar with the mental model of storing miniapps externally. Why not do the same for content and get all the benefits mentioned above?</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/05/24/the-case-for-farcaster-protocol-minimalism/diagram.png"
   type="image/png"
   length="126728"/>

    </item>
    
    <item>
      <title>Devcoins
</title>
      <link>https://blog.vrypan.net/2025/04/13/devcoins/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/04/13/devcoins/</guid>
      <pubDate>Sun, 13 Apr 2025 11:06:58 +0200</pubDate>
      <description>In the world of crypto, we’ve seen coins created for just about everything — from memes to celebrities.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/04/13/devcoins/image.png">
        
	<p>In the world of crypto, we’ve seen coins created for just about everything — from memes to celebrities.</p>
<p>Developers, the one group that probably makes more sense to have a coin, did not use it.</p>
<p>So, let's talk <strong>devcoins</strong>.</p>
<p>A devcoin is a personal token for a developer.<br />
It’s a way to back the value a developer can create over time.<br />
Instead of betting on hype, you’re supporting the people building real things.</p>
<hr />
<p>Devcoins make sense. Developers are always shipping projects, tools, services, and infrastructure.</p>
<p>But it’s not always easy for them to get paid — especially when they build open-source software or tools that aren’t easy to monetize.</p>
<p>A devcoin gives people a simple way to support a developer directly.</p>
<p>Holding a devcoin can mean:</p>
<ul>
<li><strong>Backing the developer</strong> and believing in what they will build next and indicating that you want to keep working on and maintaining their projects.</li>
<li><strong>Unlocking utility</strong> — like using the devcoin to pay for services, or access to features.</li>
<li><strong>Getting early access</strong> to new projects, beta features, or private tools.</li>
</ul>
<p>It’s a simple relationship:  If you believe in a developer’s work, you hold their devcoin.  If you want to support them even more, you can buy more —or even send the coins back to them as a tip.</p>
<p>An indie developer building many small projects could tie all of them to the same devcoin, creating a mini-ecosystem around their work.</p>
<hr />
<p>The tools are already here, we don’t need to invent anything new to make devcoins happen.</p>
<p>Platforms like <a href="https://clanker.world">clanker.world</a> already let anyone launch a token, set up a liquidity pool and make it trivial for users to buy and sell it in seconds.</p>
<p>Everything that works for memecoins can be used for devcoins too — just with more purpose.</p>
<hr />
<p>It would be even better if we could link devcoins to developer identities more formally — for example, showing them on GitHub profiles or Farcaster accounts.</p>
<p>Imagine being able to discover new developers, check out their projects, and back them immediately through their devcoin.</p>
<p>The tools exist, the need is clear, the idea is simple.</p>
<hr />
<p>As a side note:</p>
<p>I launched <a href="https://dexscreener.com/base/0xb5f6d50e83ade083214cf861c87a751e7d3eb91a">$lemon3</a> about a month ago, as a way to support the development of <a href="/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/">lemon3</a>. But as I was building <a href="https://pingem.xyz">pingem.xzy</a> I realized that $lemon3 could become my personal devcoin, so if you want to use pingem, you need to hold (not pay, just hold) 10M $lemon3 (that’s about $5 worth of tokens). I’ll keep playing with the concept to see how it works.</p>
<hr />
<p><a href="https://warpcast.com/vrypan.eth/0xb467ab17">Leave a comment here.</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/04/13/devcoins/image.png"
   type="image/png"
   length="3535007"/>

    </item>
    
    <item>
      <title>Socially-Scoped Infrastructure
</title>
      <link>https://blog.vrypan.net/2025/03/28/socially-scoped-infrastructure/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/03/28/socially-scoped-infrastructure/</guid>
      <pubDate>Fri, 28 Mar 2025 23:15:35 +0200</pubDate>
      <description>Decentralized infrastructure (DePIN) has solved core problems like peer-to-peer networking, distributed consensus, and trustless storage. But one question remains: how do these systems decide what matters?</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/03/28/socially-scoped-infrastructure/socially-scoped-infar.png">
        
	<p>Decentralized infrastructure (DePIN) has solved core problems like peer-to-peer networking, distributed consensus, and trustless storage. But one question remains: <strong>how do these systems decide what matters?</strong></p>
<p>In this article, we introduce the concept of <strong>Socially-Scoped Infrastructure</strong>, where systems use social signals to decide what to act on. Farcaster becomes a real-time intent layer, guiding infrastructure like IPFS to respond.</p>
<h2>Coordination Without Central Control</h2>
<p>When the decentralized system is a blockchain, it is easy to prioritise transactions, allocate resources and decide what matters using global logic built around financial incentives.</p>
<p>But global, financial incentives may not be ideal for other types of decentralized infrastructure. In some of these cases, <strong>social signals</strong> may be the answer.</p>
<ul>
<li>Which files should be pinned?</li>
<li>How should compute be allocated?</li>
<li>Where should mesh networks expand?</li>
</ul>
<h2>Core Idea: Social Signals Trigger Infra Actions</h2>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Signal Layer</strong></td>
<td>Users express intent (e.g. CIDs, tags, likes in casts)</td>
</tr>
<tr>
<td><strong>Scope Layer</strong></td>
<td>Defines whose signals matter (e.g. follows, lists, channels)</td>
</tr>
<tr>
<td><strong>Agent</strong></td>
<td>Listens and reacts (e.g. bot, daemon, client-side app)</td>
</tr>
<tr>
<td><strong>Action Layer</strong></td>
<td>Infra responds (e.g. pinning, caching, executing compute)</td>
</tr>
</tbody>
</table>
<h2>Example: Pinning IPFS CIDs from Farcaster</h2>
<p>The following example is <a href="https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/">inspired by lemon3</a>:</p>
<p>You follow someone on Farcaster. They share an IPFS CID. Your client checks if the post is from a followed user. If yes, your IPFS node pins the content.</p>
<p>No consensus. No token. Just <strong>trust-based automation</strong>. Farcaster provides the intent. IPFS executes. Social attention becomes an input to decentralized infrastructure.</p>
<h2>Broader Use Cases</h2>
<p>This pattern works well in storage-based systems like IPFS, Filecoin, and Arweave, where resource allocation (storage) is simple and flexible. It can also apply to decentralized compute where tasks are parallelizable and scoped to a social subgraph.</p>
<p>In geographically distributed hardware systems, like Helium or WeatherXM, applying social scoping may be more complex or not feasible, because the network can not easily react to social signals -but if you have ideas on how to use these patterns there, ping me!</p>
<h2>Conclusion</h2>
<p>Combining decentralized infra with open social layers like Farcaster creates a programmable stack, where <strong>infrastructure responds to social signals.</strong></p>
<p>These social signals can provide an alternative way for decentralized infrastructure to prioritize and allocate resources based on what matters to each one of the participants —locally, socially, even temporally.</p>
<hr />
<p><a href="https://warpcast.com/vrypan.eth/0xef39f4b5">Comment of farcaster</a></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/03/28/socially-scoped-infrastructure/socially-scoped-infar.png"
   type="image/png"
   length="2695859"/>

    </item>
    
    <item>
      <title>lemon3
</title>
      <link>https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/</guid>
      <pubDate>Sun, 23 Mar 2025 12:38:27 +0200</pubDate>
      <description>lemon3 is an open source program that uses IPFS and Farcaster to allow decentralized file hosting and sharing.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/blueprint.png">
        
	<p><a href="https://github.com/vrypan/lemon3">lemon3</a> is an open source program that uses IPFS and Farcaster to allow decentralized file hosting and sharing.</p>
<p>The name is a tribute to <a href="https://en.wikipedia.org/wiki/Juice_(aggregator)">iPodder Lemon</a>, the original podcast aggregator, because it is intended to be a web3-friendly version of the original idea.</p>
<p><strong>lemon3</strong> uses <code>cast.Embeds</code> to embed a special <code>enclosure+ipfs://&lt;CID&gt;</code> link in casts. The link points to a json payload hosted on IPFS. The json payload is intended to make up for the fact that Farcaster <code>Embeds</code> are plain links with no additional information that is required in this case (and could be very useful in other use cases too), and provides: file name, file type, file size and the IPFS CID of the file that was shared. This is the equivalent of the RSS <code>&lt;enclosure&gt;</code> tag used in podcasting.</p>
<p><strong>lemon3</strong> is a mini Farcaster client, that connects to a hub: It will show casts containing enclosures from users you follow, and it allows you to share files by uploading them to IPFS and casting the corresponding enclosure. It also contains an embedded IPFS server, so you don’t have to run your own.</p>
<table>
<thead>
<tr>
<th>iPodder Lemon (2005)</th>
<th>lemon3 (2025)</th>
</tr>
</thead>
<tbody>
<tr>
<td>RSS feed</td>
<td>Farcaster user casts</td>
</tr>
<tr>
<td>RSS enclosures</td>
<td><code>enclosure+ipfs://</code> Embeds</td>
</tr>
<tr>
<td>Files on web server</td>
<td>Files on IPFS</td>
</tr>
<tr>
<td>Web server required to host feed and files</td>
<td>No servers required</td>
</tr>
</tbody>
</table>
<h2>Status and next steps</h2>
<p>Version 0.1.1 is the MVP: You can upload and share files, and you can find and download files shared by others.</p>
<p><figure><img src="https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/screenshot1.png" alt="screenshot1" /></figure><figure><img src="https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/screenshot2.png" alt="screenshot2" /></figure></p>
<p>But there’s a lot to be done to get to a version that “just works”: various bug fixes, UX streamlining, a decent user onboarding flow, and features such as keeping track of already downloaded files, support for standalone IPFS servers and a download manager. Maybe a web interface (similar to how Transmission works), too. Probably an RSS gateway that exposes these feeds as RSS for compatibility with existing podcast clients.</p>
<p>Even the core protocol design may need some updates, like replacing the JSON payload with IPLD.</p>
<p>But once everything is more stable, there are new opportunities that we did not have with RSS, like reactions and comments: For example, if you are producing a podcast, your listeners could reply, like and share your episodes, natively, within their social network.</p>
<p>I’m very excited with the possibilities!</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/blueprint.png"
   type="image/png"
   length="8235162"/>

   <enclosure url="https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/screenshot1.png"
   type="image/png"
   length="88233"/>

   <enclosure url="https://blog.vrypan.net/2025/03/23/lemon3-farcaster-ipfs-decentralized-file-sharing/screenshot2.png"
   type="image/png"
   length="83767"/>

    </item>
    
    <item>
      <title>Farcaster in Coinbase Wallet
</title>
      <link>https://blog.vrypan.net/2025/03/03/farcaster-in-coinbase-wallet/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2025/03/03/farcaster-in-coinbase-wallet/</guid>
      <pubDate>Mon, 03 Mar 2025 20:01:01 +0200</pubDate>
      <description>A month ago, Coinbase announced their plans for the next itteration of Coinbase Wallet. Check out the announcement.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2025/03/03/farcaster-in-coinbase-wallet/fc-cb-wallet.png">
        
	<p>A month ago, Coinbase announced their plans for the next itteration of Coinbase Wallet.
<a href="https://warpcast.com/coinbasewallet/0x5f8e2bbf">Check out the announcement</a>.</p>
<p>One of the exciting points is Farcaster integration: The evolution of Coinbase Wallet
will have a full social feed and mini-apps powered by Farcaster.</p>
<p>Integrating a crypto wallet with Farcaster opens up new possibilities. For example:</p>
<ul>
<li>Checking if a recipient's address is tied to someone in your network.</li>
<li>Seeing if trusted people have interacted with a smart contract or left comments.</li>
<li>Viewing on-chain activities from your social circle.</li>
<li>Minting/claiming tokens based on social activity.</li>
<li>Notifications about time-sensitive events (e.g., ENS domain renewal).</li>
<li>Fun games!</li>
</ul>
<p>I can’t be sure what the Coinbase team will build, and some of these already exist either as stand-alone apps or as app features, but Coinbase has the power to bring these features to a much larger audience.</p>
<p>This is a fundamentally different mental model for Farcaster: Warpcast is a social app with a wallet (added recently), Coinbase Wallet will be a wallet with social features (I guess).</p>
<hr />
<p>Bonus: <a href="https://warpcast.com/dwr/0xf41f9f54142227a8f19d948488b1f364f2769bd0">An old cast of dwr</a> 👀</p>
<p><figure><img src="https://blog.vrypan.net/2025/03/03/farcaster-in-coinbase-wallet/social-wallet.png" alt="social wallet" /></figure></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2025/03/03/farcaster-in-coinbase-wallet/fc-cb-wallet.png"
   type="image/png"
   length="793585"/>

   <enclosure url="https://blog.vrypan.net/2025/03/03/farcaster-in-coinbase-wallet/social-wallet.png"
   type="image/png"
   length="83305"/>

    </item>
    
    <item>
      <title>Ethereum as a Neutral Economic Zone
</title>
      <link>https://blog.vrypan.net/2024/12/23/ethereum-as-a-neutral-economic-zone/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2024/12/23/ethereum-as-a-neutral-economic-zone/</guid>
      <pubDate>Mon, 23 Dec 2024 21:37:18 +0200</pubDate>
      <description>Neutral economic areas are geographical or conceptual zones characterized by a lack of strong economic dependence or dominance by a single state, company, or interest group.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2024/12/23/ethereum-as-a-neutral-economic-zone/eth-zone.png">
        
	<p>Neutral economic areas are geographical or conceptual zones characterized by a lack of strong economic dependence or dominance by a single state, company, or interest group.</p>
<p>These areas are often governed by principles that encourage equal access and opportunity for multiple participants without favoritism. Such areas can exist in various contexts, including international trade zones, shared natural resources, or collaborative spaces for innovation.</p>
<p>Common characteristics of neutral economic areas are</p>
<ul>
<li><strong>Equitable Access</strong>. All participants have equal opportunities to engage in economic activities.</li>
<li><strong>Non-Dominance</strong>. No single party exercises disproportionate control over the area’s resources or decision-making.</li>
<li><strong>Shared Governance</strong>. Decisions are made collaboratively, often involving multiple stakeholders or international entities.</li>
<li><strong>Regulatory Framework</strong>. Clear rules exist to ensure neutrality and fair competition.</li>
</ul>
<p>These zones aim to foster cooperation, reduce conflicts, and promote balanced economic development.</p>
<hr />
<p>The world is entering an era of deepening conflict and mistrust. Old allies are turning into rivals, new barriers are emerging between nations, and economic tools like export controls, tariffs, and asset freezes are being weaponized to a degree we haven't seen for many decades. In this increasingly fragmented and hostile environment, the concept of neutrality in economic zones is more critical than ever.</p>
<p><strong>In this emerging environment, Ethereum is the largest, neutral, economic activity zone, and Ether (ETH) is its base currency.</strong></p>
<p>You can be sure that your Eth funds can’t be frozen or seized. That your transactions can’t be stoped. That the contracts you sign will be executed to the letter. That you can pay, get paid, trade, borrow, lend, get dividends, vote and make trusted commitments that can’t be canceled by third parties.</p>
<p>This is why it is important to keep Ethereum neutral, decentralized and unstoppable. We must avoid core dependencies on technologies like TEEs (that can be controlled through legislation and export controls). And we must work towards making Ethereum safer to use in adversarial environments, with technologies that protect privacy.</p>
<p><strong>Ethereum, as the largest, neutral, economic activity zone is our hedge against a fragmented and hostile world that is starting to treat prosperity is a zero-sum game.</strong></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2024/12/23/ethereum-as-a-neutral-economic-zone/eth-zone.png"
   type="image/png"
   length="2439791"/>

    </item>
    
    <item>
      <title>Farcaster L2s
</title>
      <link>https://blog.vrypan.net/2024/06/26/farcaster-l2/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2024/06/26/farcaster-l2/</guid>
      <pubDate>Wed, 26 Jun 2024 22:55:40 +0200</pubDate>
      <description>I often consider casts to be a special "Farcaster application": I could see an alternative universe where Farcaster launched without casts, and casts were an application leveraging Farcaster identity and social graph .</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2024/06/26/farcaster-l2/diagram.png">
        
	<h1>Before you read</h1>
<p>I often consider casts to be a special &quot;Farcaster application&quot;: I could see an alternative universe where Farcaster
launched without casts, and casts were an application leveraging Farcaster identity and social graph <sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>.</p>
<p>A Farcaster without protocol-level casts may sound crazy, but think of what Direct Casts are today: An application that leverages
the Farcaster identity and social graph, without being part of the protocol.</p>
<p><strong>This is not an FIP:</strong> I find the idea interesting, but it comes with a number of technical, architectural,
business and social implications. Adopting this architecture could change what Farcaster is —I'm not even
sure if I'd like a Farcaster that moved in this direction.</p>
<p>That said, I also think it’s a space we should explore, discuss and debate, so here’s my contribution.</p>
<hr />
<h1>Problem</h1>
<p>Every technical design has its limitations, and so does Farcaster. One of them is the speed that messages propagate throughout the network.
An other one is storage limits. And of course, there are a number of widely accepted norms, for example, we expect a cast to be readable text.</p>
<p>An other problem is disk space required for hubs: We know that if Farcaster grew 100x or 1000x, storage requirements for hubs would
probably grow to a point that hosting a hub would require very expensive hardware, inevitably leading to centralization.</p>
<h1>Specification</h1>
<p><code>Bundles</code> are Farcaster messages that contain references to messages stored externally (not in hubs).</p>
<p>A Bundle message can be added with a <code>BundleAdd</code> message and removed<sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>2</a></sup> with a tombstone <code>BundleRemove</code> message.</p>
<p>A new <code>UnbundleMessages</code> RPC endpoint allows a client to submit the bundle data to a hub and get the messages back. The hub will validate each message included in the bundle and return only the messages that are valid.</p>
<p>Only Cast add/remove and Reaction add/remove messages can be part of a bundle.</p>
<pre><code>message MessageBundle {
  // Only CastAdd, CastRemove, ReactionAdd and RecationRemove 
  // messages are allowed in messages.
  repeated Message messages = 1; 
  bytes data_hash = 2;  
}

message BundleAdd {
  string url = 1;
  bytes data_hash = 2;     // Hash of the data stored at url
  bytes parent_bundle = 3; // Message.hash value of the previous bundle
}

message BundleRemove {
  bytes target_hash = 1;  // Message.hash value of the bundle being removed
}

rpc UnbundleMessages(MessageBundle) returns (MessagesResponse);
</code></pre>
<h1>Rationale</h1>
<p>The high-level idea of this proposal is (is some ways) similar to an Ethereum Validium L2: Messages are bundled and they are stored externally, and hubs store references to these bundles, instead of the messages themselves. In this context, hubs are &quot;Farcaster L1&quot;, and the bundles submitted by a specific FID form
a &quot;Farcaster L2&quot;.</p>
<p>Hubs remain the authority for identity (FIDs), social graph (Links), user profiles and signers.</p>
<p>A bundler bundles multiple messages in a bundle, stores them and posts <code>BundleAdd</code> messages to hubs. A bundler can be centralized (a typical web2 application) or decentralized (for example, a group of hubs running a modified version of Hubble). If bundles are used to create an L2, then the bundler’s FID defines the L2.</p>
<p>This is the typical flow:</p>
<ul>
<li>The application allows its users to send Farcaster messages such as <code>CastAdd</code> and <code>ReactionAdd</code>, but these messages are not submitted to a hub.</li>
<li>The application/bundler packages these messages as a <code>MessageBundle</code> blob, and stores them somewhere online. The storage
location can be public (for example, a public URL or IPFS) or even private (for example, the app database or a protected S3 bucket).</li>
<li>The application/bundler submits a <code>BundleAdd</code> message to hubs. The message states the location of the blob and its hash.
It may also reference a parent bundle from the same fid.</li>
<li>If an other application wants to retrieve these messages, it has to fetch the blob, and call <code>UnbundleMessages()</code> to unbundle them.</li>
</ul>
<p>Notes:</p>
<ul>
<li>Messages are expected to be valid messages, that comply to message rules imposed by hubs (size, signatures, signer validity, etc)</li>
<li>Users of the application have to trust that the application will actually include their messages in the bundle. They also trust
that the application will not delete a bundle that contain their messages.</li>
</ul>
<h2>Cross-layer architecture</h2>
<p>In interesting property of this architecture is that messages can be moved between layers:</p>
<p>A message posted on a L2 is a valid message that can be posted at any time to a hub (L1), or copied to any other L2. And a message that was posted to a hub (L1) can be copied to an L2 -even after it’s been purged.</p>
<h2>Why would an app use this and not build something from scratch?</h2>
<p>The design has a high level compatibility with existing tools and patterns used by developers. For example, shuttle <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>3</a></sup> could be extended to support Bundles (developers could also configure their shuttle instance to accept only specific bundlers, using their FID) and make bundles messages available to apps that use it. Similarly, services like Neynar could support bundles from specific FIDs and make their messages available to devs using the existing APIs.</p>
<p>The design also takes advantage of the Farcaster identity infrastructure, social graph, and everything that comes with Farcaster.</p>
<p>Depending on the implementation (this is the case with any “layer 2”), users can have strong assurances that once a message is bundled and submitted, it will be available to others. In any case, users could “move” their messages to L1 if they like.</p>
<h2>Farcaster scalability</h2>
<p>Farcaster could decrease storage unit limits to push users to use bundles (L2s).</p>
<p>An extreme scenario that would force most users to use a L2 (but would also make it even cheaper for them to use Facraster):</p>
<ul>
<li>The first storage unit for each FID could have 0 (zero) casts, 0 bundles, 2500 Links, 50 Verifications and 50 User Data and cost even less than today.</li>
<li>Storage units after the first one, cost 10x more than today and allow 5000 casts or bundles.</li>
</ul>
<h2>Do we need an FIP for this?</h2>
<p>The truth is someone could implement most of what’s described here by using <code>CastAdd</code> and setting <code>embed.url</code> to the location where messages are stored, in some custom format.</p>
<p>However, this would be a hack. The protocol gets no benefit, its messy, and the lack of standardisation limits interoperability between tools, layers and services.</p>
<h2>Possible use-case examples</h2>
<p>The default use case is an app like Warpcast has it's own L2, and posts a bundle every few seconds. All users of the app see the messages instantly, and
everyone else who tracks the specific L2 sees them with a small delay of a few seconds.</p>
<p>Other, possible use cases:</p>
<ul>
<li>A sports app that allows users to comment in real-time during a game, offering a chat-like experience. The app also uses a special pattern for each cast, where the first characters are reserved for the minute/second of the game, and the user’s favorite team. All messages are stored in a RDBMS during the game. At the end of the game, they are bundled, stored on IPFS and a <code>BundleAdd</code> is submitted to Farcaster.</li>
<li>A Farcaster archiver keeps track of pruned casts and reactions. Every day, it stores them on IPFS and submits them as a bundle to Farcaster.</li>
<li>An app designed to preserve privacy encrypts casts, without worrying that they will appear as noise to the rest of the users.</li>
<li>An L2 that hosts content not allowed in Warpcast, such as adult content.</li>
<li>A &quot;private&quot; L2: Messages are stored in a non-public location that requires authentication and are not available to the public.</li>
<li>A bundler can be open (for example, Warpcast could maintain their own bundler that exposes an open API to be used by other apps), or closed (for example one that can only be used by a proprietary app, and requires users to pay to use it.)</li>
</ul>
<h1>Concerns/TBD</h1>
<p>An assorted list of concerns and points that need further discussion:</p>
<ul>
<li>A malicious user can copy all messages of an FID from a bundle (L2) and post them to L1, consuming all of FID’s storage space. Is this really a problem?</li>
<li>Could this design lead to Balkanization of Farcaster, with multiple, isolated L2s that don’t interact or are not even aware of each other?</li>
<li>Do we want to allow bundlers that do not store bundles in a publicly accessible storage? If not, how can this be prevented other than by social norms?</li>
<li>How will an app handle bundled messages when a signer used to sign some of them is removed? Where does this logic reside?</li>
<li>To which extent <code>UnbundleMessages</code> performs tests? Should it reject duplicate messages in a bundle? Should it reject a cast that is already on L1?</li>
<li>Are apps expected to mix bundled messages and “normal” messages? Is it either L1 or L2 and messages are not mixed? Or is it L1 + a single L2?</li>
<li>How can someone reference a message included in a bundle in such a way that a third party knows it should fetch the bundle first?</li>
<li>What happens if a <code>CastRemove</code> message is submitted to a hub, that refers to a message included in a bundle?</li>
<li>How can this model be abused?</li>
<li>Set a limit on the size of <code>MessageBundle</code>.</li>
<li>App guidelines to avoid user confusion?</li>
<li><code>UnbundleMessage</code> will be a resource-intensive call. Hubs must be able to restrict it to specific users or IPs.</li>
</ul>
<hr />
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>Of course, from a project development pov, it was a wise decision to have casts from day one. <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-3">
<p>Update, 2024-06-30. The more I think about this, there should be no option to remove bundles. If you want to remove <code>*Add</code> messages in a bundle, post <code>*Remove</code> messages in a future bundle. <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://github.com/farcasterxyz/hub-monorepo/tree/main/packages/shuttle">shuttle package</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2024/06/26/farcaster-l2/diagram.png"
   type="image/png"
   length="161228"/>

    </item>
    
    <item>
      <title>The Moore-Nakamoto plain</title>
      <link>https://blog.vrypan.net/2024/04/27/moore-nakamoto/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2024/04/27/moore-nakamoto/</guid>
      <pubDate>Sat, 27 Apr 2024 09:24:42 +0200</pubDate>
      <description>If you think about it, crypto is orthogonal to Moore's Law.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2024/04/27/moore-nakamoto/depin.png">
        
	<h1>Nakamoto is orthogonal to Moore</h1>
<p>If you think about it, crypto is orthogonal to Moore's Law.</p>
<p>Crypro is <strong>designed</strong> to add friction to the things that Moore's Law made frictionless or trivial.</p>
<p>For example, Bitcoin is designed to countermeasure the addition of computing power by increasing block difficulty, and NFTs are the answer to frictionless media replication enabled by computers.</p>
<p>Running the current version of Microsoft Office, or even Chrome on a computer built 15 years ago is painful if not impossible. A typical 15 years old computer is not powerful enough to handle today's programs because they depend on 10x more power than was available back then. (Just take a look at <a href="https://browser.geekbench.com/mac-benchmarks">Geekbench Benchmarks for Macs</a> comparing Apples to Apples.)</p>
<p>On the other hand, the Bitcoin codebase has not changed much since 2008 -not in ways that require additional processing power. Similarly, the exponential increase in Ethereum transaction bandwidth thanks to L2s was not a result of increased compute power.</p>
<h1>The Moore-Nakamoto plain</h1>
<p>We can consider a two-dimensional plain, where one axis indicates the impact of compute improvements and the other the impact of crypto technology. <strong>I'll call this the Moore-Nakamoto plain.</strong></p>
<p>Where do various projects and technologies go on this plain?</p>
<p>For example, traditional video games are not impacted at all by advances in crypto, but CPU/GPU power increase or efficiency has a dramatic impact on them. Compare this to a game like Axie Infinity, where the quality of graphics obviously depends on the available computing power, but advances in crypto technology, like L2s or wallet abstraction are also very important.</p>
<p><figure><img src="https://blog.vrypan.net/2024/04/27/moore-nakamoto/axie-cod.png" alt="" /></figure></p>
<p>Here is an other example comparing Uniswap, DePIN and OpenAI.</p>
<ul>
<li>OpenAI depends 100% on the cost of compute and advances in crypto have no effect on it.</li>
<li>Uniswap is not affected by advances in compute power, but advances in crypto have a huge impact on it.</li>
<li>DePIN projects are affected by both.</li>
</ul>
<p><figure><img src="https://blog.vrypan.net/2024/04/27/moore-nakamoto/depin.png" alt="" /></figure></p>
<p>I think that the Moore-Nakamoto plain is a great tool to map and compare projects, and to analyze how advances in compute and crypto will affect them in the future.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2024/04/27/moore-nakamoto/axie-cod.png"
   type="image/png"
   length="45990"/>

   <enclosure url="https://blog.vrypan.net/2024/04/27/moore-nakamoto/depin.png"
   type="image/png"
   length="56076"/>

    </item>
    
    <item>
      <title>The l--o--l collection
</title>
      <link>https://blog.vrypan.net/2024/03/08/l-o-l/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2024/03/08/l-o-l/</guid>
      <pubDate>Fri, 08 Mar 2024 16:24:42 +0200</pubDate>
      <description>"|" is the pipe symbol (character 0x7C), but when the pipe symbol can't be used (ex. domain names or Farcaster usernames) the lowercase L is used: l--o--l.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2024/03/08/l-o-l/preview-01.png">
        
	<p><em>&quot;|&quot; is the pipe symbol (character 0x7C), but when the pipe symbol can't be used (ex. domain names or Farcaster usernames) the lowercase L is used: <code>l--o--l</code>.</em></p>
<p>|--o--| is a collection of 10,000 ASCII art spaceships represented as ERC721 tokens on the Base chain.</p>
<p>Each spaceship will have:</p>
<ul>
<li>A <strong>blueprint</strong>: The ascii characters that represent it, for example <code>|-x--0--x-|</code>. Each character is called a <strong>part</strong>.</li>
<li>An <strong>engine</strong> (a smart contract used to convert the blueprint to artwork).</li>
</ul>
<p>During mint, the the available parts will be <code>|-:o@bd8x0()=\/</code>, but the smart contract is designed to allow new parts to be added in the future. It also allows a holder of two spaceships to rearrange their parts to build two new ones.</p>
<p>The basic engine, that will be available from day zero, generates an onchain SVG representation of the ship, and will look something like this. The artwork is generated dynamically, based on the ship's blueprint, which means that if the blueprint changes in the future, so will the artwork.</p>
<p><figure><img src="https://blog.vrypan.net/2024/03/08/l-o-l/edition.svg" alt="" /></figure></p>
<p>More engines can be added in the future. Some may use a different design style (I'd love to see artists create alternative engines!), and some may even allow complex functionality, like altering the artwork based on game rules or actions. The ship's holder will always be able to change the engine used back to the basic engine.</p>
<p>Each ship has one more property that could be useful for future onchain integrations: <strong>Captaincy</strong>. This is the number of days a ship has remained in the current wallet. I'm not 100% how captaincy can be used, but it's there if you want to build some mechanics on top of it.</p>
<h3>I want users to be able to modify their spaceships, play with them, have fun. This is why I like to think of |--o--| as &quot;onchain toys&quot;.</h3>
<p>A nice way to experience how |--o--| ships will look like is <a href="https://warpcast.com/l--o--l/0xd01846f3">this Farcaster frame</a>.</p>
<hr />
<h1>Minting</h1>
<p>Minting phases I and II will only be available through Farcaster. Please consider this if you plan to participate.</p>
<p>It's not finalized yet, but most probably, this is how minting will take place.</p>
<h2>Phase I: The first 100-200 &quot;OG&quot; tokens</h2>
<p>This phase will be reserved for <a href="https://zora.co/collect/base:0x0f504e65368a65759847d54c43d98bb473d1191f/1">Edition</a> holders. A snapshot will be taken, and holder FIDs will be whitelisted, and allocated a number of mints equal to the number of Editions they hold.</p>
<p>Minting will take place using a frame that will allow whitelisted users to create their ships using their own &quot;blueprints&quot; (characters). Minting will be free (probably no gas cost either).</p>
<p>Ships minted using this method will also have an &quot;OG&quot; flag set, and will be visually distinctive (probably have a glitch effect, like the Editions).</p>
<p>At the end of this phase, the collection will have 100-200 carefully crafted OG ships that will be used as blueprints for the rest of the collection (see next phases).</p>
<p>In total, 88 Editions were minted. I may manually mint some more to get to 100 or slightly more OG blueprints.</p>
<p><figure><img src="https://blog.vrypan.net/2024/03/08/l-o-l/preview-03.png" alt="(--db--)" /></figure></p>
<h2>Phase II: Airdrop of 1000 tokens</h2>
<p>I intend to whitelist 1000-2000 FIDs. Not sure about the criteria yet, probably based on other NFTs they hold, or social graph (Farcaster).</p>
<p>During this phase, each whiltelisted FID will be able to mint for free (but pay for gas) one ship. They won't be able to create their own, ships minted during this phase will be copies of OG ships (but without the OG flag and the OG visual effect).</p>
<h2>Phase III: Open Mint of ~9,000 tokens</h2>
<p>During this phase, the rest of the collection will be minted (up to 10,000).
This will be an open mint, at 0.005 + gas per NFT.</p>
<p>The price tag is there to make sure that ships are distributed to many holders, and prevent someone from minting 1000s of them.</p>
<p>Like in Phase II, ships minted during this phase will be copies of the OG ships, without the OG flag.</p>
<p><figure><img src="https://blog.vrypan.net/2024/03/08/l-o-l/preview-04.png" alt="8==::--x-(@)=8" /></figure></p>
<hr />
<p><strong>Dates and final details to be announced.</strong>
If you want to stay up-to-date, <a href="https://warpcast.com/l--o--l">follow |--o--| on Farcaster</a>.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2024/03/08/l-o-l/edition.svg"
   type="image/svg+xml"
   length="2660"/>

   <enclosure url="https://blog.vrypan.net/2024/03/08/l-o-l/preview-01.png"
   type="image/png"
   length="13481"/>

   <enclosure url="https://blog.vrypan.net/2024/03/08/l-o-l/preview-02.png"
   type="image/png"
   length="10460"/>

   <enclosure url="https://blog.vrypan.net/2024/03/08/l-o-l/preview-03.png"
   type="image/png"
   length="13151"/>

   <enclosure url="https://blog.vrypan.net/2024/03/08/l-o-l/preview-04.png"
   type="image/png"
   length="20619"/>

    </item>
    
    <item>
      <title>Farcaster is a better match for SpaceX than X.
</title>
      <link>https://blog.vrypan.net/2023/12/20/farcaster-is-a-better-match-for-spacex-than-x/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2023/12/20/farcaster-is-a-better-match-for-spacex-than-x/</guid>
      <pubDate>Wed, 20 Dec 2023 20:53:11 +0200</pubDate>
      <description>Let's talk about hubs and how they sync.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2023/12/20/farcaster-is-a-better-match-for-spacex-than-x/mars2.png">
        
	<p>Let's talk about hubs and how they sync.</p>
<p>The Farcaster network is a network of hubs that exchange messages between them. Each hub holds the entire &quot;global state&quot;: every cast, reaction, follow, every user's profile data, everything.</p>
<p>The farcaster app you are using, only has to connect to one of the hubs to read and post messages. Then this hub syncs with the rest of the network and every other hub receives your activity.</p>
<p>Hubs exchange messages between them in two ways:</p>
<ol>
<li>
<p>The first one, is practically real-time: The hub that receives a message uses a protocol called gossipsub and sends the message to the hubs it's connected to, then they do the same and in just a few seconds all hubs have received the message.</p>
</li>
<li>
<p>The second is an out-of-band sync. This one is slower and only happens every few minutes (or whenever it's feasible, more on this later). During the out-of-band sync, two hubs practically compare their databases, and exchange deltas in order to get to the same status (exchange deltas to reach the same state).</p>
</li>
</ol>
<p>If you are interested, <a href="https://www.youtube.com/watch?v=Uqga87HWs_g">there is a video describing the concept in more detail</a>.</p>
<h2>Advantages</h2>
<p>This model has a number of advantages:</p>
<ul>
<li>It's developer friendly, because a developer can have a full copy of the network, locally, to work with</li>
<li>It's decentralized and censorship resistant because there's no single point of entry to the network</li>
<li>It's very resilient because you can take away any number of hubs (a recent count of Farcaster hubs brings them to ~150) and if there is at least one left, spawn new ones and reconstruct the network as if nothing happened.</li>
</ul>
<p>These characteristics make Farcaster ideal for a number of environments where other social networks (centralized or federated) would fail.</p>
<h2>When the office ISP went down</h2>
<p>Imagine you are at work, using Farcaster by connecting to the office Farcaster hub that runs locally, and you are using a Farcaster client that connects directly to the hub <sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. At some point, your ISP goes down.</p>
<p>Here is what happens during the period you have lost connection to the rest of the Internet:</p>
<ol>
<li>
<p>You continue to have access to everything that was posted on Farcaster up to the moment the Internet connection went down.</p>
</li>
<li>
<p>You can also cast, like, recast, follow and unfollow as if nothing changed.</p>
</li>
<li>
<p>You can also see new casts and reactions from your colleagues that use the same hub, and you can reply and react to their casts.</p>
</li>
</ol>
<p>The most important thing that changes during the period the ISP is down, is that you don't see any activity that happens outside your office (your office farcaster hub). But as soon as the ISP is up again, your hub will connect to the other hubs, it will propagate any activity that happened (in the office) during downtime, and receive all activity that happened outside your hub!</p>
<p>There are a few things that wouldn't work while the ISP is down:</p>
<ol>
<li>
<p>Any Farcaster activity that requires an onchain transaction, such as creating new accounts, approving and removing signers, or purchasing storage units.</p>
</li>
<li>
<p>Of course, any content referenced or embedded in casts will not be available, such as images -but that's not Farcaster's problem and if someone really wanted to, they could fix it by using a caching proxy or something similar.</p>
</li>
</ol>
<h2>Social media on the Mars colony</h2>
<p>One of the challenges a crew of a future the Mars colony will have to overcome is staying connected with Earth. Radio signals take 4-22 minutes to get from Earth to Mars, and it will take as much for a response to come back. There's not much we can do about this, unless we find a way for the radio signals to travel faster than light.</p>
<p>One more problem is that the available bandwidth is nothing compared to what we are used on terrestrial communications. I expect that all available bandwidth, will be used to support the operations of the station, and to exchange asynchronous messages between the station crew and Earth command center and their families.</p>
<p>One thing is for sure: The Mars crew will not be able to use X/Twitter, because it's built on HTTP, a synchronous protocol. However, <strong>our astronauts could use Farcaster!</strong></p>
<p>An other cool thing is that Earth-March syncing could also be performed entirely off-line: Every mission to Mars could also carry a Earth-synced hub, that would sync with Mars when it gets there and every mission from Mars to Earth could carry the Mars state back to Earth.</p>
<p>Astronauts will have full access to everything discussed on Farcaster on Earth, interact between them, share their thoughts, and when their hub syncs with Earth, we will all be able to see their activity, react to it, etc., and vice versa.</p>
<p>We may have <a href="https://github.com/farcasterxyz/protocol/discussions">to create an FIP</a> to introduce some small changes to support the Mars colony use case, but I'm optimistic that space settlers count as qDAUs and it will get the full support of the devs.</p>
<p>So, yes: <strong>Farcaster is a better match for SpaceX than X!</strong></p>
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>A small note on Farcaster clients connecting directly to hubs. Today, most Farcaster clients depend on a backend hosted by the developer or a third party. These backends take a lot of the load that otherwise a client would have to do, like hosting a database that can be easily queried. These clients will not work without connection to this backend. However, it's 100% feasible to create a client that connects directly to a Farcaster hub, or even have a local installation of the backend required. <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2023/12/20/farcaster-is-a-better-match-for-spacex-than-x/mars2.png"
   type="image/png"
   length="2225576"/>

    </item>
    
    <item>
      <title>All about Farcaster Signers
</title>
      <link>https://blog.vrypan.net/2023/11/25/all-about-farcaster-signers/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2023/11/25/all-about-farcaster-signers/</guid>
      <pubDate>Sat, 25 Nov 2023 07:31:50 +0200</pubDate>
      <description>Most users know "Signers" as "this thing you have to pay for when you connect a new app". One of the first articles in Purple Sumbarine, was about Farcaster Signers, but my understanding has evolved since then, and we also have new tools and advances since then.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2023/11/25/all-about-farcaster-signers/signers.png">
        
	<p>Most users know &quot;Signers&quot; as &quot;this thing you have to pay for when you connect a new app&quot;. <a href="https://paragraph.xyz/@purplesubmarine/farcaster-signers">One of the first articles in Purple Sumbarine, was about Farcaster Signers</a>, but my understanding has evolved since then, and we also have new tools and advances since then.</p>
<p>In order to understand signers, you have to keep in mind that all interactions with hubs take place by sending hubs a &quot;message&quot; that has a specific structure. So, when you cast, like, or recast, the app you are using sends a message to a hub saying &quot;@vrypan.eth casted Hello World&quot;, or &quot;@vrypan.eth liked this cast&quot;.</p>
<p>Messages look something like this under the hood:</p>
<p><figure><img src="https://blog.vrypan.net/2023/11/25/all-about-farcaster-signers/screenshot1.png" alt="" /></figure></p>
<p>As you can see such messages have two parts.</p>
<ul>
<li>
<p>The data part: this is more or less what we usually consider the content, like the text of the cast, the date it was casted, the user who casted.</p>
</li>
<li>
<p>The metadata part which has a hash of the data, a digital signature of the hash, and the key that produced the signature: <strong>the signer</strong>.</p>
</li>
</ul>
<p>(What you see in the signer filed is not the actual signer, but the public key of the signer.)</p>
<h2>Why we need signers</h2>
<p>In a centralized network such as twitter or facebook, you usually have a username and a password. You use your credentials to connect to a server, and then the server knows that you are who your credentials say you are. There is no other way to post something to the service, and the centralized server is the absolute authority of what was posted by whom.</p>
<p>Farcaster is an open, p2p network. Anyone with some technical knowledge can create a program that sends messages to the Farcaster network. The only way to verify the authenticity of these messages, is by their digital signature.</p>
<p>Each Farcaster user has their own keypair, a private and a public key. If you signed up using Warpcast, your recovery phrase can be used to generate this pair. This keypair also corresponds to an ethereum address, what is often called in Farcaster the custody wallet.</p>
<p>So, you could actually sign your messages using your private key. But users rarely create these messages on their computer using a program they wrote. They connect to a service or app, like buidler and after authenticating with it, it posts on their behalf. The problem is you don't want to give them your private key. This would be the equivalent of giving a gmail integration your username and password (and to some extent, not even being able to change the password).</p>
<p>Here is where Farcaster Signers come to play: Instead of giving an app your private key, the app creates a new random key, and asks you to approve it. You approve it using your private key and you register your approval onchain (<strong>gas cost!</strong>). From this point on, any hub that receives a message signed by this Signer, can check the blockchain to verify that you have approved the signer and accept it as authentic.</p>
<h2>Warpcast and meta-transactions</h2>
<p>When you make a call to a smart contract, the caller has to pay the gas for its execution. This is why adding or revoking a signer (onchain transactions) have a cost.</p>
<p>Normally, your Farcaster custody wallet would need to have some OP ETH to perform these transactions.</p>
<p>But wait. There's a workaround: KeyGateway, the smart contract used to approve Signers, allows meta-transactions. You can think of meta-transactions like this:</p>
<ul>
<li>
<p>The user who wants to perform a transaction signs the transaction or an authorization to perform the transaction using his wallet. This is an offline action.</p>
</li>
<li>
<p>The signed transaction is not sent to the smart contract, but it is shared offchain with a third party, usually called the &quot;relayer&quot;.</p>
</li>
<li>
<p>The relayer performs the transaction and pays the required gas.</p>
</li>
</ul>
<p>Warpcast takes advantage of this feature to hide the added complexity of using a blockchain: It will ask the user to pay them $1, and then they use a meta-transaction and they pay for the gas.</p>
<p>This is roughly the equivalent of them saying <em>&quot;Just sign this paper, give me $1, and I'll take care of the rest.&quot;</em></p>
<p>The actual gas cost for adding and removing signers is usually well bellow $1. Warpcast now allows users to also pay using Warps, an in-app credit system: You can buy 500 Wraps for $5, and approving a signer will usually cost around 40-50 Warps (depending on gas cost at the time of the transaction).</p>
<p>(Warps are an interesting experiment that deserve a separate article.)</p>
<h2>Revoking a signer</h2>
<p>Obviously, a user must be able to revoke a signer, and they can do so using their private key and posting the revokation onchain to let everyone know that the signer is no longer authorized to act on their behalf. This was the whole point of not giving away our private key in the first place.</p>
<p>But, when a signer is revoked, hubs see messages that are no longer signed by a valid signer. Most people's first thought is OK, but these are old messages signed when the signer was valid. But you have to keep in mind that Farcaster is an open, p2p network. Hubs are added and removed all the time. You could spin up your hub right now (it's actually quite easy) and your hub would receive messages from other hubs it discovers in order to get its history (aka state) up to date. How can your newly created hub know when a message was signed?</p>
<p>This is why hubs have a simple way of &quot;thinking&quot;: not a valid signer, not a valid message. And, as a result, <strong>when you revoke a Signer, all messages signed using it, are pruned by hubs!</strong></p>
<p>This looks bad. The truth is there is a simple solution that no app (to my knowledge) has implemented (yet). Remember the message example we used earlier? What if you signed the same message with a different signer?</p>
<p><figure><img src="https://blog.vrypan.net/2023/11/25/all-about-farcaster-signers/screenshot2.png" alt="" /></figure></p>
<p>Signing the message with new signer will create a new signature, but the message data and the message hash will stay the same: Same user (fid), same content, same timestamp.</p>
<ul>
<li>
<p>To any client, this new, re-signed message is the same as the original one.</p>
</li>
<li>
<p>To any hub, this is a valid message, provided that the original (same hash) is not in the hub's database.</p>
</li>
</ul>
<p>So, an app could:</p>
<ol>
<li>Download all your messages (your Farcaster history)</li>
<li>When you remove a signer, and some messages are pruned, re-sign these messages (from your download) with a new signer.</li>
<li>Post the re-signed messages to a hub.</li>
</ol>
<hr />
<h3>Using fario</h3>
<blockquote>
<p>You can perform the above steps using <a href="https://github.com/vrypan/fario">https://github.com/vrypan/fario</a> if you are comfortable working in the command line. You will have to:</p>
</blockquote>
<blockquote>
<p>Backup your data using <code>fario-out --all</code>.</p>
</blockquote>
<blockquote>
<p>Use <code>fario-grep</code> to select the records signed by the signer you want to remove.</p>
</blockquote>
<blockquote>
<p>Remove the signer using <code>fario-signers remove</code> and create a new signer using <code>fario-signers add</code></p>
</blockquote>
<blockquote>
<p>Re-sign the messages using <code>fario-signers sign</code></p>
</blockquote>
<blockquote>
<p>Upload the re-signed messages using <code>fario-in</code></p>
</blockquote>
<h2>Final thoughts</h2>
<p>Signers are an elegant approach to delegating permissions. It allows users to easily let an app act on their behalf, but at any point in time, they can revoke this permission.</p>
<p>The lack of a simple, user-friendly app that allows users to revoke a signer without deleting all activity performed using it, is definitely a pain-point looking for solutions: Right now, using a signer means that you are stuck with it, since revoking access will delete any casts, likes, recasts and follows you have performed using it. (Unless you are one of the few users who understand the technical details of Signers, and have the skills to use something like fario or put together a script by yourself.)</p>
<p>Looking forward to try the first apps that will give a user-friendly solution to this!</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2023/11/25/all-about-farcaster-signers/screenshot1.png"
   type="image/png"
   length="429486"/>

   <enclosure url="https://blog.vrypan.net/2023/11/25/all-about-farcaster-signers/screenshot2.png"
   type="image/png"
   length="381806"/>

   <enclosure url="https://blog.vrypan.net/2023/11/25/all-about-farcaster-signers/signers.png"
   type="image/png"
   length="1394343"/>

    </item>
    
    <item>
      <title>The Farcaster icon font
</title>
      <link>https://blog.vrypan.net/2023/11/11/farcaster-icon-font/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2023/11/11/farcaster-icon-font/</guid>
      <pubDate>Sat, 11 Nov 2023 15:08:44 +0200</pubDate>
      <description>I wanted to use the farcaster icon, just like other app icons in my web pages.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2023/11/11/farcaster-icon-font/screenshot.png">
        
	<p>I wanted to use the farcaster icon, just like other app icons in my web pages.</p>
<p>For example, at the top of this page, you see a twitter icon. This icon is displayed
by using Font Awesome<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup> and then something like <code>&lt;i class=&quot;fa-brands fa-twitter&quot;&gt;&lt;/i&gt;</code>.
In this case, the icon is a font character, which means it scales with the rest of the text,
it changes color with the rest of the text, and so on.</p>
<p>I wanted something similar for Farcaster.</p>
<p>So, I converted the Farcaster logo outline to SVG using Pixelmator<sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup>, and the used Icomoon<sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup>
to turn it into a web font. Then, I manually cleaned up the result, and added some instructions
on how to use it.</p>
<p>You can find the result at <a href="https://github.com/vrypan/fc-font">github.com/vrypan/fc-font</a>.</p>
<p>After downloading the files, you use something like</p>
<pre><code>&lt;link rel=&quot;stylesheet&quot; href=&quot;farcaster/style.css&quot;&gt;
</code></pre>
<p>and then you can use the icon:</p>
<pre><code>&lt;i class=&quot;fc fc-farcaster&quot;&gt;&lt;/i&gt;
&lt;i class=&quot;fc fc-square-farcaster&quot;&gt;&lt;/i&gt;
</code></pre>
<p>and you'll get something like this:</p>
<div class="fc" style="font-size:40px;">π Π</div>
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://fontawesome.com">fontawesome.com</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://www.pixelmator.com/pro/">Pixelmator Pro</a> is a great design tool for macOS. <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p><a href="https://icomoon.io">Icomoon</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2023/11/11/farcaster-icon-font/screenshot.png"
   type="image/png"
   length="29373"/>

    </item>
    
    <item>
      <title>Welcome to farcaster</title>
      <link>https://blog.vrypan.net/2023/10/11/welcome-to-farcaster/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2023/10/11/welcome-to-farcaster/</guid>
      <pubDate>Wed, 11 Oct 2023 17:56:25 +0200</pubDate>
      <description>Farcaster is a lot like and a lot unlike other social networks. There's so much to learn and explore, but if you are new, this article will help you find your way around.</description>
      <content:encoded><![CDATA[
	
	<h2>I originally published this post on <a href="https://paragraph.xyz/@purplesubmarine">Purple Submarine</a>, a newsletter
about Farcaster. But I think it can be of help to anyone interested in Farcaster.</h2>
<blockquote>
<p>On October 11, 2023, Farcaster opened its doors to everyone
(<a href="https://danromero.org/farcaster-permissionless/">a.k.a &quot;went permissionless&quot;</a>).</p>
</blockquote>
<p>Farcaster is a lot like and a lot unlike other social networks. There's so much to learn and explore, but if you are new, this article will help you find your way around.</p>
<h2>Warpcast is to Farcaster, what Firefox is to Web</h2>
<p><a href="https://www.farcaster.xyz/">Farcaster</a> is a protocol, and <a href="https://warpcast.com/">Warpcast</a> is a Farcaster client,
much like Firefox, Chrome, Safari and Edge are HTTP clients. There are many other clients and applications.
You can find an (incomplete!) <a href="https://www.farcaster.xyz/apps">list of applications that use Farcaster here</a>.</p>
<blockquote>
<p>If you don't have a Farcaster account, the simplest way to create one is to install Warpcast.</p>
</blockquote>
<h2>You own your Farcaster identity.</h2>
<p>Everything you do on Farcaster (casts, likes, recasts, follows, etc.) is tied to your Farcaster Identity (fid). No one can take away, suspend or cancel your Farcaster identity: it is controlled by an Ethereum address only you have the keys for. Don't worry, if you loose your keys,
<a href="https://paragraph.xyz/@purplesubmarine/farcaster-account-recovery">there is a way to recover your identity</a>.</p>
<h2>Open, Decentralized</h2>
<p><strong>Farcaster is an open protocol.</strong> This means than anyone can build applications on top of it, without asking permission and without paying fees. Compare this to using Facebook, Twitter/X, or Reddit APIs: Each one of these companies has changed policies, requirements and pricing, often pulling the rug under developers' feet.</p>
<p><strong>Farcaster is decentralized.</strong> At the core of Farcaster are the Farcaster hubs. Every hub keeps a complete copy of everything there is on Farcaster. Hubs talk to each other and sync their status to reach consensus. Anyone can run a hub. If you like experimenting, you can run your own hub, even from your home (hardware requirements are minimal, your previous PC or laptop is probably more than adequate).</p>
<h2>Why do I have to pay?</h2>
<p><strong>Because there is no Twitter or Facebook to pay the costs.</strong></p>
<p>In exchange, you own your Farcaster identity, data and network.</p>
<p>There are two costs to using Farcaster.</p>
<p>Storage space on hubs. For most users, this will be a cost between $0.6/month and $1/month, depending on the payment method. The easiest way to pay is through Warpcast's in-app purchase ($12/year including AppStore fees and USD-to-ETH conversion). But you can also use a service like caststorage.com, pay in ETH and avoid the AppStore tax.</p>
<p>Both methods bellow, will have the same result. Warpcast purchases are converted to ETH and used to perform the onchain transaction.
<figure><img src="https://blog.vrypan.net/2023/10/11/welcome-to-farcaster/farcaster-storage.png" alt="" /></figure></p>
<p><strong>The cost of identity-related transactions</strong> (remember, your Farcaster identity &quot;lives&quot; onchain, and onchain transactions have a small cost), such as the initial signup or giving permissions to apps. This cost is small, and in some cases apps may pay it on your behalf to make your life easier, but occasionally you may be asked to pay something like $0.99 (the actual cost is much less, and there will be ways and tools to pay much less in the future).</p>
<h2>Where can I learn more?</h2>
<ol>
<li><a href="http://farcaster.xyz/">farcaster.xyz</a> is the home of the Farcaster protocol.</li>
<li><a href="http://thehubble.xyz/">thehubble.xyz</a> is Hubble's homepage. Hubble is the software run by Farcaster nodes.</li>
<li><a href="https://www.youtube.com/watch?v=vMWjol6xHJ0&amp;list=PL0eq1PLf6eUdm35v_840EGLXkVJDhxhcF">Farcaster Overview</a>:
short videos explaining the core concepts of Farcaster. (Keep in mind that the videos were created some time ago,
and some of the details may have changed through <a href="https://docs.farcaster.xyz/protocol/fips.html">Farcaster Improvement Proposals</a>.)</li>
<li>Check out the articles on <a href="https://paragraph.xyz/@purplesubmarine">Purple Submarine</a>.</li>
</ol>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2023/10/11/welcome-to-farcaster/farcaster-storage.png"
   type="image/png"
   length="339882"/>

    </item>
    
    <item>
      <title>Farcaster account recovery
</title>
      <link>https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/</guid>
      <pubDate>Fri, 06 Oct 2023 10:26:13 +0200</pubDate>
      <description>Varun has created a video that explains everything in a very simple way:</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/header.png">
        
	<h2>How it works</h2>
<p>Varun has created a video that explains everything in a very simple way:</p>
<p><a href="https://youtu.be/DnAG4mXlOFI?si=kauG-qhvJ5FkI9xo"><figure><img src="https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/varun-account-recovery.png" alt="youtube video" /></figure></a></p>
<ul>
<li>Every Farcaster account is owned by an Ethereum address (often called “wallet”).</li>
<li>Every Farcaster account can also set a <strong>recovery address</strong>. The only thing the recovery address can do is to move your Farcaster account to a new address.</li>
</ul>
<p>Moving your account to a new address is quite a power to give to someone. The owner of the recovery address can save you if you lost your “secret phrase” (think of it as your password), by moving your account to a new address you control. But if they go rogue, or get hacked, they can also steal your Farcaster account!</p>
<p><figure><img src="https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/recovery.gif" alt="demo" /></figure></p>
<hr />
<h2>Failsafe, no failsafe</h2>
<p>If you watched the above video, you may have noticed that there was a fail-safe: Between the initiation of the account transfer and the actual transfer there was a <strong>5-day delay</strong> during which you could cancel it and even change/revoke the recovery address.</p>
<p>I’m writing in the past tense because this fail-safe was removed by <strong><a href="https://github.com/farcasterxyz/protocol/discussions/100">FIP-5: Instant Recovery</a></strong>: The recovery address can now instantly move your account to a new address and there’s nothing you can do about it.</p>
<p>While this may seem a bad thing, it’s not that bad, and there’s good reasoning behind it:</p>
<ol>
<li>99 % of the users, especially new users that will join once signups are open for everyone, are used to Web2 platforms: <em>I lost my password, I use my email to recover it.</em></li>
<li>When a new user signs up, <strong>Warpcast</strong> (that most of them will use to sign up) sets the recovery address to one Warpcast controls. This way they can hide the complexity from users, and provide them with what most users expect: Being able to instantly help them recover their account.</li>
</ol>
<p><figure><img src="https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/casts.png" alt="casts screenshot" /></figure>
<a href="https://warpcast.com/dwr.eth/0x7137eced">https://warpcast.com/dwr.eth/0x7137eced</a></p>
<hr />
<h2>Where did decentralization go?</h2>
<p>If you are here because of the Web3 ethos, decentralization and sovereignty, you’re probably disappointed. What I just described is a way for a centralized entity (Warpcast) to take away your decentralized Farcaster identity. If that’s the case, what’s the point of all the decentralization, web3 and the costs that come with them?</p>
<p>There are a couple of good answers.</p>
<ul>
<li>First of all, you can set your <strong>own recovery address</strong>: You can use another address you control, a good friend’s address you trust, or your lawyer’s Ethereum address (yes, there are some that know what this is).</li>
<li>You could also set it to an <strong>M-of-N multisig wallet</strong>, controlled by N people you trust.</li>
<li>I can also imagine more exotic implementations of a recovery address.
<ul>
<li>For example, all Farcaster accounts a company uses can have a recovery address controlled by their IT, which has a dual purpose:
<ol>
<li>Being able to support users who lost their secret phrase</li>
<li>Being able to take away a corporate account.</li>
</ol>
</li>
<li>Or a smart contract that implements the time-delay feature removed by FIP-5.</li>
<li>Or even create a valet service that users pay annually and in order to recover their account, users have to do a video call, prove their identity, and then the service helps them recover their account.</li>
</ul>
</li>
</ul>
<hr />
<h2>Takeaways</h2>
<ol>
<li>
<p>If you sign up to Farcaster using Warpcast, Warpcast can recover your account if you lose your keys, but they can also take away your account, or be compelled to do so. Keep this in mind if you think that someone may want to censor you in the future.</p>
</li>
<li>
<p>If you are an experienced Web3 user, you may want to consider some of the options mentioned above, like setting the recovery address to one controlled by your hardware wallet, or a multisig.</p>
</li>
<li>
<p>There is a wide range of services to be built that help users recover their Farcaster accounts. You may want to build one of them.</p>
</li>
</ol>
<hr />

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/casts.png"
   type="image/png"
   length="859572"/>

   <enclosure url="https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/header.png"
   type="image/png"
   length="1028011"/>

   <enclosure url="https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/recovery.gif"
   type="image/gif"
   length="3506566"/>

   <enclosure url="https://blog.vrypan.net/2023/10/06/farcaster-account-recovery/varun-account-recovery.png"
   type="image/png"
   length="927761"/>

    </item>
    
    <item>
      <title>Goodbye, Twitter
</title>
      <link>https://blog.vrypan.net/2023/08/14/goodbye-twitter/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2023/08/14/goodbye-twitter/</guid>
      <pubDate>Mon, 14 Aug 2023 21:28:58 +0200</pubDate>
      <description>Twitter is now X.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2023/08/14/goodbye-twitter/twitter-x.jpg">
        
	<p>Twitter is now X.</p>
<p>&quot;Ex&quot;, &quot;ten&quot;, &quot;ex-twitter&quot;, or &quot;the service formerly known as Twitter&quot;, it doesn't matter much. What matters (to me), is that this feels like the end of an era —from now on, it will be something else.</p>
<p>I feel that there is a whole Internet generation with a special place for Twitter in our hearts.</p>
<p>I signed up for twitter in December 2006. This was the time when the first wave of podcasting was getting traction. This was the time of Dave Winer's <em>Morning Coffee Notes</em> and Adam Curry's <em>Daily Source Code</em> (<em>&quot;we don't need no stinking transmitters!&quot;</em>) which was my inspiration for my own podcast.</p>
<p>Much like every other podcaster at the time, I was trying to understand how this new format works, and I was eager to try every new tool and service that promised to make podcasting better. One of them was <a href="https://en.wikipedia.org/wiki/Odeo"><em>ODEO</em></a>. I loved Odeo, and the people behind it, the co-founders of Pyra Labs, Noah Glass and Evan Williams, made it even more special to may eyes. Pyra Labs was the company that built blogger.com which is fair to say that made blogging accessible to everyone and transformed the Web from a read-only medium to read-write one for most.</p>
<p>In 2006, Odeo (actually Obvious Corp, the company that was formed to hold Odeo and other products the team would develop) launched Twitter, and since I was following what Odeo and Ev were doing, I had to try it. I was user #74233.</p>
<blockquote>
<p><figure><img src="https://blog.vrypan.net/2023/08/14/goodbye-twitter/Twttr_sketch-Dorsey-2006.jpg" alt="" /></figure></p>
</blockquote>
<blockquote>
<p>A sketch, c. 2006, by Jack Dorsey, envisioning an SMS-based social network <sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup></p>
</blockquote>
<p>For a few years, Twitter was a public place where &quot;Internet geeks&quot; would &quot;gather&quot;. The Internet was much smaller than today (not small, but much smaller), and the first Twitter users were the people we already knew from blogs and podcasts. The most followed accounts were not brands, politicians or pop stars, but bloggers, podcasters, developers and tech entrepreneurs.</p>
<p>To me, and I think for many people like me at the time, twitter's appeal was twofold:</p>
<ol>
<li>It was an open system, with a simple, open API, true to the ideas of Web2.0 at the time: A service we could integrate with our own services, write scripts for, build tools and applications on top of.</li>
<li>I did not have to find a title for my content. Before Twitter, &quot;publishing to the web&quot;, was synonymous to blog posting and blog posts have titles which add a huge overhead when you want to write something casual —it just did not feel right to have blog post containing a single sentence and find a title for it. Blogs were not designed with this &quot;casual posting&quot; in mind, and Twitter's simplicity was liberating.</li>
</ol>
<hr />
<p>Twitter was home of many innovations and some of them originated came from their users.</p>
<p>It introduced the <code>@username</code> namespace. Until then, you either had a username or an email. The <code>@username</code> namespace is still a huge part of Twitter's brand equity.</p>
<p>The (initially small) scale allowed for features that have long been gone. Like the <code>track</code> command: You could tweet <code>track pizza</code> and you would get notified whenever someone posted a tweet containing the word <em>pizza</em>. You could also use it to track usernames, which allowed you to get all mentions of a specific username.</p>
<p>There was no &quot;retweet&quot;: Users would copy paste a tweet and add <code>rt @username</code> in front of it (<a href="https://twitter.com/vrypan/status/1058909119?tw_i=1058909119&amp;tw_e=details&amp;tw_p=archive">like this</a>). Which meant that if you wanted your tweet to be retweeted with credit, you had to make sure there was enough space to add <code>rt @yourusername</code> and still be under the 140 characters limit —and short usernames had a nice advantage.</p>
<p>And there were no hashtags. Hashtags were <a href="https://buffer.com/resources/a-concise-history-of-twitter-hashtags-and-how-you-should-use-them-properly/">Chris Messina's &quot;invention&quot;</a> that were later adopted by Twitter.</p>
<p>Oh, and there was also a SMS gateway. (Remember, in 2006 the iPhone was not yet released.) So you could text 40404 (if you were in the US) with your tweet, and get SMS notifications when people you followed tweeted.</p>
<p>We also had &quot;FF&quot;, for &quot;Follow Friday&quot;: Every Friday, we would tweet <code>FF:</code> followed by usernames that posted interesting content, to help them be discovered by other users.</p>
<p>Twitter also popularised &quot;URL shorteners&quot;: Shortening a long link left you more characters to write your comment (and in some cases, it was the only way to make a link fit in 140 characters).</p>
<p>It was the first social network that grew to scale. The problem with scaling a social network with x users (the algebraic symbol as in <em>x+y</em>, not as in &quot;ex-twitter&quot;...) who follow one another is that complexity grows exponentially. So, after a point twitter would go down. And we would get the <a href="https://www.theatlantic.com/technology/archive/2015/01/the-story-behind-twitters-fail-whale/384313/">Fail Whale</a>.</p>
<p><figure><img src="https://blog.vrypan.net/2023/08/14/goodbye-twitter/failwhale.png" alt="Fail Whale screenshot" /></figure></p>
<hr />
<p>Since then, Twitter grew in scale, solved their technical issues, closed their API, integrated organically hashtags and retweets, expanded beyond 140 characters. A wider audience joined. It became a place for political debate, public discourse, and civic mobilisation, a customer relationships management tool, a sales channel, the breaking news channel. Internet hackers and geeks were hugely outnumbered by celebrities, politicians and their followers together with armies of bots and anonymous (and sometimes, professional) haters.</p>
<p>All this is not good or bad. I've been part of some of these changes, I ran political campaigns using Twitter, I advised companies on how to leverage twitter as a CRM tool, I promoted my work, I joined polarised conversations and received my share of anonymous hate. Things change. It just is what it is.</p>
<p>My original intention was to end this post by saying that Elon killed Twitter. But the Twitter I have in mind has long been gone. I guess that changing the name when everything else has already changed is an honest decision, after all.</p>
<p>(A delayed) <strong>Goodbye, Twitter and thank you for the memories.</strong></p>
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p>Source <a href="https://en.wikipedia.org/wiki/Twitter">Wikipedia</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2023/08/14/goodbye-twitter/Twttr_sketch-Dorsey-2006.jpg"
   type="image/jpeg"
   length="96013"/>

   <enclosure url="https://blog.vrypan.net/2023/08/14/goodbye-twitter/failwhale.png"
   type="image/png"
   length="120217"/>

   <enclosure url="https://blog.vrypan.net/2023/08/14/goodbye-twitter/twitter-x.jpg"
   type="image/jpeg"
   length="76152"/>

    </item>
    
    <item>
      <title>VisionPro's EyeSight may be a killer feature.
</title>
      <link>https://blog.vrypan.net/2023/06/06/visionpro-eyesight-is-a-killer-feature/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2023/06/06/visionpro-eyesight-is-a-killer-feature/</guid>
      <pubDate>Tue, 06 Jun 2023 10:26:13 +0200</pubDate>
      <description>Based on what was presented yesterday at WWDC, VisionPro is an amazing product. But what I'm really fascinated about is EyeSight. Here is why.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2023/06/06/visionpro-eyesight-is-a-killer-feature/eyesight-plain.png">
        
	<p>Based on what was presented yesterday at WWDC, <a href="https://www.apple.com/apple-vision-pro/">VisionPro is an amazing product</a>. But what I'm really fascinated about is EyeSight. Here is why.</p>
<p>EyeSight is an outward display. It's (intended? initial?) use will be to display your eyes while you are wearing the VisionPro in order to let people around you know if you're looking at them, or at someone else, or if you are immersed in an experience on your own.</p>
<p>This is obviously very important, because it retains the communication bandwidth provided by facial expressions. We all know that eyes and eye contact are an important, high-bandwidth communication channel for humans.</p>
<p><em>&quot;I saw it in her eyes&quot;, &quot;Eyes don't lie&quot;, &quot;Let the eyes do the talking&quot;</em> —others have said it better than me.</p>
<p>But I have the feeling that EyeSight can be more than this. In addition to preserving the existing communication bandwidth, it may also increase it! If Apple allows it, I can see a future where the outward display shows more than your eyes.</p>
<p>Imagine being able to do some hand gesture, or even eye gesture, like blinking your eyes in a specific way that change the display, and show emojis (I'm really bad at design, I'm sure any designer could make these look much better). Or even animations like fireworks or any animated meme gif!</p>
<p><figure><img src="https://blog.vrypan.net/2023/06/06/visionpro-eyesight-is-a-killer-feature/eyesight-emojis.png" alt="" /></figure></p>
<p>I know that the idea may sound silly to many, but there is a generation of people who are really good at communicating ideas and feelings using visual clues when they are in front of their keyboard but have no way of doing it IRL. (Just visit any discord server.) Being able to express themselves IRL, with images that are displayed exactly where the person they are talking to is looking can be a killer feature.</p>
<p>And the most interesting part is that if this turns out to be a killer feature, it's one that will drive adoption because it has built-in virality: when I use it, other people see how cool it is and they want it too.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2023/06/06/visionpro-eyesight-is-a-killer-feature/eyesight-emojis.png"
   type="image/png"
   length="1096889"/>

   <enclosure url="https://blog.vrypan.net/2023/06/06/visionpro-eyesight-is-a-killer-feature/eyesight-plain.png"
   type="image/png"
   length="998448"/>

    </item>
    
    <item>
      <title>The dangerous path of OpenSea's blacklisting tool
</title>
      <link>https://blog.vrypan.net/2022/11/08/the-dangerous-path-of-opensea-blacklisting-tool/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2022/11/08/the-dangerous-path-of-opensea-blacklisting-tool/</guid>
      <pubDate>Tue, 08 Nov 2022 01:06:02 +0200</pubDate>
      <description>So, OpenSea announced they are releasing a tool "that allows creators to enforce fees on chain". Here's why this tool is much more, and why it's scary.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2022/11/08/the-dangerous-path-of-opensea-blacklisting-tool/opensea.png">
        
	<p>So, OpenSea announced they are releasing a tool <em>&quot;that allows creators to enforce fees on chain&quot;</em><sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. Here's why this tool is much more, and why it's scary.</p>
<h2>How it works</h2>
<p>OpenSea offers a solidity library that creators can include in their NFT contracts. This library allows a creator to blacklist an address (the address of a marketplace) from being able to list and trade their NFTs. So, I can only sell the NFT at a marketplace <strong>only</strong> if it is not a blacklisted one.</p>
<p>@0xCygaar has a great in-depth analysis of the details on twitter. <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup></p>
<h2>Subscription lists</h2>
<p>Now, 99.99% of the creators do not know how to identify the addresses (and contract hashes, an other check provided), but OpenSea offers a solution for them: they can subscribe to a blacklist maintained by someone else who knows how to do these things and is willing to spend the time to maintain the list up to date as marketplaces deploy new contracts, they change their policies on royalties, new ones are launched and so on.</p>
<h2>The scary part</h2>
<p>This all sounds great. As a creator, I can block marketplaces and services that allow users to trade my NFTs without paying royalties, how cool is this. And I don't have to do much, my smart contract is subscribed to the OpenSea's blaclist and they make sure they update it.
Of course I could subscribe to a blacklist mainteined by someone else, but why bother, I know OpenSea, they are the experts.</p>
<p>Wait.</p>
<p>This is great until a government asks all marketplaces to implement something. KYC for example. And then demands from OpenSea to add the ones that did not comply to their blacklist.</p>
<p>Or until OpenSea has a dispute with an other marketplace over something. Over copyrights, over patents, over policies. Businesses get into these debates every day. And OpenSea decides to add this marketplace to their blacklist.</p>
<p>I can think of many scenarios where something like this happens. And I can see the competing marketplace trying to reach out to creators and explain to them with detailed hoots and videos how to use etherscan to go to the contract code and sign a transactions to unsubscribe from OpenSea's blacklist. Which most won't do, because it will seem scary, complicated, and in any case, <em>&quot;why go through all this if 90% of their sales are on OpenSea, anyway&quot;</em>?</p>
<p>I can also see how this could lead to a place where no one even tries to launch an other marketplace, because OpenSea has all the power: They have
the biggest share of the market, they are deeply integrated with the ecosystem, and if everything else fails they can find a reason to blacklist
competitors.</p>
<p>OpenSea will probably swear: <em>&quot;We would never do something like this!&quot;</em></p>
<p>But remember? We created crypto and web3 because we did not want to rely on promisses, we wanted the rules to be written in code.</p>
<h2>It's the email story, all over again.</h2>
<p>A couple of days ago, Jameson Lopp published a great article<sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup> explaining how email started as a completely decentralised protocol and ended up being one where 90% of email users are captured by 5 companies.</p>
<blockquote>
<p><em>It is said that those who do not learn from history are doomed to repeat it. I believe it is of utmost importance that proponents of decentralized protocols learn from the failures of those that have come before. The following is a review of 40 years of history for the protocol that is the foundation of email.</em></p>
</blockquote>
<p>It's amazing how we are about to do the same mistakes all over again.</p>
<p>What OpenSea released is not a royalties protection system. It's a blacklisting infrastructure. Yes, it can be used by creators to protect their royalties. This is how these types of centralised control have always been introduced: to protect us from &quot;something bad&quot;.</p>
<p>But what they are actually asking is to give up control, and give them more power.</p>
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://opensea.io/blog/announcements/on-creator-fees/">On Creator Fees</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://twitter.com/0xCygaar/status/1589309374060957696">@0xCygaar's twitter thread</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p><a href="https://blog.lopp.net/death-of-decentralized-email/">The Death of Decentralized Email
</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2022/11/08/the-dangerous-path-of-opensea-blacklisting-tool/opensea.png"
   type="image/png"
   length="2496441"/>

    </item>
    
    <item>
      <title>ERC721 Subset
</title>
      <link>https://blog.vrypan.net/2022/11/06/erc721-subset/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2022/11/06/erc721-subset/</guid>
      <pubDate>Sun, 06 Nov 2022 08:20:30 +0200</pubDate>
      <description>This is about a small ERC721 contract I wrote, but let me give you the context first.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2022/11/06/erc721-subset/opensea.png">
        
	<p>This is about a small ERC721 contract I wrote, but let me give you the context first.</p>
<p>I think of NFTs as a new data pointer. Much like filesystems (file path + file name), and URLs (protocol + server + path + filename), NFTs (contract address + item Id) provide us with a way to point to data.</p>
<p>If you think of an ERC721 contract as a bucket of &quot;files&quot;, we have developed ways to present, query and organise these &quot;files&quot;: We can refer to a specific one by Id, but we also have tools like NFT marketplaces that allow us to filter by trait.</p>
<p>The problem is that filtering by trait is based on the decisions that the smart contract developer did: If the contract creator added a colour trait, we can easily filter by colour for example.</p>
<p>But what if we want to create a different grouping? What if I want to create a way to group together my favourite items of a NFT collection, or the ones that have a characteristic not explicitly described in the NFT metadata? The most common example of this is ENS clubs: .eth domains that follow a pattern that some users find valuable or interesting (all digits, 4 digits, palindromes, English names, Arabic numerals, all emojis, etc.) <strong>We do not have a tool to do this grouping on-chain.</strong></p>
<p>This is where my smart contract comes in. I call it &quot;ERC721 Subset&quot; and I tried to implement it in a way that conforms with the ERC721 standard, but:</p>
<ul>
<li>It does not allow approvals and transfers (all related functions revert with an error.)</li>
<li>All tokens are owned by the contract and (based on the above) can't be transferred or traded.</li>
<li>The contractor needs a ERC721 contract address (the &quot;original collection&quot;) to be passed to.</li>
<li>There is an <code>add(tokenId)</code> and <code>remove(tokenId)</code> that add a token from the original collection to the subset. They are implemented as mint and burn functions to allow services like NFT marketplaces to track the addition and removal of tokens in a way that they understand.</li>
<li>There is an <code>exists(tokenId)</code> function that allows an other service or contract to check if a token is part of the subset.</li>
<li><code>tokenURI(tokenId)</code> is proxied to the function of the original contract, so the sub collection NFT looks exactly like the original one.</li>
</ul>
<hr />
<p>To illustrate how this works, I created an ERC721 Subset of the  <a href="https://onchainbirds.com/">OnChainBirds collection</a> that contains what their community call &quot;greyscales&quot;: These are birds that happen to use only black, white and grey traits. There is no specific trait that describes grayscales, but a user went through the whole collection and identified 17 of them.</p>
<p>So, I deployed A ERC721 Subset called &quot;OnChainBirds: Grayscales&quot;. If you look at the <a href="https://etherscan.io/address/0xe10250464f9a59435705f842e0e5958ba4f2071a">etherscan page of the contract</a>, you will see the contract creation and the <code>add()</code> calls to add the specific token Ids. If you go to <a href="https://opensea.io/collection/onchainbirds-greyscales">the OpenSea page</a> (or any other marketplace) you will get a nice gallery of these tokens.</p>
<hr />
<p>This is a first take on the idea. There are probably ways to make the smart contract more efficient, or more secure or add some features that will make it more useful. It would be nice for example if there was a way to programmatically manifest that this is not a normal ERC721 contract. Or a more efficient way to add multiple items. What are the implications for services (wallets, marketplaces, etc) that deal with ERC721 tokens? Would it make sense to make this an ERC standard?</p>
<p>If you have any suggestions or ideas, ping me <a href="https://twitter.com/vrypan">@vrypan</a>.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2022/11/06/erc721-subset/opensea.png"
   type="image/png"
   length="396992"/>

    </item>
    
    <item>
      <title>Implementing tokenURI as a separate contract
</title>
      <link>https://blog.vrypan.net/2022/05/13/erc721-tokenuri-contract/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2022/05/13/erc721-tokenuri-contract/</guid>
      <pubDate>Fri, 13 May 2022 12:25:06 +0200</pubDate>
      <description>The metadata extension of ERC721 includes tokenURI() that returns the metadata for a specific token ID:</description>
      <content:encoded><![CDATA[
	
	<p>The metadata extension of ERC721 includes <code>tokenURI()</code> that returns the metadata for a specific token ID:</p>
<pre><code>/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x5b5e139f.
interface ERC721Metadata /* is ERC721 */ {
    /// @notice A descriptive name for a collection of NFTs in this contract
    function name() external view returns (string _name);

    /// @notice An abbreviated name for NFTs in this contract
    function symbol() external view returns (string _symbol);

    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the &quot;ERC721
    ///  Metadata JSON Schema&quot;.
    function tokenURI(uint256 _tokenId) external view returns (string);
}
</code></pre>
<p>And the Openzeppelin implementation or ERC721 implements it like this (practically, it returns &quot;baseURI + tokenId&quot;)</p>
<pre><code>    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), &quot;ERC721Metadata: URI query for nonexistent token&quot;);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length &gt; 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : &quot;&quot;;
    }
</code></pre>
<p>For <a href="https://niftywalls.xyz">NiftyWalls</a>, is decided to implement tokenURI as a separate contract.</p>
<p>So, the NiftyWalls implementation looks like more or less this</p>
<pre><code>interface ITokenURI {
    function tokenURI(uint256 tokenId) public view returns (string memory) ;
}

contract NiftyWalls is Ownable, ERC721 {
    address public metadata;
    
...
...

  function tokenURI(uint256 tokenId) public view override(ERC721)returns (string memory) {
    require(_exists(tokenId), &quot;NiftyWalls: URI query for nonexistent token&quot;);
    IToknURI meta = ITokenURI(metadata);
    string memory json = meta.idToJson(tokenId);
    return string(abi.encodePacked(&quot;data:application/json;base64,&quot;, Base64.encode(bytes(json))));
  }
  
...
...

  function setMetadataContract(address _metadata) public onlyOwner {
    metadata = _metadata;
  }
</code></pre>
<p>A very simple implementation of the TokenURI contract would be something like this.</p>
<pre><code>contract TokenURI {
    string private baseURI = 'http://mysite/' ;
    
     function tokenURI(uint256 tokenId) public view returns (string memory) {
        return string(abi.encodePacked(baseURI, tokenId.toString())) ;
    }
}
</code></pre>
<p>The nice thing with this approach is that it allows you to upgrade the TokenURI contract to do interesting things in the future, without touching the NFT contract. For example:</p>
<ul>
<li>You may use <code>setMetadataContract()</code> to &quot;activate&quot; metadata only after all tokens are minted.</li>
<li>Or you could make the TokenURI contract return different metadata after a date or a block number is reached.</li>
<li>Or deploy a new TokenURI contract (and use <code>setMetadataContract()</code> to point your contract to it) that implements on-chain metadata.</li>
<li>Or deploy a new TokenURI contract that holds the metadata on-chain and allows for changes (for example, the owner of a token can change the name of the token).</li>
<li>Or even use on-chain events or an oracle to update metadata.</li>
</ul>
<p>The cost of implementing <code>tokenURI</code> as a separate contract is minimal, and the advantages are significant, so I expect more ERC721 contracts to implement it this way.</p>

]]></content:encoded>

    </item>
    
    <item>
      <title>What's the utility of a pfp NFT collection? Signalling.
</title>
      <link>https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/</guid>
      <pubDate>Wed, 19 Jan 2022 11:10:47 +0200</pubDate>
      <description>Obviously, every individual NFT image can signal something: Good taste, love for retro gaming, girl power, unconventional thinking, etc. But a 10k pfp are becoming brands that signal more than what the design of an individual item can.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/rarity-tools.png">
        
	<p>Obviously, every <em>individual</em> NFT image can signal something: Good taste, love for retro gaming, girl power, unconventional thinking, etc. But a 10k pfp are becoming brands that signal more than what the design of an individual item can.</p>
<p>Using a <a href="https://www.larvalabs.com/cryptopunks">CryptoPunk</a> is a signal by itself –which punk is secondary, especially if you don't own one. CryptoPunks signal OG status, (usually crypto-originating) wealth, someone who can spend 60ETH ($180,000) for a NFT.</p>
<p><figure><img src="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/cryptopunks-screenshot.png" alt="" /></figure></p>
<p>Costing at least 80ETH each ($240,000), <a href="https://boredapeyachtclub.com/#/home">Bored Apes</a> signal &quot;rock-star&quot;. You are part of an exclusive yacht club, only accessible to millionaires. Not the &quot;old money&quot; type, these are degen millionaires, eating pizza, wearing silly hats and having fun at parties.</p>
<p><figure><img src="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/bayc-screenshot.png" alt="" /></figure></p>
<hr />
<p>My personal experience with a couple of other projects:</p>
<p><a href="https://thehashmasks.com">Hashmasks</a> (floor is close to 1ETH, or $3000), <em>&quot;a living digital art collectible created by over 70 artists globally&quot;</em>, signal art. (They focus a lot on their OG status as this was one of the very first PFP NFT projects, but I think that the main signal is art.)</p>
<p><figure><img src="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/hashmasks-screenshot.png" alt="" /></figure></p>
<p>Some of their subcategories have evolved to carry additional signalling. For example, users renamed clown Hashmasks as part of a <a href="https://clownbanks.com/">&quot;banks are clowns&quot;</a> campaign (which btw, seems like a thing a contemporaty art project would address).</p>
<p><figure><img src="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/clown-banks.png" alt="" /></figure></p>
<p>An other project I follow, <a href="https://chubbies.io">Chubbies</a> (floor is about 0.07ETH or $210), created by a single, laid back developer called... solazy, signal geek zen: &quot;no roadmap, no team, no grand vision - just a mission to learn, experiment, and make fun projects&quot;.</p>
<p><figure><img src="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/chubbies-screenshot.png" alt="" /></figure></p>
<p>Solazy writes in the project's discord server:</p>
<blockquote>
<p><em>I want to think of Chubbies as my lifelong project but there's a reason I named myself @solazy.eth. I'm just one person (and sometimes my wife), with a finite amount of time, and many interests. I like the idea of working solo and I put on many hats: backend dev, frontend dev, artist, community manager, marketer, founder etc.</em></p>
</blockquote>
<blockquote>
<p><em>I can't and won't do most of the things you probably expect from other projects. Thus, I've decided to set clear boundaries and expectations for this to be sustainable and fun for me to continue.</em></p>
</blockquote>
<hr />
<p>I think that once we understand that <strong>the main utility of these NFTs is signalling</strong>, projects will start to focus more on their brand identity and brand values and less on other things like &quot;roadmaps&quot; and &quot;utility&quot;.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/bayc-screenshot.png"
   type="image/png"
   length="1254925"/>

   <enclosure url="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/chubbies-screenshot.png"
   type="image/png"
   length="142939"/>

   <enclosure url="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/clown-banks.png"
   type="image/png"
   length="6766301"/>

   <enclosure url="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/cryptopunks-screenshot.png"
   type="image/png"
   length="1197445"/>

   <enclosure url="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/hashmasks-screenshot.png"
   type="image/png"
   length="1894079"/>

   <enclosure url="https://blog.vrypan.net/2022/01/19/10k-pfp-nft-utility-is-signaling/rarity-tools.png"
   type="image/png"
   length="393874"/>

    </item>
    
    <item>
      <title>Putting an old iMac to use
</title>
      <link>https://blog.vrypan.net/2022/01/06/putting-an-old-imac-to-use/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2022/01/06/putting-an-old-imac-to-use/</guid>
      <pubDate>Thu, 06 Jan 2022 13:54:11 +0200</pubDate>
      <description>So, I have this old iMac "Early 2009" Aluminum iMac Core 2 Duo. I decided to make something usefull out of it, so I upgraded the RAM to 8GB, replaced the original HDD with 1TB SSD and installed Ubuntu 20.24.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2022/01/06/putting-an-old-imac-to-use/head.png">
        
	<p>So, I have this old iMac &quot;Early 2009&quot; Aluminum iMac Core 2 Duo. I decided to make something usefull out of it, so I upgraded the RAM to 8GB, replaced the original HDD with 1TB SSD and installed Ubuntu 20.24.</p>
<p><strong>Important note:</strong> Bellow, I describe how I configured autologin and how I changed permissions to /sys/. These <strong>are NOT</strong> are not good security practices. However, given that the machine is sitting on my desk, and behind a well configured firewall, my assesment was that it is safe for me to do them. Please do your own security assesment.</p>
<h1>Installing Ubuntu</h1>
<p>Intalling Ubuntu was straight forward with two exceptions:</p>
<ul>
<li>The nouveau video driver seems to freeze when X does something intensive (and by intencive I mean opening Firefox). But I did not care about it as I intended to use this on console mode.</li>
<li>The wifi driver is a commercial one, and you have to have newtork connectivity to install it. So, I had to use Ethernet, use <code>ubuntu-drivers</code> to identify the driver I needed and install it. From that point on, I could configure wifi and Ethernet was no longer needed.</li>
</ul>
<h1>Booting in console mode.</h1>
<p>First stem, was to disable X from starting on boot.</p>
<pre><code>systemctl enable multi-user.target
systemctl set-default multi-user.target
</code></pre>
<p>/etc/default/grub</p>
<pre><code># If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.
# For full documentation of the options in this file, see:
#   info -f grub -n 'Simple configuration'

GRUB_DEFAULT=&quot;Ubuntu&quot;
GRUB_TIMEOUT=&quot;3&quot;
GRUB_DISTRIBUTOR=&quot;`lsb_release -i -s 2&gt; /dev/null || echo Debian`&quot;
GRUB_CMDLINE_LINUX_DEFAULT=&quot;text&quot;
GRUB_CMDLINE_LINUX=&quot;&quot;

# Uncomment to disable graphical terminal (grub-pc only)
GRUB_TERMINAL=&quot;console&quot;

GRUB_GFXMODE=&quot;640x480&quot;
# Uncomment to disable generation of recovery mode menu entries
GRUB_DISABLE_RECOVERY=&quot;false&quot;

# Uncomment to get a beep at grub start
GRUB_INIT_TUNE=&quot;480 440 1&quot;

GRUB_DISABLE_OS_PROBER=&quot;true&quot;
GRUB_SAVEDEFAULT=&quot;false&quot;
</code></pre>
<h1>Configuring tty1</h1>
<p>This would be a keyboardless system, so I would like to make sure that tty1 starts with some things on it.</p>
<pre><code>$ sudo systemctl edit getty@tty1.service
</code></pre>
<p>This (creates and) openes file <code>/etc/systemd/system/getty@tty1.service.d/override.conf</code> for editing. I entered:</p>
<pre><code>[Service]
ExecStart=
ExecStart=-/sbin/agetty --noissue --autologin vrypan %I $TERM
Type=idle
</code></pre>
<p>To enable the service and starts an auto-login session on tty1:</p>
<pre><code>$ sudo systemctl enable getty@tty1.service; sudo systemctl restart getty@tty1.service
</code></pre>
<p>To automatically run some useful stuff on tty1, I added the following lines to <code>$HOME/.profile</code>:</p>
<pre><code>if [[ &quot;x$XDG_VTNR&quot; = &quot;x1&quot; &amp;&amp; &quot;x$SHLVL&quot; = &quot;x1&quot; ]] ; then
    # Sometimes fbterm failed to start immediately, it seems that
    # the framebuffer needs a couple of milliseconds to initialise.
    # Or maybe it's something else, but waiting a second or
    # two fixed it.
    echo Waiting 2 secs... 
    sleep 2
    /usr/bin/fbterm -- tmuxp load -y $HOME/custom/tmuxp.tty1.yaml 
fi
</code></pre>
<p>tmuxp.tty1.yaml will start a tmux session with all the panes arranged like I want them and run the corresponding processes in each one of them.</p>
<pre><code>#  tmuxp.tty1.yaml
session_name: tty1
windows:
  - window_name: status
    focus: 'true'
    layout: 0774,240x75,0,0{91x75,0,0[91x10,0,0{45x10,0,0,1,45x10,46,0,7},91x64,0,11,2],148x75,92,0[148x38,92,0,3,148x36,92,39,4]}
    options:
      automatic-rename: 'off'
      pane-active-border-style: fg=black
      pane-border-style: fg=black
      status: &quot;off&quot;
    panes:
    - tty-clock
    - while true; do clear; ncal -M ; sleep 1m ; done
    - while true; do clear; calendar -A 2 ; sleep 1m ; done
    - glances -1
    - colortail -f &lt;(docker exec pihole pihole -t )
    start_directory: /home/vrypan
  
  - window_name: lights_on
    panes:
      - shell_command:
          - tput setab 7
          - clear
</code></pre>
<p>And this is the result:</p>
<p><figure><img src="https://blog.vrypan.net/2022/01/06/putting-an-old-imac-to-use/screenshot.png" alt="screenshot" /></figure></p>
<h1>The services</h1>
<p>I also installed docker, and then configured a couple of containers (that replaced rasperrypis I used for this purposes):</p>
<ul>
<li><a href="https://hub.docker.com/r/pihole/pihole">pihole</a></li>
<li>an <a href="https://hub.docker.com/r/ipfs/go-ipfs/">ipfs server</a></li>
<li>and <a href="https://github.com/oznu/docker-homebridge">homebridge</a></li>
</ul>
<p>I also configured syslog-ng to receive logs from my Unifi Dream Machine:</p>
<pre><code># /etc/syslog-ng/conf.d/remote.conf 
source t_src { tcp(port(514)); };
source u_src { udp(port(514)); };
destination r_all { file(&quot;/var/log/$HOST&quot;); };
log { source(t_src); source(u_src); destination(r_all); };
</code></pre>
<h1>Using the iMac as a (sort of) LED panel light</h1>
<p>You may have noticed there is a second tmux window, called <em>ligths_on</em>. I find this kind of cool. It's a window that is all white (tput settab 7 sets the background to white). So I can ssh to this machine, do <code>tmux next -t tty1</code> and the screen will turn on white.</p>
<p>And since this is placed on my desk, I use it as a light panel (!!!) that makes me look better when I'm on a video call on my laptop. Then <code>tmux next -t tty1</code> will switch back to my normal &quot;control center&quot; view.</p>
<p><figure><img src="https://blog.vrypan.net/2022/01/06/putting-an-old-imac-to-use/lights-on.png" alt="" /></figure></p>
<p>Of course, don't expect a thousand nits from this display. But it makes a difference when there's low light.</p>
<h1>Turning on and off the iMac screen using Siri</h1>
<p>I don't want my iMac screen to be on all the time. So I use the following over ssh</p>
<pre><code>$ echo 0 |sudo tee /sys/class/backlight/nv_backlight/brightness # turn off
$ echo 100 |sudo tee /sys/class/backlight/nv_backlight/brightness # turn on
</code></pre>
<p>But since I have already homebridge running, why not use Siri for this?</p>
<p>I order to easily allow the homebridge docker container to access /sys/class/backlight/nv_backlight/brightness I changed the permissions</p>
<pre><code>$ sudo chmod 666 /sys/class/backlight/nv_backlight/brightness
</code></pre>
<p>and I also mount <code>/sys/class/backlight/nv_backlight/</code> as a rw docker volume, so my docker-compose file looks like this:</p>
<pre><code>version: '2'
services:
  homebridge:
    image: oznu/homebridge:latest
    container_name: homebridge
    restart: always
    network_mode: host
    environment:
      - TZ=Europe/Athens
      - PGID=1000
      - PUID=1000
      - HOMEBRIDGE_CONFIG_UI=1
      - HOMEBRIDGE_CONFIG_UI_PORT=8581
    volumes:
      - $HOME/data/homebridge:/homebridge
      - /sys/class/backlight/nv_backlight:/backlight:rw
</code></pre>
<p>Next I installed the <a href="https://github.com/cr3ative/homebridge-shell-switch#readme">homebridge-shell-switch</a> plugin, and configured like this:</p>
<pre><code>{
    &quot;accessory&quot;: &quot;ShellSwitch&quot;,
    &quot;name&quot;: &quot;Monitor&quot;,
    &quot;onCmd&quot;: &quot;echo 100 &gt; /backlight/brightness&quot;,
    &quot;offCmd&quot;: &quot;echo 0 &gt; /backlight/brightness&quot;
}
</code></pre>
<p>Now, I can turn on and off the monitor by saying <em>Hey Siri, turn the monitor off</em>. I can also schedule the monitor to turn off during the night for example, or turn it on/off using the Home.app on my iPhone.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2022/01/06/putting-an-old-imac-to-use/head.png"
   type="image/png"
   length="79055"/>

   <enclosure url="https://blog.vrypan.net/2022/01/06/putting-an-old-imac-to-use/lights-on.png"
   type="image/png"
   length="930028"/>

   <enclosure url="https://blog.vrypan.net/2022/01/06/putting-an-old-imac-to-use/screenshot.png"
   type="image/png"
   length="289680"/>

    </item>
    
    <item>
      <title>Christina's Linux adventures, part 2.
</title>
      <link>https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures-part-2/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures-part-2/</guid>
      <pubDate>Sun, 26 Dec 2021 21:42:21 +0200</pubDate>
      <description>(If you haven't done so, read Part 1 of this series.)</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures-part-2/printout.jpeg">
        
	<p>(If you haven't done so, read <a href="/2021/12/26/christina-s-linux-adventures/">Part 1</a> of this series.)</p>
<p>The next morning, when Christina woke up, she found the above note.</p>
<p>This is what Tips-and-Tricks-1.txt said:</p>
<pre><code>Hello, Christina!

Try the following commands!

$ bb

$ fortune

Every time you run fortune, you get a new fortune cookie. Try it.

Now, try this:
$ echo &quot;Hello, Christina!&quot; | boxes -d santa
$ echo &quot;Hello, Christina!&quot; | boxes -d boy
$ echo &quot;Hello, Christina!&quot; | boxes -d girl
$ echo &quot;Hello, Christina!&quot; | boxes -d cat

If you want to see all available &quot;boxes&quot;, type
$ boxes -l

You can always pipe the output of one command to an other!

$ echo &quot;Hello, Christina!&quot; | boxes -d cat | lolcat

or...

$ fortune | boxes -d cat | lolcat

or even.....

$ fortune | cowsay | boxes -d cat | lolcat

Remember, you have already used the following commands:

ls
ls -l
pwd
cd
asciiquarium
cowsay
lolcat

You can see your terminal history by typing 
$ history

</code></pre>
<p>After she tried all the above, I heard what every geek dad wants to hear:</p>
<blockquote>
<p><em>Is there a way to make this fortune cookie appear every time I log in?</em></p>
</blockquote>
<p>Yes!!! She has questions!!! Now, we are in business.</p>
<p>We edited <code>.bashrc</code> and added <code>fortune | boxes -d cat | lolcat</code> at the end.</p>
<p>An other thing she tried was a box, within a box, within a box, something like <code>fortune | boxes -d mouse | boxes -d cat | boxes -d dog</code></p>
<p>She spent a big part of the day trying various combinations of the commands she knows.</p>
<p>Our day, ended with this.</p>
<blockquote>
<p>Dad, I think the terminal is my favourite app.</p>
</blockquote>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures-part-2/printout.jpeg"
   type="image/jpeg"
   length="170579"/>

    </item>
    
    <item>
      <title>Christina's Linux adventures. Part 1.
</title>
      <link>https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/</guid>
      <pubDate>Sun, 26 Dec 2021 13:01:29 +0200</pubDate>
      <description>One of Christina's Christmas presents was an old MacBook (Late 2008 Aluminum), that had not been used for years. I cleaned it, formated the disk and installed Linux Mint.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/lolcat1.png">
        
	<p>One of Christina's Christmas presents was an old MacBook (Late 2008 Aluminum), that had not been used for years. I cleaned it, formated the disk and installed Linux Mint. <sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup></p>
<p>Before we presented it to her, I had already created an account for her, so I just had to give her the password and she logged in.</p>
<p>Christina is quite experienced with computers and electronics (as most of the kids her age), but she mostly lives inside her iPad, and I realised that the desktop environment looked strange to her. Especially the trackpad gestures like tap-to-click, or two-fingers-click, etc.</p>
<p>Not surprisingly, the first thing she wanted to know is how to change the desktop background 😆. Which turned out to be a good opportunity to use right-click-save, after she googled for backgrounds. We also installed Skype, and tested OpenOffice Writer.</p>
<hr />
<p>Next stop was the terminal (and to be honest, this was my goal, what we had done so far she could do much better and easier on her iPad).</p>
<p>She had already seen a terminal a year ago, when I tried and failed to introduce her to Python on an old iMac (where almost nothing worked without tweaking). I also took the opportunity to explain to her that the application is called &quot;terminal&quot; because it's a software that works just like... a terminal. Yes, we have one of these in the house.</p>
<p>This time, I decided to start with something fun. <sup class="footnote-ref"><a href="#fn-2" id="fnref-2" data-footnote-ref>2</a></sup></p>
<pre><code>$ sudo apt install sl
$ sl
</code></pre>
<p><figure><img src="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/linux-terminal-train.png" alt="" /></figure></p>
<p>Next we tried <code>asciiquarium</code><sup class="footnote-ref"><a href="#fn-3" id="fnref-3" data-footnote-ref>3</a></sup>,
<figure><img src="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/asciiquarium.png" alt="" /></figure></p>
<p>and <code>cowsay</code><sup class="footnote-ref"><a href="#fn-4" id="fnref-4" data-footnote-ref>4</a></sup>
<figure><img src="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/cowsay.png" alt="" /></figure></p>
<p>I also installed <code>aalib</code>, <code>aview</code> and <code>jp2a</code>  which allowed us to view the pokemon image she downloaded in the terminal.
<figure><img src="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/jp2a.png" alt="" /></figure></p>
<p>What turned out to be a great hit, was <code>lolcat</code><sup class="footnote-ref"><a href="#fn-5" id="fnref-5" data-footnote-ref>5</a></sup>, which also provided a nice intro to using Unix pipes. Once she got to know <code>lolcat</code>, she had to pipe the output of every command she knew through it.
<figure><img src="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/lolcat1.png" alt="" /></figure></p>
<p>As we went through these commands, we also had to learn <code>ls</code>, <code>pwd</code>, even <code>sudo</code> (&quot;it's like 'please', for Linux&quot;). I tried to let her do most of the typing, and let her get the expected errors when she did not leave a space or when a file was not found because of an uppercase letter, etc.</p>
<p>Overall, she got really excited with her new laptop, and especially with the command line.</p>
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-1">
<p><a href="https://www.reallinuxuser.com/bring-your-macbook-aluminum-late-2008-back-to-life-again-with-linux/">Bring your MacBook Aluminum Late 2008 back to life again with Linux</a> <a href="#fnref-1" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="https://itsfoss.com/ubuntu-terminal-train/">Running a Train in the Linux Terminal to Amuse Your Friends and Family</a> <a href="#fnref-2" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>
<li id="fn-3">
<p><a href="https://robobunny.com/projects/asciiquarium/html/">ASCIIquarium</a> <a href="#fnref-3" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
<li id="fn-4">
<p><a href="https://alligator.io/workflow/cowsay/">Command-line Basics: Dressing up Output with cowsay</a> <a href="#fnref-4" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="4" aria-label="Back to reference 4">↩</a></p>
</li>
<li id="fn-5">
<p><a href="https://www.tecmint.com/lolcat-command-to-output-rainbow-of-colors-in-linux-terminal/">Lolcat – A Command Line Tool to Output Rainbow Of Colors in Linux Terminal</a> <a href="#fnref-5" class="footnote-backref" data-footnote-backref data-footnote-backref-idx="5" aria-label="Back to reference 5">↩</a></p>
</li>
</ol>
</section>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/asciiquarium.png"
   type="image/png"
   length="9917"/>

   <enclosure url="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/cowsay.png"
   type="image/png"
   length="189803"/>

   <enclosure url="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/jp2a.png"
   type="image/png"
   length="582181"/>

   <enclosure url="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/linux-terminal-train.png"
   type="image/png"
   length="12206"/>

   <enclosure url="https://blog.vrypan.net/2021/12/26/christina-s-linux-adventures/lolcat1.png"
   type="image/png"
   length="93952"/>

    </item>
    
    <item>
      <title>web3, ens and trademarks
</title>
      <link>https://blog.vrypan.net/2021/11/05/web3-ens-and-trademarks/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/11/05/web3-ens-and-trademarks/</guid>
      <pubDate>Fri, 05 Nov 2021 11:37:47 +0200</pubDate>
      <description>Of course, all this may make no sense to you. ENS, .eth, web3, wtf are they?</description>
      <content:encoded><![CDATA[
	
	<blockquote>
<p>Trademarks + Web3. 1/🧵 <small>// @vrypan<a href="https://twitter.com/i/web/status/1456536317463044122">→</a></small></p>
</blockquote>
<blockquote>
<p>Web3 will bring new identity systems, like @domains_ens. Your ENS domain will be the way for others to verify it's you, it will probably be the way social networks will verify the identity of your brand, it will be the address where your clients will use to pay you. 2/ <small>// @vrypan<a href="https://twitter.com/i/web/status/1456536318805221383">→</a></small></p>
</blockquote>
<blockquote>
<p>The thing is that Web3 is decentralised and to a large extent, anonymous. Which means that your trademark will be really hard to claim.</p>
</blockquote>
<blockquote>
<p>What can you do against the ETH address that holds your companyname.eth? Sue them? Good luck. 3/ <small>// @vrypan<a href="https://twitter.com/i/web/status/1456536320239673352">→</a></small></p>
</blockquote>
<blockquote>
<p>Maybe ask ENS to take the domain away?</p>
</blockquote>
<blockquote>
<p>&quot;[...]  the root key holders have locked control of the .eth registrar contract, which means that even keyholders cannot affect the ownership of .eth domains.&quot; <a href="https://docs.ens.domains/frequently-asked-questions">docs.ens.domains/frequently-as...</a> 4/ <small>// @vrypan<a href="https://twitter.com/i/web/status/1456536322252939292">→</a></small></p>
</blockquote>
<blockquote>
<p>So, here's the obvious advise: make sure you claim your brand-related .eth domains <em>now</em>, before someone else does. Smart companies already did.</p>
</blockquote>
<blockquote>
<p>Or buy them if someone else claimed them already: Most probably it will cost you less now than in the future.  5/5 <small>// @vrypan<a href="https://twitter.com/i/web/status/1456536324203335680">→</a></small></p>
</blockquote>
<p>Of course, all this may make no sense to you. ENS, .eth, web3, wtf are they?</p>
<p>Remember: Domain names made no sense to you or the people that were in your shoes back in the 90s, when the web was starting. But a couple of decades later, we got to this: <a href="https://www.godaddy.com/garage/the-top-20-most-expensive-domain-names/">The top 25 most expensive domain names</a>.</p>
<p>So, find someone who knows about these things and pay them to handle it for you.</p>
<p>There's one thing you can be sure of: When all this is common sense, when your kids will have their own .eth address, then your brand/corporate .eth domain will cost <strong>much much more</strong> to buy back. And this time, it won't take decades to get there.</p>

]]></content:encoded>

    </item>
    
    <item>
      <title>Planet LRR
</title>
      <link>https://blog.vrypan.net/2021/11/03/planet-lrr/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/11/03/planet-lrr/</guid>
      <pubDate>Wed, 03 Nov 2021 16:54:41 +0200</pubDate>
      <description>Today I'd like to introduce you to my latest passion: Planet LRR.  // @vrypan→Planet LRR is actually a mathematical object, disguised as a painting. It's the result of a very very simple process called "cellular automata". This is where it got its name from: Left, Right, Right. /...</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2021/11/03/planet-lrr/media1.jpg">
        
	<blockquote>
<p>Today I'd like to introduce you to my latest passion: Planet LRR.  <small>// @vrypan<a href="https://twitter.com/i/web/status/1455875308775780358">→</a></small></p>
</blockquote>
<blockquote>
<p>Planet LRR is actually a mathematical object, disguised as a painting. It's the result of a very very simple process called &quot;cellular automata&quot;. This is where it got its name from: Left, Right, Right. <small>// @vrypan<a href="https://twitter.com/i/web/status/1455875311652982793">→</a></small></p>
</blockquote>
<blockquote>
<p>The actual process to generate Planet LRR took 2 million steps but you can see the genesis of Planet LRR (the first 30-something thousand steps) here: <a href="https://videos.files.wordpress.com/fFpFOWdg/planet-rll-genesis.mp4">videos.files.wordpress.com/fFp...</a> <small>// @vrypan<a href="https://twitter.com/i/web/status/1455875313477603330">→</a></small></p>
</blockquote>
<blockquote>
<p>The reason I find it fascinating is that all this complexity comes from such a simple rule. Which is actually an existential or cosmological question: is our universe with all its complexity the result (or governed by) some very simple rules/laws? <small>// @vrypan<a href="https://twitter.com/i/web/status/1455875315193032704">→</a></small></p>
</blockquote>
<blockquote>
<p>To my knowledge, there are no (or at least very few?) pieces of art that try to explore these questions. My <a href="http://turmites.art">turmites.art</a> project is an effort to make works (of art?) about these great questions. I hope you like it. :-) <small>// @vrypan<a href="https://twitter.com/i/web/status/1455875317122412551">→</a></small></p>
</blockquote>
<blockquote>
<p>You can find more about Planet LRR here: <a href="https://turmites.art/gallery/planet-lrr/">turmites.art/gallery/planet-lr...</a> <small>// @vrypan<a href="https://twitter.com/i/web/status/1455875319009849350">→</a></small></p>
</blockquote>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/11/03/planet-lrr/media1.jpg"
   type="image/jpeg"
   length="133637"/>

    </item>
    
    <item>
      <title>Stories from NFT land #1
</title>
      <link>https://blog.vrypan.net/2021/10/22/stories-from-nft-land-1/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/10/22/stories-from-nft-land-1/</guid>
      <pubDate>Fri, 22 Oct 2021 22:58:28 +0200</pubDate>
      <description>It was February 2021 when I bought my first NFT art. I was looking around, trying to find some NFTs that I liked but did not cost a ton of money, when I found Lisa Fogarty's "Nostalgia Series" on Mintable.</description>
      <content:encoded><![CDATA[
	
	<p>It was February 2021 when I bought my first NFT art. I was looking around, trying to find
some NFTs that I liked but did not cost a ton of money, when I found <a href="https://lisafogarty.se/">Lisa Fogarty's</a>
&quot;Nostalgia Series&quot; on Mintable.</p>
<p><figure><img src="https://blog.vrypan.net/2021/10/22/stories-from-nft-land-1/nostalgia-series.png" alt="nostalgia series watter color" /></figure></p>
<p>I'm no art expert, my only criteria is how much I like a piece, and these three spoke directly to my heart,
so I went ahead and bought them.</p>
<p>I looked up Lisa, found <a href="https://instagram.com/lisakfogarty">her Instagram account</a> and messaged her that
I liked her work, and suggested she should add a link from her Instagram profile to her Mintable profile
to prove that she is her on both sites.</p>
<p>Since then, she has joined twitter
(<a href="https://twitter.com/NftLisa">@NftLisa</a>, follow her!), she got deep into NFTs and her works are sold at
significantly higher prices than the early ones I bought 8 months ago.
(links: <a href="https://linktr.ee/LisaFogarty">https://linktr.ee/LisaFogarty</a>)</p>
<p><figure><img src="https://blog.vrypan.net/2021/10/22/stories-from-nft-land-1/lisa-fogarty-foundation.png" alt="Lisa Fogarty Foundation page" /></figure></p>
<p>Some days ago, I reached out to her again, to ask her something technical about these early NFTs, and
as we were chatting, she was very kind to offer to send me the original works as a gift
for the early support.</p>
<p>So, today I got these! <strong>Thank you so much Lisa!</strong></p>
<p><figure><img src="https://blog.vrypan.net/2021/10/22/stories-from-nft-land-1/nostalgia-series-rl.png" alt="photo" /></figure></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/10/22/stories-from-nft-land-1/lisa-fogarty-foundation.png"
   type="image/png"
   length="2948947"/>

   <enclosure url="https://blog.vrypan.net/2021/10/22/stories-from-nft-land-1/nostalgia-series-rl.png"
   type="image/png"
   length="993549"/>

   <enclosure url="https://blog.vrypan.net/2021/10/22/stories-from-nft-land-1/nostalgia-series.png"
   type="image/png"
   length="323379"/>

    </item>
    
    <item>
      <title>Some thoughts on stablecoins
</title>
      <link>https://blog.vrypan.net/2021/05/21/some-thoughts-on-stablecoins/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/05/21/some-thoughts-on-stablecoins/</guid>
      <pubDate>Fri, 21 May 2021 08:40:51 +0200</pubDate>
      <description>It turns out that stable coins are a fascinating subject. You may say, what's so fascinating about something that's stable by definition? Thread 👇 // @vrypan→For one, the various implementations. Take DAI, USDT, USDC, SUSD, TUSD, BUSD, GUSD and the rest. In theory, they are 1-1 t...</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2021/05/21/some-thoughts-on-stablecoins/media1.jpg">
        
	<blockquote>
<p>It turns out that stable coins are a fascinating subject. You may say, what's so fascinating about something that's stable by definition? Thread 👇 <small>// @vrypan<a href="https://twitter.com/i/web/status/1395613622160793602">→</a></small></p>
</blockquote>
<blockquote>
<p>For one, the various implementations. Take DAI, USDT, USDC, SUSD, TUSD, BUSD, GUSD and the rest. In theory, they are 1-1 to USD. But you get algorithmic vs centralised implementations, each one with its pros and cons. <small>// @vrypan<a href="https://twitter.com/i/web/status/1395613623427403780">→</a></small></p>
</blockquote>
<blockquote>
<p>And then, even for the centralised ones, you get to have different jurisdictions. You want a stable coin backed by a company regulated/audited in the US or not? How much do you trust the backer (if centralised) or the algorithm (if decentralised)? <small>// @vrypan<a href="https://twitter.com/i/web/status/1395613624698343426">→</a></small></p>
</blockquote>
<blockquote>
<p>Also, you have to consider liquidity and integration with marketplaces, exchanges and other services. Will you be able to convert your stablecoin to the desired price? Which one(s) are supported by the services you are interested in? <small>// @vrypan<a href="https://twitter.com/i/web/status/1395613625969217536">→</a></small></p>
</blockquote>
<blockquote>
<p>I think that nothing illustrates these differences than this. This is the current deposit/borrow APY on aave. In theory they are all the same, but the APYs differ based on demand. <a href="https://app.aave.com/markets">app.aave.com/markets</a>  <small>// @vrypan<a href="https://twitter.com/i/web/status/1395613631216295936">→</a></small></p>
</blockquote>
<blockquote>
<p><figure><img src="https://blog.vrypan.net/2021/05/21/some-thoughts-on-stablecoins/media1.jpg" alt="media" /></figure></p>
</blockquote>
<blockquote>
<p>You may think that stablecoins are second class citizens compared to the reference currency. But in some cases they are better. For example, there is no KYC. Remittances are a breeze and you don't have to convert to the local (usually much weaker currency). <small>// @vrypan<a href="https://twitter.com/i/web/status/1395613633036574721">→</a></small></p>
</blockquote>
<blockquote>
<p>Sidenote on remittances: This is a <em>huge</em> and critical economic activity for a very big percentage of the global population. For example, in Nigeria official remittances have exceeded oil revenues for multiple years. See <a href="https://www.pwc.com/ng/en/pdf/the-economic-power-of-nigerias-diaspora.pdf">www.pwc.com/ng/en/pdf/the-econ...</a> <small>// @vrypan<a href="https://twitter.com/i/web/status/1395613634311692291">→</a></small></p>
</blockquote>
<blockquote>
<p>I'm looking forward to stablecoins pegged to other currencies. I for one, would love to have one (or more) EUR stablecoins. Is someone working on this? <small>// @vrypan<a href="https://twitter.com/i/web/status/1395613635699957762">→</a></small></p>
</blockquote>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/05/21/some-thoughts-on-stablecoins/media1.jpg"
   type="image/jpeg"
   length="31620"/>

    </item>
    
    <item>
      <title>Leaving ChannelVAS
</title>
      <link>https://blog.vrypan.net/2021/04/27/leaving-channelvas/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/04/27/leaving-channelvas/</guid>
      <pubDate>Tue, 27 Apr 2021 03:22:22 +0200</pubDate>
      <description>I joined ChannelVAS when it was more like a startup. We were setting up our first projects, the team was small, we had to do a bit of everything.</description>
      <content:encoded><![CDATA[
	
	<p>I joined <a href="https://www.channelvas.com">ChannelVAS</a> when it was more like a
startup. We were setting up our first projects, the team was small, we
had to do a bit of everything.</p>
<p>I got to work in a truly multicultural company, with people from Europe, Africa,
Asia, Latin America, the Middle East. I got to travel to places I'd never been before:
Ghana, Zambia, Saudi Arabia, India, Brazil, Kambodia, Bangladesh, Nepal, Surinam,
Trinidad and Tobago, Curacao, Sri Lanka, Tanzania, Tunisia, Algeria, UAE (I'm probably
forgetting some), and worked with even more, like Benin and Uganda. I made some good
friends, and I worked with great people from around the world.</p>
<p>When I joined, the telco tech stack was a black box to me.
5.5 years later, after working with something like 20 mobile operators and their vendors
and the peculiarities of each country and region, you could call me an expert on some
parts of this stack, especially the IN and billing systems and various CDRs. But I also
got to understand how the various product offerings work in all these operators and
countries -and the similarities and differences.</p>
<p>So, I learned a lot, I traveled to places I'd never been before, I met and worked
with great people and made some good friends.</p>
<p>But ChannelVAS has grown up, the team is 10x bigger, processes have been put in place, things have become
more structured and well defined. And even if this sounds good for most people, it's
no longer the startup mess where I can give my best.</p>
<p>Cheers to all the people I worked with in these 5.5 years! We'll be in touch.</p>
<p><figure><img src="https://blog.vrypan.net/2021/04/27/leaving-channelvas/beers.png" alt="beers around the world" /></figure></p>
<hr />
<p>For job openings, checkout <a href="https://apply.workable.com/channelvas/">https://apply.workable.com/channelvas/</a>.</p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/04/27/leaving-channelvas/beers.png"
   type="image/png"
   length="4748935"/>

    </item>
    
    <item>
      <title>The rise of the activist trader (?)
</title>
      <link>https://blog.vrypan.net/2021/01/31/the-rise-of-the-activist-trader/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/01/31/the-rise-of-the-activist-trader/</guid>
      <pubDate>Sun, 31 Jan 2021 10:12:10 +0200</pubDate>
      <description>I think of trading activism in the same way as consumer activism.</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2021/01/31/the-rise-of-the-activist-trader/wallstreet.jpg">
        
	<p>I think of trading activism in the same way as consumer activism.</p>
<blockquote>
<p>Consumer activism is a process by which activists seek to influence the way
in which goods or services are produced or delivered. Kozinets and Handelman
attempt to define the broad concept as any social movement that uses society's
drive for consumption to the detriment of business interests.
<em>-- <a href="https://en.wikipedia.org/wiki/Consumer_activism">wikipedia: Consumer activism</a></em></p>
</blockquote>
<p>In the same way that an activist consumer may boycott a product that is cheaper,
better or even essential to them in order to apply pressure to a producer or a distributor
to change their policies (for example using sweatshops, destroying palm trees, or lobbying
for a specific politician), an activist trader may buy or sell stocks or other financial
instruments in order to make an ideological point by driving out of buisness
or causing significant financial damage to a company, an institution, or a fund
that is considered to have negative social impact.</p>
<p>For example, the some individual traders kept buying $GME stock at any price, in hope
of buncrupting hedge funds because they consider that these funds are bad for society.
They knew that they may loose their small investment, but they did not care, as the expected
profit for them was to bring down a hedge fund. [1]</p>
<p>Activist trading has become feasible by services like Robinhood that allow retail
traders invest small amounts and social networks like reddit that allows the coordination
and aggregation of these activists.</p>
<p><strong>Much like activist consumers, activist traders do not act in their best financial
interest.</strong></p>
<p>This may be a new reality that shakes the fundamental assumption behind financial markets
that all parties act in their best financial interest. Publicly traded companies, individual
and institutional investors, brokers, funds and other parties like banks that are part of the
financial system will have to take this into account.</p>
<hr />
<small>
[1] I'm not saying that *all* $GME traders acted with this motive in mind. I am refering to
the ones that bought and hold $GME "to bring the f---- hedge funds down".
</small>
<small>
[2] Image source: [Wikimedia commons](https://commons.wikimedia.org/wiki/File:Wall_Street_-_New_York_Stock_Exchange.jpg)
</small>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/01/31/the-rise-of-the-activist-trader/wallstreet.jpg"
   type="image/jpeg"
   length="457881"/>

    </item>
    
    <item>
      <title>The GameSpot backstory
</title>
      <link>https://blog.vrypan.net/2021/01/29/the-gamespot-backstory/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/01/29/the-gamespot-backstory/</guid>
      <pubDate>Fri, 29 Jan 2021 07:36:58 +0200</pubDate>
      <description>So many folks (esp. the media) are missing the complete backstory on $GME and how we got here.This has been simmering for over a year and the story behind it is great. I’ve been tracking this since September and devoured all of the details from the origin through today. // @endtw...</description>
      <content:encoded><![CDATA[
	
	<blockquote>
<p>So many folks (esp. the media) are missing the complete backstory on $GME and how we got here.</p>
</blockquote>
<blockquote>
<p>This has been simmering for over a year and the story behind it is great. I’ve been tracking this since September and devoured all of the details from the origin through today. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354547622133051393">→</a></small></p>
</blockquote>
<blockquote>
<p>So back in September 2019 (!) some guy named DeepFuckingValue posted this on r/wallstreetbets: <a href="https://www.reddit.com/r/wallstreetbets/comments/d1g7x0/hey_burry_thanks_a_lot_for_jacking_up_my_cost/">www.reddit.com/r/wallstreetbet...</a> <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554164714602497">→</a></small></p>
</blockquote>
<blockquote>
<p>It was just a post about his LEAPS (aka,
Long-Term Equity Anticipation Securities — tl;dr long-dated calls) on GME.</p>
</blockquote>
<blockquote>
<p>At the time, nobody understood his position at all. The top comment on that post?</p>
</blockquote>
<blockquote>
<p>&quot;Bid-ask spread on these are ridiculous, good luck getting rid of them&quot; lol. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554165842874369">→</a></small></p>
</blockquote>
<blockquote>
<p>For the next year, every month about once a month, he posted his &quot;YOLO GME&quot; position. Every month for a year he got made fun of.</p>
</blockquote>
<blockquote>
<p>I caught wind of this trade back in September 2020, a FULL YEAR after this guy was already holding. I also thought it was weird—the dying retailer? <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554166765637633">→</a></small></p>
</blockquote>
<blockquote>
<p>So I dug into the public quarterly reports of GameStop. Every quarter, public companies are required to release what's called a &quot;10-Q&quot; which is a quarterly report of their financials. You can find them here: <a href="https://news.gamestop.com/financial-information/sec-filings">news.gamestop.com/financial-in...</a> <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554167717728259">→</a></small></p>
</blockquote>
<blockquote>
<p>And what did I find? GameStop was actually in a great financial position; they weren't going broke! In fact, they had a lot of cash-in-hand, enough to pay off all their debts.</p>
</blockquote>
<blockquote>
<p>So why was it trading at like … $2-4/share? <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554168686628866">→</a></small></p>
</blockquote>
<blockquote>
<p>Next, I looked at their short interest. &quot;Shorting&quot;, for those who don’t know, is when you borrow a stock (from someone) and sell it on the market expecting the price to go down. You eventually buy back the stock at a lower price, return the borrowed shares, and pocket the diff. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554169592602624">→</a></small></p>
</blockquote>
<blockquote>
<p>So, the short interest was over 100% of total shares. In fact, it was 140%. Which makes no sense—how can you sell more shares than there are shares?</p>
</blockquote>
<blockquote>
<p>Keep in mind, not all shares are actively traded. In fact, over 75% of $GME is locked up in passive funds and GME board &amp; C-suite. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554170477604864">→</a></small></p>
</blockquote>
<blockquote>
<p>So really, short interest was like 300-500% of <em>float</em> (float is how many shares are actively traded, basically).</p>
</blockquote>
<blockquote>
<p>Which is insane. Basically, the shorts (which are hedge funds like Melvin) were expecting $GME to go bankrupt and they'd never have to cover (return their shares). <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554171354206214">→</a></small></p>
</blockquote>
<blockquote>
<p>u/DeepFuckingValue had figured this out long before anyone. Even Michael Burry (yes, The Big Short guy) who bought in AFTER u/DeepFuckingValue.</p>
</blockquote>
<blockquote>
<p>And he bought in, with conviction in his trade, ignoring the haters. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554172264374273">→</a></small></p>
</blockquote>
<blockquote>
<p>A year later and people start to take notice on reddit. The price has started to inch up, from $4 to $8 to $12 over September and October.</p>
</blockquote>
<blockquote>
<p>And more people on r/WallStreetBets started buying in.</p>
</blockquote>
<blockquote>
<p>And then more people.</p>
</blockquote>
<blockquote>
<p>And then more people. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554173610749952">→</a></small></p>
</blockquote>
<blockquote>
<p>Which, of course, makes the price go up. So the price keeps going up and more people keep taking notice and so on.</p>
</blockquote>
<blockquote>
<p>Eventually, the shorts are supposed to cover. But how? They need to purchase more shares than there are in the company. Well, that means purchasing at any price. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554174512508934">→</a></small></p>
</blockquote>
<blockquote>
<p>So they start to cover, which means buying hundreds of thousands of shares, which pushes the price up more.</p>
</blockquote>
<blockquote>
<p>And then last Friday, thanks to momentum and growing interest from retail traders, we had what is called a &quot;gamma squeeze.&quot; Which isn’t the short squeeze! <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554175435247616">→</a></small></p>
</blockquote>
<blockquote>
<p>So, quick aside to explain this: Market Makers (the big banks and funds, like GS, Citadel, etc) write options. When they do, they have to remain &quot;market neutral&quot; by law. So there are what's called &quot;the greeks&quot; on options: theta, gamma, etc. Look 'em up if you'r curious.</p>
</blockquote>
<blockquote>
<p>Anyway… <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554176395767811">→</a></small></p>
</blockquote>
<blockquote>
<p>&quot;Gamma&quot; is a number between 0-1 that changes on a call as the price of a stock gets closer to the call price. Lets say you buy a $300 call and the stock is $290. Gamma would be ~0.98.
Meaning for every call purchased (which rep. 100 shares), MMs buy 98 shares to be neutral. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554177389793280">→</a></small></p>
</blockquote>
<blockquote>
<p>As gamma changes, they have to buy more or sell more shares.</p>
</blockquote>
<blockquote>
<p>On Friday, the price was over every available call strike, which meant that MMs had to buy millions of shares—if a call is &quot;in the money&quot; (stock price &gt; call price) they have to deliver the shares. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554179122036736">→</a></small></p>
</blockquote>
<blockquote>
<p>So on Friday and Monday, the price ran up very quickly as MMs hustled to cover the calls and settle them.</p>
</blockquote>
<blockquote>
<p>Then the news took notice and everything went wild. More people piled in, larger firms are piling in on the buy side, Elon, Chamath… and the price exploded. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554179994480641">→</a></small></p>
</blockquote>
<blockquote>
<p>So that’s how we're where we are now. Supposedly, a number of shorts have covered. That being said, last I checked, the short interest was still ~138% so either:</p>
</blockquote>
<blockquote>
<p>(a) the shorts haven’t covered or,
(b) more people are shorting to replace the shorts that covered <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554181785444355">→</a></small></p>
</blockquote>
<blockquote>
<p>When you short, you pay a borrow fee which can change from day to day. Right now that fee on $GME is between 20-80%. That’s like… credit card interest rates! To borrow a stock!</p>
</blockquote>
<blockquote>
<p>So the longer you’re holding your short position, the more it costs. <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554182766895108">→</a></small></p>
</blockquote>
<blockquote>
<p>Eventually it either costs too much and you have to close your position for a loss, or you go bankrupt. Melvin almost went bankrupt (they got a $2.75B bailout from 2 other hedge funds).</p>
</blockquote>
<blockquote>
<p>This is where we are now. Where does it go from here? I’m not sure! <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554183735783431">→</a></small></p>
</blockquote>
<blockquote>
<p>Sorry this was so long, I find it really interesting and have been very invested in the story for months :) <small>// @endtwist<a href="https://twitter.com/i/web/status/1354554184603938822">→</a></small></p>
</blockquote>

]]></content:encoded>

    </item>
    
    <item>
      <title>How can we make ENS in IPFS more distributed?
</title>
      <link>https://blog.vrypan.net/2021/01/22/how-can-we-make-ens-in-ipfs-more-distributed/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/01/22/how-can-we-make-ens-in-ipfs-more-distributed/</guid>
      <pubDate>Fri, 22 Jan 2021 14:33:23 +0200</pubDate>
      <description>I'm a bit sceptical about @IPFS and @ensdomains. Based on my limited understanding, in practice, IPFS resolves ENS content using DNS. This is OK as an interim solution, but if this is the case, the whole flow is again using a centralised service. 1/ // @vrypan→</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2021/01/22/how-can-we-make-ens-in-ipfs-more-distributed/ipfs_and_ens.png">
        
	<p>I'm a bit sceptical about @IPFS and @ensdomains. Based on my limited understanding, in practice, IPFS resolves ENS content using DNS. This is OK as an interim solution, but if this is the case, the whole flow is again using a centralised service. 1/ <small>// @vrypan<a href="https://twitter.com/i/web/status/1352291769745088513">→</a></small></p>
<p>So, if someone wanted to resolve .eth domains without relying on an external EthDNS, would you eventually have to use a full ETH node? This sounds like an overkill. 2/ <small>// @vrypan<a href="https://twitter.com/i/web/status/1352291771175329792">→</a></small></p>
<p>Of course there are a lot of people that could deploy a full ETH node + EthDNS, so a user could choose to host their own, use a popular one, or even use on set up by their local hackerspace. But in every case you have to trust this third party blindly. 3/ <small>// @vrypan<a href="https://twitter.com/i/web/status/1352291772538499074">→</a></small></p>
<p>I'm trying to understand (with my limited technical knowledge on this) if ENS contracts should be implemented on a smaller side chain. Or have a smaller, lighter, more robust side chain that can answer ENS queries. 4/ <small>// @vrypan<a href="https://twitter.com/i/web/status/1352291773872275459">→</a></small></p>
<p>Please feel free to jump in if you are more knowledgeable on this field than I am. I would appreciate some expert opinion. Is there a roadmap towards something better? 5/5 <small>// @vrypan<a href="https://twitter.com/i/web/status/1352291775386423298">→</a></small></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/01/22/how-can-we-make-ens-in-ipfs-more-distributed/ipfs_and_ens.png"
   type="image/png"
   length="830823"/>

    </item>
    
    <item>
      <title>Crypto, blockchains and the next computing paradigm
</title>
      <link>https://blog.vrypan.net/2021/01/12/crypto-blockchains-and-the-next-computing-paradigm/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/01/12/crypto-blockchains-and-the-next-computing-paradigm/</guid>
      <pubDate>Tue, 12 Jan 2021 09:28:58 +0200</pubDate>
      <description>This is a post I've been trying to write for years but I was unable to find the right way to frame until I heard Chris Dixon on the latest episode of Bankless.</description>
      <content:encoded><![CDATA[
	
	<p>This is a post I've been trying to write for years but I was unable to find the right
way to frame until I heard Chris Dixon
<a href="http://podcast.banklesshq.com/47-the-fourth-crypto-cycle-chris-dixon-a16z">on the latest episode of Bankless</a>.</p>
<p>For me it started 8 years ago, when I founded a company called &quot;Longaccess&quot;. Our
mission was &quot;to safeguard and preserve personal digital archives for the future&quot;.
We offered strongly encrypted, long term storage where someone could put their data (for
example family photos) pay once and have it preserved for at least 30 years. The data
owner would get a &quot;Certificate&quot; (a short document including the archive ID and encryption keys)
that could be used (by anyone that had it) to recover the data.
(See <a href="https://blog.vrypan.net/2014/05/07/longaccess-video-intro/">Using Longaccess</a>
if you are currious.)</p>
<p>The business model was solid, and looking back into all the assumptions we did about
storage costs and viability, they hold better than we originally thought.
But we failed. We failed for various reasons, but if you ask me now, the main reason was
that we could not answer the core question: &quot;how do I know you will be around in 30 years&quot;.</p>
<p>At the time, I had some complex solutions in mind that involved the creation of a trust fund that would
use the money paid up front to ensure that there will always be a financial incentive
for someone to preserve the data, but this was a complex and costly solution, that required
scale and resources out of reach of our small tech startup.</p>
<p>Longaccess closed in 2015 and, for not totally unrelated reasons, this was also the time I
started paying attention to cryptocurrencies and blockchain.</p>
<p>Shortly after, the ICO boom started and when I got familiar with the idea of on-chain
contracts, I knew that this would be the tool we should have used for Longaccess if only
it was available to us at the time.</p>
<hr />
<p>I could not exactly describe how this would have worked, until I heard Chris Dixon describe
what the blockchain paradigm brings to computing.</p>
<blockquote>
<p><strong>Blockchains are computers that can make commitments.</strong>
-- <a href="https://cdixon.org/2020/01/26/computers-that-can-make-commitments">Chris Dixon</a></p>
</blockquote>
<p>Yes! This is it! We were trying to sell a commitment, but we did not have a computer that could make
commitments.</p>
<hr />
<p>I've been paying attention to things like Storj, Siacoin, Filecoin since their
early steps because I have a personal interest and passion about this area. I now know what
they are missing. They are trying to sell &quot;decentralized storage&quot; which is something that adds no
value to most of cloud storage buyers. They try to compete with centralized storage giants
in efficiency or price instead of offering something that these companies cannot offer
(or would be less capable of offering): long term data storage <strong>commitments</strong>.</p>
<hr />
<p>And this is probably a great way to identify the places where blockchain will be the catalyst
for the next big thing.</p>
<p>Look at successful services and search for explicit commitments like &quot;we will never...&quot; or
&quot;we will always...&quot;. &quot;We will never sell your data&quot;, &quot;our API will always be free&quot;,
&quot;we are committed to...&quot;. Or implicit ones that come up in debates, like &quot;Google/Amazon/Apple/xyz
would never do this because...&quot;</p>
<p>Look around you. What are the things, based on social or legal contracts, that don't work
well? What are the activities that require a lawyer or a contract? Our social, business
and even political life is based on commitments.</p>
<p>Well, <strong>we now have computers that can make commitments.</strong></p>

]]></content:encoded>

    </item>
    
    <item>
      <title>My first take on NFC tags
</title>
      <link>https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/</link>
      <guid isPermaLink="true">https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/</guid>
      <pubDate>Fri, 01 Jan 2021 20:37:20 +0200</pubDate>
      <description>NFC tags are small passive circuits that draw power from the device that reads them, using magnetic induction and respond with a small piece of information (usually a few bytes long). Which means that they don't need a battery. They function much like RFID, but in the case of NFC...</description>
      <content:encoded><![CDATA[
	
        <img  src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/photo.png">
        
	<p>NFC tags are small passive circuits that draw power from the device that reads them,
using magnetic induction and respond with a small piece of information (usually a few
bytes long). Which means that they don't need a battery. They function much like RFID,
but in the case of NFC the reader has to be really close to the tag, in most of the
cases, actually touching it.</p>
<p>They are cheap, small and you can purchase them in the form of small stickers, the size
of a small coin. And your mobile phone is probably able to read them (for example, any
iPhone since iPhone 7 with iOS 11 or later).</p>
<hr />
<p>I knew little about NFC tags, so I got a <a href="https://amzn.to/2KTJt1Z">10-pack for €6.95 from Amazon</a>.</p>
<p>It is important to understand that the tag itself does not implement any logic. If
you read about &quot;programming NFC tags&quot;, this is not about implementing some logic on the
tag, but writting some piece of information on it. An NFC tag is as smart as a piece of
paper with a QR code on it.</p>
<p>The tags I purchased can hold up to 888 bytes. If you don't write any additional info on them,
when read they will just return an ID.</p>
<hr />
<p>In order to use them on iPhone, go to the Shortcuts app, create a new Automation and select NFC.</p>
<p>At the end of this post are the steps I followed to create an automation that will turn on/off the (Philips Hue)
lamp on my desk.</p>
<p>I'm not sure if it's the tags, my iPhone or the NFC spec itself, but in some occasions the phone
may not read the tag and you have to try again. I found it useful to add some indication (vibration
in this case) as the first step of the automation, in order to have a clear sign if the automation
was triggered or not.</p>
<hr />
<p>Final notes.</p>
<p>You can read/write the info on a tag using apps like <a href="https://apps.apple.com/us/app/nfc-taginfo-by-nxp/id1246143596">NFC TagInfo by NXP</a>
and <a href="https://apps.apple.com/us/app/nfc-tagwriter-by-nxp/id1246143221">NFC TagWriter by NXP</a>. I tried it, it
works, but I did not have any use for it at the moment.</p>
<p>These are my first steps on NFC tags. If you think something sould be corrected on this
article, please let me know! (<a href="https://twitter.com/vrypan">@vrypan</a>)</p>
<hr />
<p><figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step1.png" alt="step1" /></figure> <figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step2.png" alt="step2" /></figure> <figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step3.png" alt="step3" /></figure> <figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step4.png" alt="step4" /></figure> <figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step5.png" alt="step5" /></figure>
<figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step6.png" alt="step6" /></figure> <figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step7.png" alt="step7" /></figure> <figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step8.png" alt="step8" /></figure> <figure><img src="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step9.png" alt="step9" /></figure></p>

]]></content:encoded>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/photo.png"
   type="image/png"
   length="2668232"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step1.png"
   type="image/png"
   length="235865"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step2.png"
   type="image/png"
   length="161317"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step3.png"
   type="image/png"
   length="255866"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step4.png"
   type="image/png"
   length="86126"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step5.png"
   type="image/png"
   length="127862"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step6.png"
   type="image/png"
   length="275139"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step7.png"
   type="image/png"
   length="155587"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step8.png"
   type="image/png"
   length="288159"/>

   <enclosure url="https://blog.vrypan.net/2021/01/01/my-first-take-on-nfc-tags/step9.png"
   type="image/png"
   length="174596"/>

    </item>
    
  </channel>
</rss>
