<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CryptoPlay Guide</title>
    <description>The latest articles on DEV Community by CryptoPlay Guide (@cryptoplayguide).</description>
    <link>https://dev.to/cryptoplayguide</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4212439%2F6777553c-47e2-402d-8037-b503a129a9dc.png</url>
      <title>DEV Community: CryptoPlay Guide</title>
      <link>https://dev.to/cryptoplayguide</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cryptoplayguide"/>
    <language>en</language>
    <item>
      <title>Inside a 61-Line JavaScript Provably Fair Verifier</title>
      <dc:creator>CryptoPlay Guide</dc:creator>
      <pubDate>Thu, 29 Oct 2026 13:19:29 +0000</pubDate>
      <link>https://dev.to/cryptoplayguide/inside-a-61-line-javascript-provably-fair-verifier-1c4h</link>
      <guid>https://dev.to/cryptoplayguide/inside-a-61-line-javascript-provably-fair-verifier-1c4h</guid>
      <description>&lt;p&gt;A verifier is easier to inspect when the cryptographic operations, input rules, and game mappings fit within a small module. Version 1.1.0 of &lt;a href="https://github.com/cryptoplayguide/provably-fair-verifier" rel="noopener noreferrer"&gt;provably-fair-verifier&lt;/a&gt; takes that approach: one 61-line &lt;code&gt;src/index.js&lt;/code&gt;, no dependencies, and tests built on Node's own tools.&lt;/p&gt;

&lt;p&gt;The useful architectural question is how those pieces connect. A commitment check answers whether a revealed seed hashes to an expected commitment. A deterministic mapping answers which result follows from that seed and the other inputs. The module returns both, leaving callers responsible for interpreting them correctly.&lt;/p&gt;

&lt;p&gt;The repository's working parts are small enough to list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/index.js          exported ESM implementation
test/index.test.mjs   vectors, reference generator, validation tests
package.json         entry point, test command, Node requirement
README.md            API usage and formula boundaries
CHANGELOG.md         version history
LICENSE              MIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt; declares Node &lt;code&gt;&amp;gt;=18&lt;/code&gt;, ESM through &lt;code&gt;"type": "module"&lt;/code&gt;, and &lt;code&gt;src/index.js&lt;/code&gt; as both the main entry and export. There are no runtime or development dependencies. The MIT license permits reuse subject to its notice requirements. Version 1.1.0 adds Mines and Plinko plus the &lt;code&gt;stakeFloats&lt;/code&gt;, &lt;code&gt;minesFromFloats&lt;/code&gt;, and &lt;code&gt;plinkoFromFloats&lt;/code&gt; exports.&lt;/p&gt;

&lt;p&gt;To clone and run the tests with Node 18 or newer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/cryptoplayguide/provably-fair-verifier.git
&lt;span class="nb"&gt;cd &lt;/span&gt;provably-fair-verifier
npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No dependency installation is needed for this checkout. The test script runs &lt;code&gt;node --test test/&lt;/code&gt;. For use as a dependency in another project, the documented installation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;github:cryptoplayguide/provably-fair-verifier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The package's import name is &lt;code&gt;@cryptoplayguide/provably-fair-verifier&lt;/code&gt;. The README says it is not yet published to the npm registry; GitHub is the installation source.&lt;/p&gt;

&lt;p&gt;For a local verification, save the following as &lt;code&gt;verify.mjs&lt;/code&gt; in the cloned repository and run &lt;code&gt;node verify.mjs&lt;/code&gt;. The input declaration is copied verbatim from &lt;code&gt;test/index.test.mjs&lt;/code&gt;; the calls exercise the same vectors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;webcrypto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fairResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;e3f1b5c2a9d84f6e7b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f60718293a4b5c6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1c7bc4411405303e0f84ab57dea9691c6376ee6891b289a65edac408519e6009&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example-client-seed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example-public-salt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fairResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;webcrypto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fairResult&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;limbo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;webcrypto&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fairResult&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mines&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;webcrypto&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fairResult&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plinko&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;webcrypto&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected values are &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;42.62&lt;/code&gt; for Dice, &lt;code&gt;2.32&lt;/code&gt; for Limbo, mine positions &lt;code&gt;[10, 14, 7]&lt;/code&gt;, and Plinko &lt;code&gt;{ path: [0,1,0,0,1,0,0,0], slot: 2 }&lt;/code&gt;. These are existing assertions, rather than newly generated fixtures. The tests also contain a separate Crash vector yielding &lt;code&gt;1.44&lt;/code&gt;, a 24-mine vector, and a 16-row Plinko vector.&lt;/p&gt;

&lt;p&gt;Web Crypto is the boundary between platform services and deterministic mapping. Both asynchronous entry points accept an injectable provider, defaulting to &lt;code&gt;globalThis.crypto&lt;/code&gt;. This signature is verbatim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stakeFloats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;webCrypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing Node's &lt;code&gt;webcrypto&lt;/code&gt; explicitly, as above, avoids depending on a global being available. Browser callers can use the default where Web Crypto is available. The implementation delegates SHA-256 and HMAC-SHA256 to &lt;code&gt;subtle.digest&lt;/code&gt;, &lt;code&gt;subtle.importKey&lt;/code&gt;, and &lt;code&gt;subtle.sign&lt;/code&gt;; it does not implement cryptographic primitives itself.&lt;/p&gt;

&lt;p&gt;The return objects also support inspection beyond a final number. Dice, Limbo, and Crash expose &lt;code&gt;commitment&lt;/code&gt;, &lt;code&gt;matches&lt;/code&gt;, &lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;digest&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, and &lt;code&gt;result&lt;/code&gt;. Mines and Plinko expose &lt;code&gt;commitment&lt;/code&gt;, &lt;code&gt;matches&lt;/code&gt;, &lt;code&gt;floats&lt;/code&gt;, and &lt;code&gt;result&lt;/code&gt;. An integration can therefore inspect the intermediate representation when diagnosing a disagreement, rather than receiving only an opaque success flag. Consumers should account for these different shapes when displaying results.&lt;/p&gt;

&lt;p&gt;There is no network request or seed generation in the module. The caller supplies the inputs; the module recomputes their consequences. This keeps browser presentation, storage, and data collection outside the cryptographic code. It also makes the local example reproducible without querying an external service.&lt;/p&gt;

&lt;p&gt;Input validation runs before computation in &lt;code&gt;fairResult&lt;/code&gt;. It accepts only the five supported game identifiers, requires a 64-character hexadecimal commitment, and additionally requires a hexadecimal server value for Crash. Non-Crash nonces must contain digits and convert to safe integers. Mines accepts counts from 1 through 24; Plinko accepts 8 through 16 rows.&lt;/p&gt;

&lt;p&gt;This is validation without input repair: malformed hashes are rejected rather than padded, and invalid counts are rejected rather than clamped. There are explicit conversions, including &lt;code&gt;Number(nonce)&lt;/code&gt; when constructing messages and lowercasing the validated hash for comparison. That distinction matters when integrating the API. The validator is not a complete application schema: it does not separately validate every client or salt field, and the exported mapping helpers assume suitable float inputs.&lt;/p&gt;

&lt;p&gt;Dice and Limbo use Stake's published formula: HMAC with the server seed as key and &lt;code&gt;clientSeed:nonce:0&lt;/code&gt; as message. Four bytes become a fractional value by summing successive base-256 fractions. Dice maps that value through &lt;code&gt;floor(value * 10001) / 100&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Limbo's reciprocal calculation needs an explicit boundary rule. A zero float would otherwise produce &lt;code&gt;Infinity&lt;/code&gt;. The module throws &lt;code&gt;RangeError&lt;/code&gt; at zero and also rejects nonnumeric, nonfinite, and out-of-range values. The tests check the dedicated zero message and assert that &lt;code&gt;limboMultiplier(0.5)&lt;/code&gt; returns &lt;code&gt;1.98&lt;/code&gt;. This fix predates the new games: the changelog records it under v1.0.1.&lt;/p&gt;

&lt;p&gt;Mines and Plinko share the multi-round byte generator. Each HMAC message includes a round counter; each 32-byte digest supplies eight floats, consuming four bytes apiece. More rounds are generated until the requested count is reached. Tests compare this output with a reference implementation using Node's &lt;code&gt;createHmac&lt;/code&gt;, providing a separate implementation path for the byte stream.&lt;/p&gt;

&lt;p&gt;The suite checks failure behavior alongside known outputs. It rejects malformed Crash seeds, a negative nonce, and an unsupported game. Another assertion supplies an all-zero commitment and expects &lt;code&gt;matches&lt;/code&gt; to be false, distinguishing a well-formed mismatch from invalid input. Helper tests exercise tile selection and left/right mapping directly. These checks document the current contract, while the reference generator comparison specifically checks agreement between the two HMAC implementations; it does not independently certify every possible operator's rules.&lt;/p&gt;

&lt;p&gt;Mines uses Fisher-Yates selection over 25 tiles. The implementation removes each selected tile from the remaining list, preventing duplicate positions. Here is the complete helper, verbatim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;minesFromFloats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;mines&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tiles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floats&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fairResult&lt;/code&gt; requests 24 floats for Mines regardless of the mine count; the helper consumes the requested number. Tile indices run from 0 through 24, left to right and top to bottom. Keeping float generation separate from selection makes the mapping independently inspectable.&lt;/p&gt;

&lt;p&gt;Plinko's helper is equally direct, also quoted verbatim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;plinkoFromFloats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;floats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each row consumes one float: 0 means left, 1 means right. Summing right turns gives the landing slot. There are deliberately no multipliers: payout tables depend on risk settings and the operator. A path verifier cannot infer those tables from the random stream alone.&lt;/p&gt;

&lt;p&gt;Crash follows bustabit's published formula and has a different byte contract. The server value is decoded from hexadecimal before hashing for the commitment and before use as the HMAC message. The salt is the HMAC key. The first 13 hexadecimal digest characters provide 52 bits; the result uses &lt;code&gt;Math.max(1, Math.floor(99 / (1 - value)) / 100)&lt;/code&gt;. Treating the seed as UTF-8 text instead would change the calculation.&lt;/p&gt;

&lt;p&gt;Finally, &lt;code&gt;matches&lt;/code&gt; confirms only that the computed commitment equals the supplied hash. It does not compare the computed result with a separately reported outcome, establish that the commitment was displayed before play, or prove payout reliability. A caller must preserve the original commitment, select the correct documented formula, and compare the returned result independently. Other implementations can use different rules.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://cryptoplay.guide/tools/provably-fair-verifier/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=verifier-repo" rel="noopener noreferrer"&gt;browser verifier&lt;/a&gt; provides another interface for checking results. The repository exposes the underlying operations for local inspection: platform cryptography, explicit validation, deterministic mappings, and reproducible vectors.&lt;/p&gt;

&lt;p&gt;18+ only. Educational use. Gambling carries financial risk; verification does not remove the house edge. Gamble responsibly.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>cryptography</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A Country Checker Is a Terms Lookup: Understanding the Data Boundary</title>
      <dc:creator>CryptoPlay Guide</dc:creator>
      <pubDate>Thu, 29 Oct 2026 05:28:58 +0000</pubDate>
      <link>https://dev.to/cryptoplayguide/a-country-checker-is-a-terms-lookup-understanding-the-data-boundary-fke</link>
      <guid>https://dev.to/cryptoplayguide/a-country-checker-is-a-terms-lookup-understanding-the-data-boundary-fke</guid>
      <description>&lt;p&gt;A country selector can make a complicated policy question look deceptively simple. Choose a country, receive a result, move on. But the meaning of that result depends on the dataset behind it and the claim the interface actually makes.&lt;/p&gt;

&lt;p&gt;CryptoPlay Guide's crypto casino country checker answers a deliberately limited question: does the selected country appear on a restricted-country list maintained for a particular operator? Understanding that boundary matters more than treating the output as a general availability verdict.&lt;/p&gt;

&lt;p&gt;For developers and data-minded readers, the useful lessons are about sourcing, labels, dates and exceptions. The tool provides a practical example of why a lookup result needs its context attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the exact output labels
&lt;/h2&gt;

&lt;p&gt;The checker reads the restricted-country lists kept for the casinos it covers. Its result is either “On this casino's restricted list” or “Not on this casino's restricted list.”&lt;/p&gt;

&lt;p&gt;Those labels describe membership in a list. A missing entry does not establish that gambling is legal in that country. It also does not guarantee that the operator will open an account or allow that account to remain open.&lt;/p&gt;

&lt;p&gt;The distinction is central to reading the interface correctly. “Not on the list” describes the available restriction data. Local gambling law, the operator's current terms and identity checks still apply independently.&lt;/p&gt;

&lt;p&gt;CryptoPlay Guide does not present the checker as a substitute for those checks. It tells readers to review the casino's own terms before signing up, even after using the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trace the data back to its stated sources
&lt;/h2&gt;

&lt;p&gt;CryptoPlay Guide maintains lists for Mint, Thrill and Castle. Those lists are based on the operators' published terms and partner documents. The checker also includes lists read from official terms pages for other popular crypto casinos.&lt;/p&gt;

&lt;p&gt;For those additional operators, the interface shows a Terms link and the date the information was last checked. Those details help a reader understand where a result came from and when the restriction information was reviewed.&lt;/p&gt;

&lt;p&gt;The maintained Thrill list includes a few sanctioned countries as a precaution. That means the stated sourcing includes an editorial precaution, alongside the published documents. A careful explanation of the dataset should retain that qualification rather than imply every maintained entry is simply copied from a single terms page.&lt;/p&gt;

&lt;p&gt;The same maintained lists also determine where CryptoPlay Guide switches off its own casino links. That is another use of the restriction data; it does not expand what a country result proves about legality or account approval.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat the check date as part of the result
&lt;/h2&gt;

&lt;p&gt;CryptoPlay Guide's checker displays “Last checked 2026-10-29” and warns that terms change. That date belongs to the information reviewed at that time. It is not a promise that an operator's policy will remain unchanged afterward.&lt;/p&gt;

&lt;p&gt;A reader needs both the result and the date. Removing the date makes it easier to mistake an earlier review for a current policy guarantee. Removing the terms reference makes it harder to verify the underlying restriction directly.&lt;/p&gt;

&lt;p&gt;The sensible reading sequence is therefore straightforward: inspect the result, note when the data was checked, then read the operator's current terms. The checker narrows the lookup work, while the terms remain necessary before any signup decision.&lt;/p&gt;

&lt;p&gt;This also explains why different results across operators are not automatically a contradiction. Each operator sets its own restricted-country list. One can restrict a country that another does not list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Country-level data has regional limits
&lt;/h2&gt;

&lt;p&gt;A country selector cannot express every regional exception in a single broad label. CryptoPlay Guide explicitly says coverage of regions within a country is partial.&lt;/p&gt;

&lt;p&gt;For example, Ontario is restricted for Mint and Thrill. Castle's restrictions include Crimea, Sevastopol, Donetsk and Luhansk, while Thrill restricts all of Ukraine.&lt;/p&gt;

&lt;p&gt;These examples illustrate why a country result needs a regional check alongside it. They are restrictions to review, not suggestions about where someone should play. CryptoPlay Guide tells readers to consult the relevant terms because the country result cannot show every regional rule.&lt;/p&gt;

&lt;p&gt;For anyone interpreting the data, preserving that limitation is essential. A broad country label should not erase the narrower conditions described in the underlying documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understand what the embed carries
&lt;/h2&gt;

&lt;p&gt;The checker is free to embed on another site and displays a “Powered by CryptoPlay Guide” credit link. Its embed address is &lt;a href="https://cryptoplay.guide/embed/country-checker/" rel="noopener noreferrer"&gt;https://cryptoplay.guide/embed/country-checker/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Embedding the widget does not change the question it answers. The result still concerns the maintained restriction lists, with the same need to check current terms, regional conditions and local law. A host page should describe it with that scope in mind.&lt;/p&gt;

&lt;p&gt;The main tool is available at &lt;a href="https://cryptoplay.guide/tools/crypto-casino-by-country/" rel="noopener noreferrer"&gt;https://cryptoplay.guide/tools/crypto-casino-by-country/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the result as evidence with limits
&lt;/h2&gt;

&lt;p&gt;The value of this checker lies in making restriction information easier to inspect, not in resolving every condition of participation. Its sources, check dates and regional caveats explain how to use its output responsibly.&lt;/p&gt;

&lt;p&gt;Before acting on a result, confirm the operator's current rules and the law where you live. The most useful answer from a data tool is one whose meaning stays clear after the lookup is complete.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://cryptoplay.guide/tools/crypto-casino-by-country/" rel="noopener noreferrer"&gt;https://cryptoplay.guide/tools/crypto-casino-by-country/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CryptoPlay Guide, the site this was originally published on, earns affiliate commissions from some casinos it covers. This post contains no affiliate links.&lt;/p&gt;

&lt;p&gt;18+ (or the higher legal age where you live). Gambling involves risk of loss; only play where legal, set deposit, loss and time limits, and seek help if gambling causes harm, for example from BeGambleAware.org.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>data</category>
      <category>transparency</category>
      <category>explainlikeimfive</category>
    </item>
    <item>
      <title>Reproduce a Provably Fair Result with HMAC-SHA256</title>
      <dc:creator>CryptoPlay Guide</dc:creator>
      <pubDate>Thu, 29 Oct 2026 05:28:06 +0000</pubDate>
      <link>https://dev.to/cryptoplayguide/reproduce-a-provably-fair-result-with-hmac-sha256-2356</link>
      <guid>https://dev.to/cryptoplayguide/reproduce-a-provably-fair-result-with-hmac-sha256-2356</guid>
      <description>&lt;p&gt;A “provably fair” label becomes useful when you can turn it into a reproducible check. For a developer, the interesting part is the path from a previously published commitment to an exact game result: hash the revealed input, rebuild the HMAC message, then apply the documented byte conversion.&lt;/p&gt;

&lt;p&gt;That path has several distinct failure points. Getting the cryptography right is necessary, but the result also depends on the nonce, message format and game formula. A matching digest with the wrong result mapping is an incomplete verification.&lt;/p&gt;

&lt;p&gt;The walkthrough below uses example seeds created for the original CryptoPlay Guide article. They are not records of a casino bet. The Dice and Limbo mappings follow the published formulas described in that article; another operator may use different rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat the commitment as your starting input
&lt;/h2&gt;

&lt;p&gt;Before betting, the operator shows a SHA-256 hash of a secret server seed. Save that hash. The client seed is visible, as is the nonce that identifies the bet within the seed pair. The operator reveals the old server seed after you rotate seeds.&lt;/p&gt;

&lt;p&gt;You therefore need the revealed server seed, the hash saved before play, the client seed and the exact nonce. You cannot complete this check while the active server seed remains secret.&lt;/p&gt;

&lt;p&gt;Here is the example server seed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cryptoplayguide-example-server-seed-2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pre-bet commitment for this example is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ea1e9ffa82b568d4ecb93488031e79bfe0cba227dbbe2b134c73e66079e78e91
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this command to check it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; %s &lt;span class="s2"&gt;"cryptoplayguide-example-server-seed-2026"&lt;/span&gt; | &lt;span class="nb"&gt;sha256sum&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare the entire output hash with the saved commitment. A mismatch means the revealed seed does not match that commitment; the later result calculation cannot repair that failed check.&lt;/p&gt;

&lt;p&gt;Preserve the input exactly. A trailing newline or space changes the hash, which is why the example uses &lt;code&gt;printf %s&lt;/code&gt; rather than &lt;code&gt;echo&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rebuild the HMAC message explicitly
&lt;/h2&gt;

&lt;p&gt;For this Dice and Limbo example, the server seed is the HMAC-SHA256 key. The message has the format &lt;code&gt;client_seed:nonce:round&lt;/code&gt;, with round set to &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using client seed &lt;code&gt;my-client-seed&lt;/code&gt; and nonce &lt;code&gt;1&lt;/code&gt;, the command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; %s &lt;span class="s2"&gt;"my-client-seed:1:0"&lt;/span&gt; | openssl dgst &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-hmac&lt;/span&gt; &lt;span class="s2"&gt;"cryptoplayguide-example-server-seed-2026"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It produces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d6e37d4cd754f8752a46ef3f8c7bcd60434a1abe8a9ab09594833e9b21883b86
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The placement of each input matters. Do not swap the key and message or silently change the message separators. Likewise, copy the nonce from the bet record: some operators start counting at &lt;code&gt;0&lt;/code&gt;, while others start at &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this stage you have reproduced the digest. You still need to reproduce the game result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow the byte mapping, then the payout mapping
&lt;/h2&gt;

&lt;p&gt;Take the first four bytes of the digest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d6 e3 7d 4c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those bytes are &lt;code&gt;214&lt;/code&gt;, &lt;code&gt;227&lt;/code&gt;, &lt;code&gt;125&lt;/code&gt; and &lt;code&gt;76&lt;/code&gt;. Convert them as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;214/256 + 227/256² + 125/256³ + 76/256⁴ = 0.83940871…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Dice, apply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;floor(value × 10001) / 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example result is &lt;code&gt;83.94&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For Limbo with the example's 1% edge, apply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;max(1, floor(0.99 / value × 100) / 100)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corresponding result is &lt;code&gt;1.17×&lt;/code&gt;. These are different mappings from the same underlying value. Copying a Dice conversion into a different game does not establish that game's result.&lt;/p&gt;

&lt;p&gt;For another useful check, keep the seeds and change the nonce to &lt;code&gt;2&lt;/code&gt;. The message becomes &lt;code&gt;my-client-seed:2:0&lt;/code&gt;; the digest begins &lt;code&gt;ad06e622&lt;/code&gt;, the value is &lt;code&gt;0.67588652…&lt;/code&gt;, and the Dice result is &lt;code&gt;67.59&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspect the implementation without confusing game models
&lt;/h2&gt;

&lt;p&gt;The open-source verifier is available at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/cryptoplayguide/provably-fair-verifier" rel="noopener noreferrer"&gt;https://github.com/cryptoplayguide/provably-fair-verifier&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Its README describes a dependency-free JavaScript module for browsers or Node.js 18+ using the Web Crypto API. It checks commitments and implements the documented Dice and Limbo mappings. Its Limbo implementation rejects a float of zero, or a value outside &lt;code&gt;(0, 1)&lt;/code&gt;, with a &lt;code&gt;RangeError&lt;/code&gt; rather than returning &lt;code&gt;Infinity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The repository also supports a Crash model, but its inputs and byte handling differ: salt is the HMAC key, the game hash is the message, and the calculation takes the first 52 bits. That distinction is a reason to read the operator's fairness documentation before choosing a verifier mode.&lt;/p&gt;

&lt;p&gt;A browser interface is available at &lt;a href="https://cryptoplay.guide/tools/provably-fair-verifier/" rel="noopener noreferrer"&gt;https://cryptoplay.guide/tools/provably-fair-verifier/&lt;/a&gt;. CryptoPlay Guide states that verification runs locally in the browser and sends nothing to CryptoPlay Guide. You can first reproduce the example, then use your own revealed inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the conclusion narrow
&lt;/h2&gt;

&lt;p&gt;A successful check establishes that the supplied result matches the committed seed under the formula you used. It does not establish solvency, withdrawal reliability, licensing or an attractive house edge.&lt;/p&gt;

&lt;p&gt;Keep result verification and payout analysis as separate checks. Reproducing a roll explains where that roll came from; it does not make a negative expected return disappear.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://cryptoplay.guide/guides/verify-provably-fair-step-by-step/" rel="noopener noreferrer"&gt;https://cryptoplay.guide/guides/verify-provably-fair-step-by-step/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CryptoPlay Guide, the site this was originally published on, earns affiliate commissions from some casinos it covers. This post contains no affiliate links.&lt;/p&gt;

&lt;p&gt;18+ (or the higher legal age where you live). Gambling involves risk of loss; only play where legal, set deposit, loss and time limits, and seek help if gambling causes harm, for example from BeGambleAware.org.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>cryptography</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
