<?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>Forem: Nick</title>
    <description>The latest articles on Forem by Nick (@apollotoday).</description>
    <link>https://forem.com/apollotoday</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%2F697612%2F73962020-bc4a-4447-a7f7-f47de10ddcf3.jpeg</url>
      <title>Forem: Nick</title>
      <link>https://forem.com/apollotoday</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/apollotoday"/>
    <language>en</language>
    <item>
      <title>The Hidden AI Cheating Crisis Costing Companies $125,000 Per Bad Hire</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Mon, 26 May 2025 00:46:17 +0000</pubDate>
      <link>https://forem.com/apollotoday/the-hidden-ai-cheating-crisis-costing-companies-125000-per-bad-hire-4o0g</link>
      <guid>https://forem.com/apollotoday/the-hidden-ai-cheating-crisis-costing-companies-125000-per-bad-hire-4o0g</guid>
      <description>&lt;h2&gt;
  
  
  The Hidden AI Cheating Crisis Costing Companies $125,000 Per Bad Hire
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How Cluely AI and Similar Tools Are Undermining Your Remote Interview Process
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;A comprehensive guide for HR professionals on detecting and preventing AI-powered interview fraud&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.detectcluely.com/" rel="noopener noreferrer"&gt;https://www.detectcluely.com/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Last month, Sarah, a seasoned HR director at a Fortune 500 company, thought she'd found the perfect candidate. The remote interview was flawless—every technical question answered with precision, behavioral responses that hit every STAR method point perfectly. Two weeks into the job, it became clear: this person couldn't perform even basic tasks they'd demonstrated mastery of during the interview.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sarah's company had fallen victim to AI-powered interview cheating.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The $125,000 Problem No One's Talking About
&lt;/h2&gt;

&lt;p&gt;While companies have invested millions in sophisticated ATS systems and interview processes, a new threat has emerged that's flying completely under the radar. Tools like Cluely AI are giving candidates real-time answers during video interviews, and the financial impact is staggering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;$85,000&lt;/strong&gt; average cost in salary and benefits for one bad hire&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$15,000&lt;/strong&gt; in training and onboarding expenses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$25,000&lt;/strong&gt; in lost productivity and team disruption&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total cost per fraudulent hire: $125,000&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here's the alarming part: &lt;strong&gt;73% of HR professionals have never heard of AI interview assistance tools&lt;/strong&gt;, according to recent industry surveys.&lt;/p&gt;

&lt;h2&gt;
  
  
  How AI Interview Cheating Actually Works
&lt;/h2&gt;

&lt;p&gt;Modern AI cheating tools like Cluely operate through sophisticated screen-monitoring technology:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Real-time audio processing&lt;/strong&gt;: The AI listens to interview questions as they're asked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant answer generation&lt;/strong&gt;: Advanced language models provide detailed, role-specific responses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seamless delivery&lt;/strong&gt;: Answers appear on secondary screens or through discrete notifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behavior coaching&lt;/strong&gt;: Some tools even provide real-time coaching on body language and tone&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The technology has become so advanced that even experienced interviewers struggle to detect when it's being used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Red Flags Every HR Professional Should Know
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Technical Interview Red Flags:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Perfect answers with no thinking time&lt;/strong&gt;: Immediate, comprehensive responses to complex technical questions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robotic response patterns&lt;/strong&gt;: Answers that sound like they came from documentation rather than experience&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inability to elaborate&lt;/strong&gt;: When asked to expand on answers, candidates struggle or repeat the same information&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screen-looking behavior&lt;/strong&gt;: Frequent glances away from the camera, especially to secondary monitors&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Behavioral Interview Red Flags:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;STAR method perfection&lt;/strong&gt;: Every behavioral question answered with textbook-perfect structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generic examples&lt;/strong&gt;: Stories that sound like they could apply to anyone in any role&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inconsistent details&lt;/strong&gt;: When asked follow-up questions about their examples, details don't align&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unusual confidence&lt;/strong&gt;: Candidates who seem overly prepared for every possible question&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Detection Challenge
&lt;/h2&gt;

&lt;p&gt;The most concerning aspect of this trend is how difficult detection has become. Unlike traditional cheating methods, AI-powered assistance creates responses that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contextually appropriate&lt;/strong&gt;: Answers are tailored to the specific role and company&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Naturally phrased&lt;/strong&gt;: Advanced language models generate human-like responses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technically accurate&lt;/strong&gt;: AI can access vast databases of information instantly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behaviorally appropriate&lt;/strong&gt;: Some tools even coach candidates on interview best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Protecting Your Organization: A Strategic Approach
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Immediate Actions:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Educate your interview team&lt;/strong&gt; about AI cheating tools and detection methods&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement multi-stage verification&lt;/strong&gt; with practical assessments that can't be easily assisted&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use randomized questioning&lt;/strong&gt; that makes it harder for AI to prepare responses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Require camera-on policies&lt;/strong&gt; with specific positioning requirements&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Long-term Solutions:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Invest in detection technology&lt;/strong&gt; that can identify unusual patterns in candidate behavior&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Develop role-specific practical assessments&lt;/strong&gt; that require real-time problem-solving&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create collaborative interview formats&lt;/strong&gt; that are harder to cheat on&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Establish clear policies&lt;/strong&gt; regarding AI assistance in interviews&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Legal and Ethical Implications
&lt;/h2&gt;

&lt;p&gt;As AI interview cheating becomes more prevalent, organizations need to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fair hiring practices&lt;/strong&gt;: How do you maintain equity when some candidates have AI assistance?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legal compliance&lt;/strong&gt;: What constitutes fraud in the interview process?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy development&lt;/strong&gt;: Clear guidelines on acceptable and unacceptable AI use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation requirements&lt;/strong&gt;: Proper record-keeping for potential legal challenges&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Industry Response and Future Outlook
&lt;/h2&gt;

&lt;p&gt;Leading HR technology companies are beginning to develop counter-measures, but the cat-and-mouse game between cheating tools and detection systems is just beginning. Organizations that don't adapt their interview processes risk:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Decreased hiring quality&lt;/strong&gt;: More unqualified candidates slipping through&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased turnover costs&lt;/strong&gt;: Bad hires leading to quick departures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team disruption&lt;/strong&gt;: Unqualified team members affecting overall productivity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reputation damage&lt;/strong&gt;: Poor hiring decisions reflecting on HR effectiveness&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Taking Action: Your Next Steps
&lt;/h2&gt;

&lt;p&gt;The AI interview cheating crisis requires immediate attention from HR leaders. Here's what you can do today:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Assess your current vulnerability&lt;/strong&gt;: Review your remote interview processes for potential weaknesses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Train your team&lt;/strong&gt;: Educate interviewers on detection methods and red flags&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update your processes&lt;/strong&gt;: Implement practical assessments and verification steps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invest in detection tools&lt;/strong&gt;: Consider technology solutions that can help identify AI assistance&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion: The Time to Act is Now
&lt;/h2&gt;

&lt;p&gt;The emergence of AI-powered interview cheating represents a fundamental shift in the hiring landscape. Organizations that recognize this threat early and adapt their processes accordingly will maintain their competitive advantage in talent acquisition.&lt;/p&gt;

&lt;p&gt;Those that don't may find themselves paying the $125,000 price tag—repeatedly.&lt;/p&gt;

&lt;p&gt;The question isn't whether AI interview cheating will affect your organization. The question is whether you'll be prepared when it does.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Want to learn more about protecting your organization from AI interview fraud? Visit &lt;a href="https://detectcluely.com" rel="noopener noreferrer"&gt;DetectCluely.com&lt;/a&gt; for comprehensive detection guides and tools designed specifically for HR professionals.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;: &lt;em&gt;This article was written by industry experts specializing in HR technology and interview security. For more insights on modern hiring challenges, follow our publication.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Tags:
&lt;/h3&gt;

&lt;h1&gt;
  
  
  HumanResources #InterviewFraud #ArtificialIntelligence #RemoteWork #HiringBestPractices #TalentAcquisition #WorkplaceTechnology #InterviewSecurity #HRTechnology #RecruitmentFraud
&lt;/h1&gt;

</description>
      <category>interview</category>
      <category>hiring</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Sun, 15 Dec 2024 05:43:54 +0000</pubDate>
      <link>https://forem.com/apollotoday/-2a96</link>
      <guid>https://forem.com/apollotoday/-2a96</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/apollotoday" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F697612%2F73962020-bc4a-4447-a7f7-f47de10ddcf3.jpeg" alt="apollotoday"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/apollotoday/deploying-nextjs-pocketbase-to-a-single-flyio-machine-34pi" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Deploying Next.js + Pocketbase to a single Fly.io machine&lt;/h2&gt;
      &lt;h3&gt;Nick ・ Dec 15&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#startup&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>nextjs</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Deploying Next.js + Pocketbase to a single Fly.io machine</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Sun, 15 Dec 2024 04:08:23 +0000</pubDate>
      <link>https://forem.com/apollotoday/deploying-nextjs-pocketbase-to-a-single-flyio-machine-34pi</link>
      <guid>https://forem.com/apollotoday/deploying-nextjs-pocketbase-to-a-single-flyio-machine-34pi</guid>
      <description>&lt;p&gt;I am constantly starting side projects, and like so many, I try to get the product out the door as quick as possible. I previously thought I have touched nirvana with Next.js + Supabase, but after so many projects you have to start paying Supabase the big bucks! &lt;/p&gt;

&lt;p&gt;After two projects you need to pay Supabase 25 dollars a month, and each project you add is an additional 10 dollars a month. Pricey for side projects that are yet to make any money.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nicholasoxford" rel="noopener noreferrer"&gt;
        nicholasoxford
      &lt;/a&gt; / &lt;a href="https://github.com/nicholasoxford/pocketwatcher" rel="noopener noreferrer"&gt;
        pocketwatcher
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🚀 Production-ready Next.js template with PocketBase and shadcn/ui. Includes authentication, beautiful UI components, and one-command deployment.
    &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;h1 class="heading-element"&gt;PocketWatcher&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://nextjs.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ac2220a21952c0bff8c3904d26e3f66447872d558088e21f93064c16b1c9972b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6578742e6a732d31352532422d626c61636b" alt="Next.js"&gt;&lt;/a&gt;
&lt;a href="https://pocketbase.io/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/0a4b7f15030db4f16141aaf828bbe3a2f218294145fcee3cf482ca9eb7fbbd93/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f636b6574426173652d302e32332d626c7565" alt="PocketBase"&gt;&lt;/a&gt;
&lt;a href="https://ui.shadcn.com/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e12f640db56d9e6c9e3715eb6cb62562f735160bc8f9ee1ee1e63ce53acb12c3/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f73686164636e25324675692d6c61746573742d707572706c65" alt="shadcn/ui"&gt;&lt;/a&gt;
&lt;a href="https://bun.sh/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/78c01299b491d76f81c99d59f415356c8f1f9f519e8def72cad391d9ef0ed5a9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f42756e2d312e302532422d626c61636b" alt="Bun"&gt;&lt;/a&gt;
&lt;a href="https://github.com/nicholasoxford/pocketwatcherLICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/4c8edb73fd95ab52c2eceb5635ead9af07567d17386848ed80d79358fe48b72a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e" alt="License"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;A modern full-stack template that combines the power of Next.js, the simplicity of PocketBase, and the beauty of shadcn/ui. Perfect for quickly bootstrapping production-ready web applications with authentication and a polished UI.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🚀 Next.js 15+ App Router&lt;/li&gt;
&lt;li&gt;📦 PocketBase backend with built-in authentication&lt;/li&gt;
&lt;li&gt;🎨 Beautiful UI components from shadcn/ui&lt;/li&gt;
&lt;li&gt;🌐 Server-side rendering and client-side interactivity&lt;/li&gt;
&lt;li&gt;🔄 Form handling with React Server Actions&lt;/li&gt;
&lt;li&gt;🔐 Complete authentication system with email/password&lt;/li&gt;
&lt;li&gt;🐳 Production-ready Docker setup&lt;/li&gt;
&lt;li&gt;☁️ One-command deployment to Fly.io&lt;/li&gt;
&lt;li&gt;🔒 Secure cookie-based authentication&lt;/li&gt;
&lt;li&gt;🛡️ Type-safe development with TypeScript&lt;/li&gt;
&lt;li&gt;⚡ Bun for fast package management and running scripts&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Started&lt;/h2&gt;

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

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Bun runtime&lt;/li&gt;
&lt;li&gt;Fly.io CLI (for deployment)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Local Development&lt;/h3&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Clone the repository:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/yourusername/pocketwatcher.git
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; pocketwatcher&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Install dependencies:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;bun install&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Start the development servers:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In one terminal, start PocketBase:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;./pocketbase serve&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In another terminal, start the Next.js development server:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;bun run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="4"&gt;
&lt;li&gt;Access the applications
&lt;ul&gt;
&lt;li&gt;Next.js: &lt;a href="http://localhost:3000" rel="nofollow noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PocketBase Admin…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/nicholasoxford/pocketwatcher" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;I was deploying so many Supabase projects I created a cli to self host Supabase on fly.io, &lt;a href="https://dev.tosupafly"&gt;Supafly&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Side projects live and die by annoying blockers, the things that are getting in your way that shouldn't. After 10, 15, 20 or so side projects you might start to get a feel for what platform to reach for when. &lt;/p&gt;

&lt;p&gt;What if we could host our entire app, in a familiar fashion, on one machine? Our database, API, and frontend. We should also be able to host this and have easy local development. Local development is classically a bit annoying with Supabase. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9yyma6laxvukesu71h71.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9yyma6laxvukesu71h71.png" alt="Charles Sheeler Painting" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This gives you Authentication, a SQLite database (based), a self deploy next.js app, which is also your api layer, and the ability to do file upload + email easily. &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying Your Stack to fly.io
&lt;/h2&gt;

&lt;p&gt;Getting your app live is surprisingly straightforward. Unlike traditional deployments where you're juggling multiple services, this is all handled in one go.&lt;br&gt;
First-Time Setup&lt;/p&gt;
&lt;h3&gt;
  
  
  Install the Fly.io CLI if you haven't already
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -L https://fly.io/install.sh | sh
fly auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Launch Process&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun run launch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run this, you'll hit two prompts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Do you want to tweak these settings before proceeding?"
→ Just hit enter (the defaults work great)
"Would you like to allocate dedicated ipv4 and ipv6 addresses now?"
→ Type Y (you'll need this)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Getting Your Admin Access
&lt;/h2&gt;

&lt;p&gt;Here's the crucial part that often trips people up. Your PocketBase admin setup needs a special URL, but it's easy to find:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fly logs | &lt;span class="nb"&gt;grep &lt;/span&gt;pbinstal
This will show you something like:
Copyhttp://0.0.0.0:8090/api/admins/confirm-password-reset?token&lt;span class="o"&gt;=&lt;/span&gt;YOUR_TOKEN_HERE

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

&lt;/div&gt;



&lt;p&gt;
  "Important: Modifying the URL"
  &lt;br&gt;
You'll need to change this URL before using it:

&lt;p&gt;Replace &lt;a href="http://0.0.0.0:8090" rel="noopener noreferrer"&gt;http://0.0.0.0:8090&lt;/a&gt; with &lt;a href="https://your-app-name.fly.dev:8091" rel="noopener noreferrer"&gt;https://your-app-name.fly.dev:8091&lt;/a&gt;&lt;br&gt;
Keep the rest of the URL path and token exactly the same&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Once you're set up, you can access your app at:&lt;/p&gt;

&lt;p&gt;Main App: &lt;a href="https://your-app-name.fly.dev" rel="noopener noreferrer"&gt;https://your-app-name.fly.dev&lt;/a&gt;&lt;br&gt;
Admin Panel: &lt;a href="https://your-app-name.fly.dev:8091/_/" rel="noopener noreferrer"&gt;https://your-app-name.fly.dev:8091/_/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pro Tips&lt;br&gt;

  "Deployment Troubleshooting"
  &lt;p&gt;If you don't see the pbinstal log right away, wait a minute and try the logs command again&lt;br&gt;
Keep that initial admin URL safe until you've set up your account&lt;br&gt;
Once you've set up your admin account, that initial URL won't work anymore (this is a security feature)&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Check out more of my writing at &lt;a href="https://nicholasoxford.com/" rel="noopener noreferrer"&gt;nicholasoxford.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project made with this: &lt;a href="https://domainbobber.com/" rel="noopener noreferrer"&gt;domainbobber.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>startup</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Minting a tree for compressed NFTs</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Thu, 23 Mar 2023 15:15:48 +0000</pubDate>
      <link>https://forem.com/apollotoday/minting-a-tree-for-compressed-nfts-13n7</link>
      <guid>https://forem.com/apollotoday/minting-a-tree-for-compressed-nfts-13n7</guid>
      <description>&lt;p&gt;If you are still NFT Twitter adjacent, you've seen a firehouse of tweets about compressed NFTs. Just like with Candy Machine V1, they are all the rage. Today we are focused on step one of minting a compressed NFT, &lt;code&gt;minting a tree on-chain&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I've found a few great explanations on what compressed NFTs are:&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%2F4adz78vfdo8r01k8t95s.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%2F4adz78vfdo8r01k8t95s.png" alt="Compression"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alchemy's: &lt;a href="https://www.alchemy.com/overviews/compressed-nfts" rel="noopener noreferrer"&gt;What are compressed NFTs?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Metaplex's: &lt;a href="https://www.metaplex.com/posts/expanding-digital-assets-with-compression-for-nfts" rel="noopener noreferrer"&gt;Expanding Digital Assets with Compression for NFTs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main goal of compressed NFTs is to dramatically decrease the cost of minting to greatly widen the adoption of Solana NFTs.&lt;/p&gt;

&lt;p&gt;When working with toy Solana projects, I've found that using a Next.js app is the best way to get started quickly. In my experience, you need a node server to work with Metaplex code. With the api folder, you can get a lot done without having to worry about compatibility and code splitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;We need to install relevant dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @solana/spl-account-compression @solana/web3.js @metaplex-foundation/mpl-bubblegum @mintee/wrapped-connection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part of working with compressed NFTs is familiarizing yourself with the connection wrapper. If you follow any example, you will see that it extends the normal &lt;code&gt;@solana/web3.js&lt;/code&gt; Connection class with some helpers around Keypairs and compressed NFTs. You pass in your RPC URL and a keypair to sign/pay for transactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;WrappedConnection&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@mintee/wrapped-connection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Keypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SystemProgram&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sendAndConfirmTransaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@solana/web3.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Keypair&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;connectionWrapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;WrappedConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getConnectionWrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.mainnet-beta.solana.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going to define a function called &lt;code&gt;mintTree()&lt;/code&gt;. When minting an account to hold your tree, you need to define the depth and buffer size. 2^{DEPTH} is the capacity of the tree.&lt;/p&gt;

&lt;p&gt;When working with Solana, you have to calculate how large the account size needs to be upfront. When working with compressed NFTs, you have a higher up-front cost, but each mint is cheaper.&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%2Fh0cwjlp39wl9swkxt5kp.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%2Fh0cwjlp39wl9swkxt5kp.png" alt="How do they work?"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mintTree&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;payer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;connectionWrapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&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;treeKeypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Keypair&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;maxDepth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxBufferSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;

&lt;span class="c1"&gt;// create account size based on number of NFTs&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getConcurrentMerkleTreeAccountSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;maxDepth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxBufferSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// get tree authority &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;treeAuthority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_bump&lt;/span&gt;&lt;span class="p"&gt;]&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;PublicKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findProgramAddressSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;treeKeypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBuffer&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="nx"&gt;BUBBLEGUM_PROGRAM_ID&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have created the instructions for minting an account we need to write the transactions for allocating the account and creating the tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createTreeIx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createCreateTreeInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;merkleTree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;treeKeypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;treeAuthority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;treeCreator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;payer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;logWrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SPL_NOOP_PROGRAM_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;compressionProgram&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SPL_ACCOUNT_COMPRESSION_PROGRAM_ID&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="nx"&gt;maxBufferSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;maxDepth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;public&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;BUBBLEGUM_PROGRAM_ID&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;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allocTreeIx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createTreeIx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;feePayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After sending the transaction we will get back an assetId. The assetId is a PDA of Bubblegum. It the equivalent of a token address. This is where compressed NFTs get controversial. They are a pretty unique RPC extension, so if you mint a compressed NFT on Helius per se, you have to use that RPC to get back the info.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendAndConfirmTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;connectionWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;treeKeypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connectionWrapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payer&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;commitment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirmed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;skipPreflight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Successfull created merkle tree for account: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;treeKeypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&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;treeKeypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;Failed to create merkle tree: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;e&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;



</description>
      <category>solana</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Using Python to track NFT prices on FTX</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Sat, 30 Oct 2021 14:49:30 +0000</pubDate>
      <link>https://forem.com/apollotoday/using-python-to-track-nft-prices-on-ftx-1h3n</link>
      <guid>https://forem.com/apollotoday/using-python-to-track-nft-prices-on-ftx-1h3n</guid>
      <description>&lt;p&gt;Recently during the launch of &lt;a href="https://twitter.com/chickentribe" rel="noopener noreferrer"&gt;ChickenTribe&lt;/a&gt; on the Solana blockchain, I became intrigued by a certain &lt;a href="https://ftx.us/nfts/token/485223445421518089" rel="noopener noreferrer"&gt;NFT&lt;/a&gt;. If you watch TV or don't have adblocker you've probably seen ads for FTX everywhere. FTX, in my opinion, is the premier trading platform for cryptocurrencies. I prefer it to coinbase and I think its relevance will only grow. They just completed a &lt;a href="https://www.cnbc.com/2021/10/21/crypto-exchange-ftx-raises-420-million-at-25-billion.html" rel="noopener noreferrer"&gt;fundraising round&lt;/a&gt; for $420 million dollar from 69 investors. &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%2Fjy6sl215kj97gsh9lo01.jpeg" 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%2Fjy6sl215kj97gsh9lo01.jpeg" alt="FTX"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During this time, &lt;code&gt;ChickenTribe #0&lt;/code&gt; was listed for sale, but returned an error when I clicked purchase. I thought, let me try to create an api to ping this until it's able to sell and buy it programmatically. What I was surprised by was just how easy it is to call FTX via its &lt;a href="https://docs.ftx.com/#overview" rel="noopener noreferrer"&gt;API&lt;/a&gt; and act on the data you receive. &lt;/p&gt;

&lt;p&gt;To get info about a particular NFT all we need to do is write and run this python program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://ftx.us/api/nft/nft/485223445421518089&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;      
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;result_formatted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_formatted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Error obtaining NFT data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&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 returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;485223445421518089&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ChickenTribe #0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;issuer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ChickenTribe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;collection&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ChickenTribe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;series&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ChickenTribe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;solMintAddress&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Du7roiVM8VzX6GFiQLYePcp1fLnkDhxWdFeQN4GMpAQF&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ethContractAddress&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imageUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.arweave.net/FnSVZj95IP0uYpU0mcHVr3TPUvCewxwTNgCQ1Ff6Xjc?ext=png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;videoUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;animationUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thumbnailUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attributes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Backgrounds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rust Red&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bodies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Fall&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Heads&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ruby&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Faces&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Lava&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Combs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Basic Purple&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Eyes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accessories&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Smokes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attributesList&lt;/span&gt;&lt;span class="sh"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rust Red&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trait_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Backgrounds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;totalQuantity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redeemable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redeemed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;offerPrice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;donation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;needsListingFee&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;featured&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2021-10-29T15:42:44.431599+00:00&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;createdAt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2021-10-29T15:42:44.431599+00:00&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quoteCurrency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SOL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;depositMethods&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;withdrawalMethods&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;totalSellerFeeRate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;royaltyFeeRate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While nft/nft/{$id} might be confusing at first. To grab all nfts you would simply call nft/nfts and iterate through the result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://ftx.us/api/nft/nfts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;      
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;nft&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="n"&gt;result_formatted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_formatted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Error obtaining NFT data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have never run python code on your computer I recommend Google Collab. Here is a &lt;a href="https://colab.research.google.com/drive/1x5bBcQp_DAO35Y8nn79uSmirwWCv3OYc?usp=sharing" rel="noopener noreferrer"&gt;link to a worksheet&lt;/a&gt; with the above code. You need to run each cell individually, in order.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://ftx.us/#a=ApolloToday" rel="noopener noreferrer"&gt;Sign up for FTX Here&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Let me know what you would like to see in future tutorials. Next tutorial I will be covering authentication to act on the data we retrieved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If you found this helpful, consider sending a tip to the author. 
2vta8S9QJEeZSRTXxR5eL3tfpFVbHhRAKMnQmQeCBKAV
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Deploying Your First Arweave Contract</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Sat, 30 Oct 2021 13:41:40 +0000</pubDate>
      <link>https://forem.com/apollotoday/deploying-your-first-arweave-contract-15jc</link>
      <guid>https://forem.com/apollotoday/deploying-your-first-arweave-contract-15jc</guid>
      <description>&lt;p&gt;At a high level, smart contracts make sense to a lot of people. They are programs that live on chain, that are deterministic in nature, and are based in that idea code is law. I first learned about smart contracts back in 2017 with ethereum first gaining traction. Instantly my mind wandered into ideas of these interweaving contracts that mitigate the need for lawyers. I think the most important thing to remember about smart contracts is that they are supposed to remove a human element, which all programs typically try to do, but do it in a verifiable and reproducible way... All on the ✨ Blockchain ✨&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%2F19t5ksy3q8tpjo5mti2w.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%2F19t5ksy3q8tpjo5mti2w.png" alt="Arweave"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Arweave released their version of smart contracts back in June 2020. Smartweave, or a new smart contract protocol, enabling computation-heavy dapps on top of the Arweave network, allowed devs to write some simple javascript and easily deploy it to the chain. If this is your first time learning about Arweave, I recommend checking out my &lt;a href="https://dev.to/apollotoday/getting-started-with-arweave-2e9k"&gt;introduction&lt;/a&gt;. If you're familiar with the ecosystem, you will notice that Smartweave is built upon the foundation of the blockweave. Unlike Eth v1 implementation of smart contracts, where each node has to validate the outcome - smartweave deploys a lazy evaluation method. Where Arweave's "network is utilized as a generic data consensus and sharing layer". Basically, the user broadcasts the outcome of their smart contract and the network validates. Learn more &lt;a href="https://arweave.medium.com/introducing-smartweave-building-smart-contracts-with-arweave-1fc85cb3b632" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In a later post, I will dive deeper into the background of smartweave and its technical implementation. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, let's go ahead and create a &lt;code&gt;contract.js&lt;/code&gt; and a &lt;code&gt;contract.json&lt;/code&gt; in the folder of your choice. Smartweave uses javascript through the client's unmodified execution engine. What I have found the biggest mental switch is that you don't define variables in the &lt;code&gt;.js&lt;/code&gt; file. You define the name and initial state of each relevant variable in &lt;code&gt;.json&lt;/code&gt;. &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%2F053b1rl2an9e5owlujlu.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%2F053b1rl2an9e5owlujlu.png" alt="Picture of code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first bit of code we are going to write is our javascript. Something important to remember is that contracts &lt;em&gt;must&lt;/em&gt; be deterministic. I feel like &lt;code&gt;deterministic&lt;/code&gt; is one of those signal words CS major use to beckon each other. All it means is that the function will produce the same output from a given starting input. You should never do a network call or produce a random number inside of a smartweave contract. Lastly, we can arbitrarily (up to a certain number of bites) input any data when we call our contract. We pass in these inputs via &lt;code&gt;action.input.function === 'someString'&lt;/code&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="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;Twitter&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;twitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;ArWallet&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arWallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;arVerify&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arVerify&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;twitter&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;arVerify&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;wallet&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;mintNft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;mintNFt&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;You'll notice we have a bunch of variables passed in through the state variables. These are the variables defined in your json.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"twitter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"arWallet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"arVerify"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mintNft"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This contract was created while I was working on another Arweave project where if you complete a certain number of steps you will receive a free NFT. More on that at a later date. This contract will get called when a user connects their wallet. At that time I will pass in &lt;code&gt;arWallet: true&lt;/code&gt;. This contract will continue to return false until all three variables are set to true. In the next article when we interact with our contract, you'll see how we can retrieve state without an input. What's cool is that contracts can read the state of other contracts. &lt;/p&gt;

&lt;p&gt;Let's go ahead and check if we have a key-file representing our Arweave wallet. While you don't need gas to interact with a contract you do to deploy, although it's nominal. Luckily you can get a dollar or two of AR through the &lt;a href="https://faucet.arweave.net/" rel="noopener noreferrer"&gt;faucet&lt;/a&gt;. &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%2Fe0kfcac2we8i71l8zjhq.gif" 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%2Fe0kfcac2we8i71l8zjhq.gif" alt="Wallet grab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll be honest, when I was getting ready to deploy my first the README.md was confusing me. It wasn't until I ran &lt;code&gt;smartweave create -h&lt;/code&gt; in my terminal didn't I really understand what I needed to pass in. To deploy our contract you need to have Node install and run &lt;code&gt;npm install -g smartweave&lt;/code&gt;. This globally installs the smartweave package so we can call it anywhere. Next, navigate to the folder your contracts are in and remember where your key file is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;smartweave create &lt;span class="nt"&gt;-h&lt;/span&gt;
  ____                       _ __        __
 / ___| _ __ ___   __ _ _ __| |&lt;span class="se"&gt;\ \ &lt;/span&gt;     / ___  __ ___   _____
 &lt;span class="se"&gt;\_&lt;/span&gt;__ &lt;span class="se"&gt;\|&lt;/span&gt; &lt;span class="s1"&gt;'_ ` _ \ / _` | '&lt;/span&gt;__| __&lt;span class="se"&gt;\ \ &lt;/span&gt;/&lt;span class="se"&gt;\ &lt;/span&gt;/ / _ &lt;span class="se"&gt;\/&lt;/span&gt; _&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="se"&gt;\ \ &lt;/span&gt;/ / _ &lt;span class="se"&gt;\&lt;/span&gt;
  ___&lt;span class="o"&gt;)&lt;/span&gt; | | | | | | &lt;span class="o"&gt;(&lt;/span&gt;_| | |  | |_ &lt;span class="se"&gt;\ &lt;/span&gt;V  V |  __| &lt;span class="o"&gt;(&lt;/span&gt;_| |&lt;span class="se"&gt;\ &lt;/span&gt;V |  __/
 |____/|_| |_| |_|&lt;span class="se"&gt;\_&lt;/span&gt;_,_|_|   &lt;span class="se"&gt;\_&lt;/span&gt;_| &lt;span class="se"&gt;\_&lt;/span&gt;/&lt;span class="se"&gt;\_&lt;/span&gt;/ &lt;span class="se"&gt;\_&lt;/span&gt;__|&lt;span class="se"&gt;\_&lt;/span&gt;_,_| &lt;span class="se"&gt;\_&lt;/span&gt;/ &lt;span class="se"&gt;\_&lt;/span&gt;__|

smartweave create &amp;lt;contractSource&amp;gt; &amp;lt;initStateFile&amp;gt;

Creates a new contract from a &lt;span class="nb"&gt;source &lt;/span&gt;file or existing contract &lt;span class="nb"&gt;source &lt;/span&gt;already
on-chain.

Positionals:
  contractSource  The contract source. A path to a .js file, or transaction &lt;span class="nb"&gt;id&lt;/span&gt;
                                                                      &lt;span class="o"&gt;[&lt;/span&gt;required]
  initStateFile   The initial state of the contract. Path to a .json file
                                                                      &lt;span class="o"&gt;[&lt;/span&gt;required]

Options:
  &lt;span class="nt"&gt;--version&lt;/span&gt;   Show version number                                      &lt;span class="o"&gt;[&lt;/span&gt;boolean]
  &lt;span class="nt"&gt;--help&lt;/span&gt;      Show &lt;span class="nb"&gt;help&lt;/span&gt;                                                &lt;span class="o"&gt;[&lt;/span&gt;boolean]
  &lt;span class="nt"&gt;--key-file&lt;/span&gt;  Your key file                                           &lt;span class="o"&gt;[&lt;/span&gt;required]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at the &lt;code&gt;-h&lt;/code&gt; you see the create call is really quite simple. Just pass in the path to your js and json file in that order. Last declare your key pair with --key-file. When you click enter the network will first calculate your tx fee. After this is calculated it will ask you to enter a random adjective it generated.&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%2F8qkmhqvgfg74a9lppgta.gif" 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%2F8qkmhqvgfg74a9lppgta.gif" alt="CLI Upload"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The contract will get pushed to the network pretty quickly. However, it will take a while for your transaction (tx) to be mined. Tx are prioritized by their fee amount. I use &lt;a href="https://dev.toArweave%20App"&gt;https://arweave.app/&lt;/a&gt; to check my pending transactions. &lt;/p&gt;

&lt;p&gt;In the next smartweave tutorial we will look at our wallet transaction history, interact with our wallet using the command line, and through a web application. &lt;/p&gt;

&lt;p&gt;If you found this helpful (AR Wallet):&lt;br&gt;
&lt;code&gt;WtrURL9vjAUQQXMQxY5c9FZnh_IKOog5P38KO7oZnbg&lt;/code&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Getting Started With Arweave</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Thu, 28 Oct 2021 20:37:40 +0000</pubDate>
      <link>https://forem.com/apollotoday/getting-started-with-arweave-2e9k</link>
      <guid>https://forem.com/apollotoday/getting-started-with-arweave-2e9k</guid>
      <description>&lt;p&gt;Our entire life, we have been told what we post on the internet lives forever. While this might be true for that photo you're embarrassed of, generally, the data that existed on the internet when we were younger, is gone.  We currently &lt;code&gt;depend&lt;/code&gt; on a slew of companies to store and access our data. What's crazy is the vast majority of us have never given a dollar to Google or Facebook. Yet their trillion-dollar valuations make them some of the most valuable companies of all time.  While during my life I have benefited from the network effects these platforms created, and I can currently look back on the majority of my life through Facebook memories, something isn't right with leaving our footprint to these technology behemoths with &lt;a href="https://www.theregister.com/2021/10/22/google_facebook_antitrust_complaint/"&gt;cartel-like behavior&lt;/a&gt; over YOUR data. Web 2.0 is unsustainable - and why would you want it to be?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lK7JLRO4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vc8iwe853k4g77vb0vh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lK7JLRO4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vc8iwe853k4g77vb0vh3.png" alt="Image description" width="759" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think for a lot of people, creating a sort of digital footprint, one future generation can look back on, is starting to bubble up in one's mind. With the current state of the web, we aren't choosing what sticks around. I already regret a whole slew of Instagram photos I deleted back when I was younger. I basically erased a good part of my digital past. There has to be a better way to pass on these important digital memories. Really, if Facebook is still relevant when my great-grandkids are around - God helps us all. &lt;/p&gt;

&lt;p&gt;Arweave is such a perspective shifter, that I think naturally we kinda shrug it off. Permanent data storage -- sure. Oh and on top of a blockchain?? okay my guy! Yet, the further I dig into Arweave the more I am convinced. I think the crucial part of Arweave is that for a miner to receive a reward - not only do they have to mine (store) the new data from the Blockweave on their hardware, they also have to return a random document that the network demands. With the right incentive structure, you can encourage the right parties, to store data forever. Obviously, I am simplifying the array of &lt;a href="https://www.arweave.org/technology"&gt;protocols&lt;/a&gt; that made something like Arweave possible, but the cool thing is to interact with Arweave and permastorage you really don't need to understand what is going on. This will also become easier over time, using &lt;a href="https://ardrive.io/"&gt;ArDrive&lt;/a&gt; it can already feel like uploading a file to Dropbox. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4rHukaePPNk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You might know Arweave through Metaplex - or the Solana defacto standard for creating NFTs. When creating these NFT's, what is actually happening is that each image is being uploaded to Arweave, and the corresponding URL is appended to that particular tokens metadata. &lt;/p&gt;

&lt;p&gt;The coolest thing is that Arweave is more than just simple data storage and retrieval protocol. Which is fast by the way. It is a platform to ensure memories, perspectives, and data can be put into the record, permanently. Personally, I've never had an issue with being censored. I've been lucky enough my whole life to share my opinions freely, without any repercussions or take-backs. This is clearly not true for everyone. Arweave allows us to upload data now, and judge later. &lt;/p&gt;

&lt;p&gt;Beyond images, you can upload entire web applications, smart contracts, and other forms of multimedia that will still the same - forever. What's interesting is that when you upload a website or web application, you have to think differently. This as is, will be the way it is forever. That is exciting! Who knows who will interact with my website, decades from now. This is a byproduct of the immutability of Arweave. Each block of data is cryptographically intertwined with the previous and following block. Lastly the economic model is what makes it sustainable. To upload an image it cost about 2 cents. This is both paying to upload the image immediately and then some of that transaction is going into an endowment. Because storage gets cheaper over year the relatively purchasing power of that endowment goes up. Effectively acting like interest. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--goKEXnAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jopyf63b0a94nkpo6qzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--goKEXnAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jopyf63b0a94nkpo6qzu.png" alt="Image description" width="880" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Arweave isn't something we can learn in a day, or a simple article. It's a journey that connects deeply with you. What does permanent mean to you? What do you want to leave behind. Do you want to help a certain group digitize their history? This is just the beginning of a deep exploration of Arweave. In the next article, I will be deploying a website to the permaweb. You won't believe how easy it is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://smarturl.it/permawebpioneers"&gt;Permaweb Pioneer's Podcast&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you found this helpful (AR Wallet):&lt;br&gt;
&lt;code&gt;WtrURL9vjAUQQXMQxY5c9FZnh_IKOog5P38KO7oZnbg&lt;/code&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Getting started with Metaplex (A Solana NFT Journey PT. 1)</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Sun, 26 Sep 2021 19:04:00 +0000</pubDate>
      <link>https://forem.com/apollotoday/getting-started-with-metaplex-a-solana-nft-journey-pt-1-1jff</link>
      <guid>https://forem.com/apollotoday/getting-started-with-metaplex-a-solana-nft-journey-pt-1-1jff</guid>
      <description>&lt;p&gt;
  TLDR
  &lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=GqXu8MfdEG4" rel="noopener noreferrer"&gt;Ignition Metaplex Worskshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://solanalabs.zoom.us/rec/share/5azT9d0TACBbGPxVV0Js1FocnoAJ6cOK1CYVsl_EyAGP8opJxa-unbtO6X7aTitn.81Xk1R8XO-mSWRVi" rel="noopener noreferrer"&gt;Zoom Office Hours / PW: I5T$pa^z&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.quicknode.com/guides/web3-sdks/how-to-mint-an-nft-on-solana-using-candy-machine" rel="noopener noreferrer"&gt;End to end Candy Machine Tutorial by Noah Hein&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackmd.io/@levicook/HJcDneEWF" rel="noopener noreferrer"&gt;Levi Cook's OG and continually updated Candy Machine guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ignore my original candy machine guide and use &lt;code&gt;ts-node&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;/p&gt;
&lt;p&gt;The velocity and excitement around the Metaplex ecosystem keeps me coming back every day. I feel both a desire and reward to learn more. I would be lying if I said I had it all figured it. I mean I already wrote &lt;a href="https://dev.to/nicholasoxford/an-annotated-guide-to-the-metaplex-candy-machine-tutorial-2ihd"&gt;one guide&lt;/a&gt; on using Metaplex's candy machine, but in my eyes, it's already out of date!  It's not like the NFT's I minted with that tutorial are invalid, there are just more robust ways to get your 5000 pngs on the chain.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/GqXu8MfdEG4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you are interested in Metaplex, I would recommend two things. First, watch Metaplex's Ignition Workshop. Ignition is the Solana hackathon currently happening &lt;code&gt;(var today = September 27th, 2021)&lt;/code&gt; until October 15th. There are 4 tracks, over 5 million dollars in awards, and sponsors like Microsoft, Metaplex, and Mango. The other content I would watch, as of today, is Metaplex's office hours from Friday. So many nuggets of knowledge to be had, and I know I will be attending them from here on out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Meeting Recording:
https://solanalabs.zoom.us/rec/share/5azT9d0TACBbGPxVV0Js1FocnoAJ6cOK1CYVsl_EyAGP8opJxa-unbtO6X7aTitn.81Xk1R8XO-mSWRVi

Access Passcode: I5T$pa^z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After watching the office hours, I knew immediately that my tutorial was at best, out of date. This could be a point of pain, thinking why did I write this, but honestly - I find it exciting. When things change, you look for a source of truth, when you find that source of truth, changes aren't so bad. The source of truth for Metaplex's candy machine is &lt;code&gt;candy-machine-cli.ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If we go to this &lt;a href="//js/packages/cli/src/candy-machine-cli.ts"&gt;file on GitHub&lt;/a&gt;, and cmd-f &lt;code&gt;create_candy_machine&lt;/code&gt;. You will see a code representation of what returns when you entered &lt;code&gt;metaplex create_candy_machine -h&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Usage: cli create_candy_machine &lt;span class="o"&gt;[&lt;/span&gt;options]

Options:
  &lt;span class="nt"&gt;-e&lt;/span&gt;, &lt;span class="nt"&gt;--env&lt;/span&gt; &amp;lt;string&amp;gt;                Solana cluster &lt;span class="nb"&gt;env &lt;/span&gt;name &lt;span class="o"&gt;(&lt;/span&gt;default: &lt;span class="s2"&gt;"devnet"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;-k&lt;/span&gt;, &lt;span class="nt"&gt;--keypair&lt;/span&gt; &amp;lt;path&amp;gt;              Solana wallet location &lt;span class="o"&gt;(&lt;/span&gt;default: &lt;span class="s2"&gt;"--keypair
                                    not provided"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;-l&lt;/span&gt;, &lt;span class="nt"&gt;--log-level&lt;/span&gt; &amp;lt;string&amp;gt;          log level
  &lt;span class="nt"&gt;-c&lt;/span&gt;, &lt;span class="nt"&gt;--cache-name&lt;/span&gt; &amp;lt;string&amp;gt;         Cache file name &lt;span class="o"&gt;(&lt;/span&gt;default: &lt;span class="s2"&gt;"temp"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt;, &lt;span class="nt"&gt;--price&lt;/span&gt; &amp;lt;string&amp;gt;              Price denominated &lt;span class="k"&gt;in &lt;/span&gt;SOL or spl-token
                                    override &lt;span class="o"&gt;(&lt;/span&gt;default: &lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt;, &lt;span class="nt"&gt;--spl-token&lt;/span&gt; &amp;lt;string&amp;gt;          SPL token used to price NFT mint. To use
                                    SOL leave this empty.
  &lt;span class="nt"&gt;-t&lt;/span&gt;, &lt;span class="nt"&gt;--spl-token-account&lt;/span&gt; &amp;lt;string&amp;gt;  SPL token account that receives mint
                                    payments. Only required &lt;span class="k"&gt;if &lt;/span&gt;spl-token is
                                    specified.
  &lt;span class="nt"&gt;-h&lt;/span&gt;, &lt;span class="nt"&gt;--help&lt;/span&gt;                        display &lt;span class="nb"&gt;help &lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You might notice that command-line options like &lt;code&gt;--log-level&lt;/code&gt; aren't listed under &lt;code&gt;create_candy_machine&lt;/code&gt;. That's because these are global options defined inside the function programCommand on line 611. Did you know, in VsCode you can hit control+g on mac to jump to a line, neat!&lt;/p&gt;

&lt;p&gt;Whenever I see people ask on the Metaplex discord &lt;em&gt;if&lt;/em&gt; something is possible, they should just look at this file. It also contains the definition for updating a candy machine. What I find interesting is that the code follows a pretty simple flow, especially for update_candy_machine. If you watch deep into the Metaplex ignition workshop, the presenters discuss how simple candy machine actually is. &lt;/p&gt;

&lt;p&gt;I believe this simplicity is difficult to see when you are first starting out.  I read the &lt;a href="https://docs.metaplex.com/" rel="noopener noreferrer"&gt;Metaplex docs&lt;/a&gt; a couple times before it started to click. It's not like I read it end to end each time, but the mental model took a few days to come together. Y'all are brighter than me though. &lt;/p&gt;

&lt;p&gt;Beyond just Levi Cook's &lt;a href="https://hackmd.io/@levicook/HJcDneEWF" rel="noopener noreferrer"&gt;legendary tutorial&lt;/a&gt;, I have found that Noah Hein's &lt;a href="https://www.quicknode.com/guides/web3-sdks/how-to-mint-an-nft-on-solana-using-candy-machine" rel="noopener noreferrer"&gt;How to Mint an NFT on Solana Using Candy Machine&lt;/a&gt; to be the most comprehensive tutorial out there. I'm probably going to update my old tutorial to only point to this site. &lt;/p&gt;

&lt;p&gt;If you have been following Levi's guide, you know at one point you used the &lt;code&gt;metaplex&lt;/code&gt; command line binary to create candy machines. This is currently not recommended. Believe me when I say it wasn't pleasant to install anyways. &lt;/p&gt;
&lt;h2&gt;
  
  
  Don't use the metaplex binary to create a candy machine
&lt;/h2&gt;

&lt;p&gt;In both the workshop and more specifically the zoom call around &lt;code&gt;15:30&lt;/code&gt; they talk and show how to create a candy machine by calling the typescript files directly. Make no mistake, you will still be using the command line, just not the metaplex package. At least for the time being.&lt;/p&gt;
&lt;h2&gt;
  
  
  That moment when everything clicks
&lt;/h2&gt;

&lt;p&gt;When I was first working with the candy machine, I wasn't aware of the significance of what the Metaplex foundation is making. I highly recommend going to &lt;code&gt;js/packages/web&lt;/code&gt; and running the web app. Once you connect this next.js app to your wallet, you are able to mint individual NFTs, dictate the way they are sold, and auction them off all on a deployable web UI. Now I am a full time Vue software engineer, so when I see React I typically look the other way. However, it's clear that React is the way to go here. I know enough about React to see the amount of work that has gone into connecting Solana wallets and React hooks. I do not want to rewrite that in Vue (alone). I found the candy-machine originally from an Exiled Apes github repo. If you are familiar with the Exiled Ape's candy-machine repo, it seems to be more just a drop in wallet for any react app. The metaplex web folder comes with all the tools you need to launch a full NFT site. It is a little slow, so a take a breath, and just enjoy the learning. &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/exiled-apes" rel="noopener noreferrer"&gt;
        exiled-apes
      &lt;/a&gt; / &lt;a href="https://github.com/exiled-apes/candy-machine-mint" rel="noopener noreferrer"&gt;
        candy-machine-mint
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Fork, config, customize and ship your own candy machine mint app on your own domain, ultra fast.
    &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;h1 class="heading-element"&gt;Candy-Machine-Mint&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;The Candy-Machine-Mint project is designed to let users fork, customize, and deploy their own candy machine mint app to a custom domain, ultra fast.&lt;/p&gt;

&lt;p&gt;A candy machine is an on-chain Solana program (or smart contract) for managing fair mint. Fair mints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start and finish at the same time for everyone.&lt;/li&gt;
&lt;li&gt;Won't accept your funds if they're out of NFTs to sell.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Candy-Machine-Mint project is meant to be as simple and usable as possible, accessible to everyone from long-time crypto devs to junior React devs with a vague interest in NFTs. Our goal is to empower users to create their own front ends to display, sell, and manage their NFTs as simply as possible by just updating a few styled components and following a well-documented process for setup and shipping.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Set Up&lt;/h2&gt;
&lt;/div&gt;

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


&lt;ul&gt;

&lt;li&gt;

&lt;p&gt;Ensure you have recent versions of both &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;yarn&lt;/code&gt; installed.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Follow the instructions &lt;a href="https://docs.solana.com/cli/install-solana-cli-tools" rel="nofollow noopener noreferrer"&gt;here&lt;/a&gt;…&lt;/p&gt;


&lt;/li&gt;

&lt;/ul&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/exiled-apes/candy-machine-mint" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Okay cool, with this Metaplex platform we can be an artist on the lower end of technical expertise all the way to an experienced rust developer connecting metaplex contracts with anchor programs using &lt;a href="https://project-serum.github.io/anchor/tutorials/tutorial-3.html" rel="noopener noreferrer"&gt;CPIs&lt;/a&gt;! &lt;/p&gt;

&lt;p&gt;I have a strong feeling that this is just the beginning of Metaplex. For artist and developers alike, types like &lt;code&gt;seller_fee_basis_points&lt;/code&gt; make for a healthier eco system. Metaplex also pushes the community towards good actors, or at least exposing potential bad actors. An nft marketplace does not need to enforce royalties, but the community would put them on blast the second anyone finds out.&lt;/p&gt;

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

&lt;p&gt;If you used my first tutorial, ignore it, and use the:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts-node ~/metaplex-foundation/metaplex/js/packages/cli/src/candy-machine-cli.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;method instead. I'm sure in a week I will need to post another update with all the great changes multiple teams are making. &lt;/p&gt;

&lt;p&gt;In part 2 I will continue to showcase the metaplex platform and begin to explore &lt;a href="https://arweave.org/" rel="noopener noreferrer"&gt;Arweave&lt;/a&gt;. Let me know if you would like an article giving an overview of Solana as well! I hope you all feel the excitement I feel when I am &lt;em&gt;truly&lt;/em&gt; learning hour after hour. I know I am not going to get this rust code overnight, I know I am not going to get every detail right about my first candy machine. The important part is we both keep coming back night after night.&lt;/p&gt;

&lt;p&gt;Nicholas Oxford&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If you found this helpful, consider sending a tip to the author.
2vta8S9QJEeZSRTXxR5eL3tfpFVbHhRAKMnQmQeCBKAV
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>blockchain</category>
      <category>programming</category>
      <category>rust</category>
    </item>
    <item>
      <title>Going Serverless with MongoDB Realm &amp; Vue 3</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Mon, 20 Sep 2021 22:06:52 +0000</pubDate>
      <link>https://forem.com/apollotoday/going-serverless-with-mongodb-realm-vue-15m1</link>
      <guid>https://forem.com/apollotoday/going-serverless-with-mongodb-realm-vue-15m1</guid>
      <description>&lt;p&gt;MongoDB Atlas is a comprehensive platform for building data driven applications. While most people know Mongo for their document style database, the capabilities of their cloud platform can empower both individual developers and teams to do great things - fast. When you spin up an Atlas cluster, you have search, charting, and data archiving built in. Today, I'll be walking through getting started with MongoDB's serverless solution - &lt;strong&gt;Realm&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Realm originally was an open source, object database oriented towards the mobile market and developer experience. They made it easy to sync data between clients(phones and tablets) and a central database. However, today it is a platform that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;builds better apps faster with edge-to-cloud sync and fully managed backend services including triggers, functions, and GraphQL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The fact that Realm sits right on top of your database means you can easily stand up an API with authentication in &lt;em&gt;minutes&lt;/em&gt;. It automates many parts of creating an API, - it creates the GraphQL schema, runs a validation, and helps you craft your queries through &lt;a href="https://docs.mongodb.com/realm/graphql/custom-resolvers/"&gt;custom resolvers&lt;/a&gt; and &lt;a href="https://graphql.org/learn/queries/"&gt;mutations&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7ater9Bu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebi12iq0ovoe2lkmpsol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7ater9Bu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebi12iq0ovoe2lkmpsol.png" alt="Cross Platform-gjuo0jvhiz" width="880" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond just GraphQL, Realm can also host a single page application or static sites, run serverless functions, and perform &lt;a href="https://www.mongodb.com/realm/mobile/sync"&gt;magic with Sync&lt;/a&gt;. If you do it right, your entire stack can be on Atlas. We're going to create a web app to do just that.&lt;/p&gt;

&lt;p&gt;I really like the idea of visualizing data on a map. While I made a tutorial about &lt;a href="https://medium.com/@nicholasoxford/learning-python-mapping-atl-crime-data-935d2406265b"&gt;doing this in Python&lt;/a&gt;, I love creating things for the web. Everyone is always app this, app that, but this limits your audience to a single platform - unlike the web.  Billions of people have access to an internet browser. Let's build a website that calls our data and visualizes it on a map. &lt;/p&gt;

&lt;p&gt;Seems pretty simple, but the second you have your site call a database it can go from some fun project to teeth grinding code writing, where you forgot why you were even doing this in the first place. I think keeping the fire alive is what can take a project from some weeknight thing to a passion project you continue to iterate on.&lt;/p&gt;

&lt;p&gt;If you are interested in seeing me upload &lt;a href="https://www.youtube.com/watch?v=tTpkM8tAgjI"&gt;crime data&lt;/a&gt; to a MongoDB collection, I am happy to walk  through that - just let me know. However, for this project, we will be using the sample data that comes with MongoDB. If you have done a MongoDB tutorial you will be beyond familiar with these &lt;a href="https://docs.atlas.mongodb.com/sample-data/"&gt;sample collections&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The sample database we are going to use is called &lt;em&gt;sample_geospatial&lt;/em&gt;, which is a collection of 11,000 shipwrecks. MongoDB actually allows you to do GeoSpatial queries, like &lt;code&gt;$geoNear&lt;/code&gt; - which returns &lt;code&gt;an ordered stream of documents based on the proximity to a geospatial point&lt;/code&gt;. Real quickly, a MongoDB instance, or cluster, is made up of Databases that contain collections. Unlike SQL, it is document-based, rather than relation-based.  The &lt;a href="https://docs.mongodb.com/manual/core/document/"&gt;document style&lt;/a&gt; is really suitable for information related to web applications. You can load everything you need for a page without joining tables. You just have to architect it right. &lt;/p&gt;

&lt;h2&gt;
  
  
  Creating The Database 💾
&lt;/h2&gt;

&lt;p&gt;If you haven't yet, go ahead and create a MongoDB account. Besides AWS, the MongoDB free tier is as generous as they come. After creating a project and a database, click [...] - Load Sample Data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tYCPG6N0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1fsxeilbf4p0n2bi4pv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tYCPG6N0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1fsxeilbf4p0n2bi4pv.png" alt="Sample Data Gif" width="878" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you now click &lt;strong&gt;Browse Collections&lt;/strong&gt; you will find our geospatial database + the single shipwrecks collection. If we click through to this and see the list of documents, we can get an understanding of the general shape of the document.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vccD84pI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nltytzmdt3yers9lp5ti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vccD84pI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nltytzmdt3yers9lp5ti.png" alt="Shipwreck MongoDB Document" width="880" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My hunch is we will mainly be focused on longitude and latitude. I recommend clicking through a few pages of documents and get a mental model of what you are seeing. Now that we have looked at our data, let's go ahead and click the &lt;strong&gt;Realm Tab&lt;/strong&gt; at the top of the page. If you haven't created a Realm project before you will see the following dialogue. Name the app whatever your heart desires and navigate to the schema tab. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f1k74xII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8pdov66nxxtfxeqvmyk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f1k74xII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8pdov66nxxtfxeqvmyk.gif" alt="Creating Schema in Realm" width="600" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After clicking this tab, it prompts us to add a Data Source. Make sure to chose your cluster, probably named Cluser0. Now name your Realm project, I am going with data-viz. I am going to leave MongoDB Connection string off for now. Finally chose primary for the Read Preference and click Save Draft. &lt;/p&gt;

&lt;p&gt;With Realm, deploying changes is a two-step process. We just drafted our changes - which at the end of the day are just a few line changes in a few &lt;code&gt;config.json&lt;/code&gt; files - now we need to deploy them. You will see a blue banner with a button about review and deploying. Click through.&lt;/p&gt;

&lt;p&gt;Before we can create a schema based on our data we have to give Realm permission to our shipwrecks collection. Click "+ Add Collection" on the Rules page it just directed you too. Make sure to select the geospatial database and proper collection. If you don't see any databases or collections, your cluster might be performing maintenance. If you go back to the Atlas tab, you can see if your cluster is ready or not.&lt;/p&gt;

&lt;p&gt;Once the collection shows up, click Shipwrecks. Ignore the sections about permissions and templates and click &lt;em&gt;Add Collection&lt;/em&gt; in the bottom right. &lt;/p&gt;

&lt;p&gt;Now if we go back to the schema page we can generate the GraphQL schema. You'll see a green "Generate Schema" button on the right side of the page. Click it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xkNzlBlW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p3kou9hoat3rd9lbgkvg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xkNzlBlW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p3kou9hoat3rd9lbgkvg.gif" alt="ezgif-3-fe520e53808f" width="600" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure to chose just the shipwrecks collection in the first select. Next, you choose how many documents to sample. With GraphQL, the schema validation matters in totality. It feels like an iron first that forces you to get your data structure down. 500 is fine for this. I've found major diminishing marginal returns after around 750.&lt;/p&gt;

&lt;p&gt;Click save and deploy. Without saving and deploying, your validation won’t work. When we navigate to the validate tab, and click run, it should pass!&lt;/p&gt;

&lt;p&gt;We are off to a great start, though it might feel like we've done nothing - but understanding what the heck is going on will have you feeling more confident when we start coding the frontend. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GrMMZHEX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hsct6pn7nzh3dar026da.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GrMMZHEX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hsct6pn7nzh3dar026da.gif" alt="ezgif-2-8efbec0fda8e" width="600" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click GraphQL in the left-hand menu, and click play in their interactive frame. It should return a single shipwreck. If we remove fields like history and recrd then rerun the document you will see that our response does not include those fields. This is the beauty of GraphQL, we only get back the fields we ask for! Next, if you add an s to shipwreck, or shipwrecks, you will see it returns a list of documents. This is how you query either one or multiple documents in GraphQL. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ddddjR70--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2x3sgn2204ug8rowi5m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ddddjR70--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2x3sgn2204ug8rowi5m.gif" alt="Gif of GraphQL query" width="600" height="284"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;Before we visualize our shipwrecks collection, we need to learn a few things about Vue, Open Street Maps, and how to call our Realm backend. &lt;/p&gt;

&lt;p&gt;For simplicity, we are going to define an anonymous authentication method, aka anyone can make a get call. We are going to use &lt;a href="https://v4.apollo.vuejs.org/"&gt;Vue Apollo&lt;/a&gt;. This is an easy way to integrate GraphQL + reactivity into your Vue app while mostly abstracting away the complexity. &lt;/p&gt;

&lt;p&gt;We are also going to use a javascript library to visualize our data. I have found &lt;a href="https://openlayers.org/"&gt;OpenLayers&lt;/a&gt;, and more specifically the &lt;a href="https://github.com/MelihAltintas/vue3-openlayers"&gt;Vue 3 Flavor&lt;/a&gt;, to be super simple to work with. &lt;/p&gt;

&lt;p&gt;Now it's time to create the frontend to display our data. Even if you have never coded something in a javascript framework, you could still do this. If I am being honest, I think Vue2 is more beginner-friendly than Vue3. The thing is - Vue2 is a bunch of boilerplate. So much scaffolding but it's easy to organize your code. &lt;/p&gt;

&lt;p&gt;Vue3, to me, feels like a mature beast. It is still approachable, but you are losing some of the bowling bumpers that Vue2 had. The tradeoff is there is way less code, and with &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt; you can make a reactive front end in just a few lines. You are going to see see things like &lt;code&gt;ref()&lt;/code&gt; and &lt;code&gt;computed(() =&amp;gt; {})&lt;/code&gt;. While you can read about these &lt;a href="https://v3.vuejs.org/guide/computed.html"&gt;concepts in the docs&lt;/a&gt;, using them might be the quickest way to learn &lt;em&gt;why&lt;/em&gt; and &lt;strong&gt;how&lt;/strong&gt; these properties are used. &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--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nicholasoxford"&gt;
        nicholasoxford
      &lt;/a&gt; / &lt;a href="https://github.com/nicholasoxford/realmVueTemplate"&gt;
        realmVueTemplate
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Template for Going Serverless with MongoDB Realm &amp;amp; Vue 3
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/nicholasoxford/realmVueTemplate.git
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; realmVueTemplate
npm i
npm run dev&lt;/pre&gt;

&lt;/div&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/nicholasoxford/realmVueTemplate"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Let's start out by downloading my Github repo. It is a starting point that has Apollo, OpenLayers, and Vue3 preconfigured. I will also add a link at the end to a completed repo for you to test out. I highly recommend trying to follow the rest of the tutorial.&lt;/p&gt;

&lt;p&gt;The first file we are going to look at is &lt;code&gt;main.js&lt;/code&gt;. It is where we mount and configure packages like openLayersMap and Apollo. If you think about it, we want to be able to call our GraphQL data anywhere in the app. To do this we have to globally configure Realm on the client-side and tell Vue our URL.&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test-iuege&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&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;appRealm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Realm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// Gets a valid Realm user access token to authenticate requests&lt;/span&gt;

&lt;span class="c1"&gt;// HTTP connection to the API&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createHttpLink&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// You should use an absolute URL here&lt;/span&gt;
  &lt;span class="na"&gt;uri&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://realm.mongodb.com/api/client/v2.0/app/test-iuege/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fetch&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;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&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="nx"&gt;accessToken&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;getValidAccessToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Authorization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getValidAccessToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Guarantee that there's a logged in user with a valid access token&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appRealm&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;appRealm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// If no user is logged in, log in an anonymous user. The logged in user will have a valid&lt;/span&gt;
    &lt;span class="c1"&gt;// access token.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;appRealm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Realm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;anonymous&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// An already logged in user's access token might be stale. To guarantee that the token is&lt;/span&gt;
    &lt;span class="c1"&gt;// valid, we refresh the user's custom data which also refreshes their access token.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;appRealm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshCustomData&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;appRealm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;const id = "test-iuege";&lt;/code&gt; with your RealmID:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rcriOYHN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5cymw6vijlmg9dp89r3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rcriOYHN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5cymw6vijlmg9dp89r3.png" alt="Screen Shot 2021-09-13 at 9.25.37 PM" width="880" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next click the GraphQL tab in the Mongo UI and copy and paste the URL on the right hand of the page. In the code replace the text of the variable &lt;code&gt;URI&lt;/code&gt; with what is in your clipboard.&lt;/p&gt;

&lt;p&gt;Finally, click the authentication tab, click the edit button next to &lt;code&gt;Allow users to log in anonymously&lt;/code&gt;, and switch it to on. Remember you have to deploy your changes when using Realm. If you look at the &lt;code&gt;main.js&lt;/code&gt; again, you see we call appRealm.login() with anonymous credentials. I am sure you could hand-code that, but these packages make it so easy to configure things like this on the client-side. &lt;/p&gt;

&lt;p&gt;Before we change any frontend code, let us go ahead run &lt;code&gt;npm run dev&lt;/code&gt; in the terminal. If you go to your link, most likely &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt;, you will see the standard Vue getting started page. I think it is beneficial to have our app running so we can see the changes in real-time. This is known as Hot Module Reloading, or HMR. One last time, look back &lt;code&gt;main.js&lt;/code&gt; and you will see &lt;code&gt;import OpenLayersMap from 'vue3-openlayers'&lt;/code&gt;. This allows us to utilize OpenLayers components anywhere in our app. &lt;/p&gt;

&lt;p&gt;Looking at &lt;a href="https://vue3openlayers.netlify.app/componentsguide/geometries/geommultipoint/#usage"&gt;Open Layer's Vue 3 Website&lt;/a&gt;, we see a list of components we can add to our template. With the fact I want to visualize more than one shipwreck, I chose the &lt;code&gt;ol-geom-multi-point&lt;/code&gt; component. Looking at this page, we see the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; code which highest level component is &lt;code&gt;ol-map&lt;/code&gt;. I would recommend clicking the ol-map component page, and exploring the rest of the site. In my opinion, you can learn enough from just ol-geom-multi-point page, but it's helpful to see how other examples utilize the code. &lt;/p&gt;

&lt;p&gt;On the site, below the template code, we see the example&lt;code&gt;script&lt;/code&gt; code section. Because we are going to use the composition API, our final result might look a little different. Let's go ahead and jump back to VsCode (I don't want to hear it) and navigate to &lt;code&gt;/components/HelloWorld.vue&lt;/code&gt;. Here you will need to delete or comment out everything in the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;Next, take everything from OpenLayers and replace what was just removed. Inside our updated &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; code, the component we will worry most about is:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;geom&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;multi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;point&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code you copied over, you will see &lt;code&gt;:coordinates=&lt;/code&gt; is equal to an array of long, lat coordinates, or an array of arrays! We are going to set coordinates to a variable later. If you scroll, you will see in the script section I have the code you need commented out. Go ahead and delete or comment the code that is already there. Notice how there is no return statement like there was in the online example. This is beauty of &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt;... Thank you Evan You!&lt;/p&gt;

&lt;p&gt;The other difference is that my center variable is different. This is because the online example shows some spots in the middle of china, about as far as you can get from shipwrecks. I put the center point to Port-au-Prince, which has a bunch of shipwrecks. Maybe in part 2 we could make it where, as we move the map, it queries our database for the closest shipwrecks. This is easy with MongoDB! It supports GeoJSON like &lt;a href="https://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even though I set the center to Haiti, there are no shipwrecks on your screen. We need to call our Realm instance! This couldn't be easier, as we did most of our configuration in &lt;code&gt;main.js&lt;/code&gt;. We need to add two things to our import statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;graphql-tag&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vue/apollo-composable&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;Looking back at the Vue3 Apollo Docs, we can learn all about &lt;a href="https://v4.apollo.vuejs.org/guide-composable/query.html"&gt;queries&lt;/a&gt;. Hopefully, right now something is clicking, Realm has already automated a gnarly part of GraphQL: creating a query. For our example, we can leave out almost all of the fields, but just copy it from the GraphQL tab!&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;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query AllShips {
    shipwrecks {
      _id
      chart
      coordinates

    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could get everything out of that result object, but I &lt;a href="https://v4.apollo.vuejs.org/api/use-result.html"&gt;recommend using&lt;/a&gt; &lt;code&gt;const points = useResult(result)&lt;/code&gt;. Instead of dealing with iteration, all the info you need is right there. Also, &lt;code&gt;useResult&lt;/code&gt; can help with returning errors. Now we need to use a &lt;a href="https://v3.vuejs.org/guide/computed.html"&gt;computed property&lt;/a&gt;. Computed properties watch for value changes and react to it, furthermore, it caches the result so it can help with performance. In the computed property we are going to map out the coordinates. If you think about it, we are creating an array of arrays.&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;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;points&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;points&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&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;The last thing we need to do is set coordinates to equal our variable messages.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;geom&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;multi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;point&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;coordinates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;messages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ol-geom-multi-point&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we click save and navigate back to our browser, we should see the shipwrecks! It is not pretty, but we have achieved two goals. First, we are calling our database and getting data back. After mapping it out, our front end is reacting and plotting it. All with a few lines of code!&lt;/p&gt;

&lt;p&gt;In this tutorial we have gone from nothing, to having a website that is visualizing shipwreck data from a database we control. We are using the latest and greatest in Vue, utilizing &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt;, the composition API, and GraphQL. We also set up authorization, cleaned our data, and validated schemas. In part 2 I can show deploying this app using Realm, and using Realm’s custom resolvers to query data based on Longitude and Latitude.&lt;/p&gt;

&lt;p&gt;Just for posterity's sake, here is my &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; section.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vue/apollo-composable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;graphql-tag&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query AllShips {
    shipwrecks {
      _id
      chart
      coordinates

    }
  }
`&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;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;points&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;points&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;72.333336&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;18.533333&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;projection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EPSG:4326&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;zoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&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;rotation&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&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;strokeWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&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;strokeColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&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;fillColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we also can do is increase the "height" value in&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;loadTilesWhileAnimating&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;loadTilesWhileInteracting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;height: 1000px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To clean up, we can go back to App.vue and comment out the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element, click save and return to &lt;a href="http://localhost:3000/"&gt;localhost:3000&lt;/a&gt;. Looking much better. Vue and Mongo are two products I love building with. It's a great mix of ease of getting off the ground and ability to craft a complex application or website. You can find a few &lt;a href="https://twitter.com/youyuxi/status/1437865344002048000?s=21"&gt;examples&lt;/a&gt; of &lt;a href="//www.apple.com"&gt;Apple.com&lt;/a&gt; using vue!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1tw91mo0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ueqgee3ejpwopidgj92c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1tw91mo0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ueqgee3ejpwopidgj92c.png" alt="Screen Shot 2021-09-22 at 12.55.32 PM" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know if there is anything you specifically want to see in part 2 😎!&lt;/p&gt;

&lt;p&gt;Nicholas Oxford&lt;/p&gt;

</description>
    </item>
    <item>
      <title>An annotated guide to the 'Metaplex Candy Machine' Tutorial</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Fri, 17 Sep 2021 23:46:31 +0000</pubDate>
      <link>https://forem.com/apollotoday/an-annotated-guide-to-the-metaplex-candy-machine-tutorial-2ihd</link>
      <guid>https://forem.com/apollotoday/an-annotated-guide-to-the-metaplex-candy-machine-tutorial-2ihd</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/exiled-apes" rel="noopener noreferrer"&gt;
        exiled-apes
      &lt;/a&gt; / &lt;a href="https://github.com/exiled-apes/candy-machine-mint" rel="noopener noreferrer"&gt;
        candy-machine-mint
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Fork, config, customize and ship your own candy machine mint app on your own domain, ultra fast.
    &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;h1 class="heading-element"&gt;Candy-Machine-Mint&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;The Candy-Machine-Mint project is designed to let users fork, customize, and deploy their own candy machine mint app to a custom domain, ultra fast.&lt;/p&gt;
&lt;p&gt;A candy machine is an on-chain Solana program (or smart contract) for managing fair mint. Fair mints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start and finish at the same time for everyone.&lt;/li&gt;
&lt;li&gt;Won't accept your funds if they're out of NFTs to sell.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Candy-Machine-Mint project is meant to be as simple and usable as possible, accessible to everyone from long-time crypto devs to junior React devs with a vague interest in NFTs. Our goal is to empower users to create their own front ends to display, sell, and manage their NFTs as simply as possible by just updating a few styled components and following a well-documented process for setup and shipping.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Set Up&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Prerequisites&lt;/h3&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Ensure you have recent versions of both &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;yarn&lt;/code&gt; installed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Follow the instructions &lt;a href="https://docs.solana.com/cli/install-solana-cli-tools" rel="nofollow noopener noreferrer"&gt;here&lt;/a&gt;…&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/exiled-apes/candy-machine-mint" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;NFTS! They are all the craze, and have been for a minute. There is at least something interesting about minting tokens, by the creator of the art, to signify someone "owns" something.  &lt;/p&gt;

&lt;p&gt;Earlier this year I got really into computer generated art. I automated some scripts that would take 8 hours on my personal computer down to 5 minutes on AWS. &lt;/p&gt;

&lt;p&gt;I wanted to see if I could combine this computer generated art and timed releases for fun. More on that at a later date. Right now we are focusing on getting through this &lt;a href="https://hackmd.io/@levicook/HJcDneEWF" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt;. Now I have never touched anything solana before today, and I am up and running. It's possible. &lt;/p&gt;

&lt;h2&gt;
  
  
  Tutorial Annotation as of September 17th, 2021
&lt;/h2&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%2Fcdxw3ymdbq3leanh95fe.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%2Fcdxw3ymdbq3leanh95fe.png" alt="Screen Shot 2021-09-17 at 7.15.48 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only thing I would note about the top instructions is, I would also run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;yarn run package:macos&lt;/code&gt; build step did not work for me. I had to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx pkg . -d --targets node14-macos-x64 --output bin/macos/metaplex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next I used zsh and my path is &lt;code&gt;/usr/local/bin&lt;/code&gt; so my command was&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; cp bin/macos/metaplex /usr/local/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I followed the tutorial until:&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%2F9g961eyh146vyz48j8ee.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%2F9g961eyh146vyz48j8ee.png" alt="Screen Shot 2021-09-17 at 7.28.49 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created a folder called assets in a random directory. I then added 5 images and 5 .json files. Here is my json file from 0.png&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"png0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"symbol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"testing dreamland"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"seller_fee_basis_points"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.arweave.net/abcd5678?ext=png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"external_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"collection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dreamland Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"family"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dreamland"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.arweave.net/abcd5678?ext=png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image/png"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image/png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"creators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REDACTED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"share"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it's my understanding that matrix replaces the url once you upload. The parts that matter are &lt;code&gt;seller_fee_basis_points&lt;/code&gt; and &lt;code&gt;creators&lt;/code&gt;. I'm not totally sure what is &lt;em&gt;required&lt;/em&gt;, but this was a good read about the &lt;a href="https://medium.com/metaplex/metaplex-metadata-standard-45af3d04b541" rel="noopener noreferrer"&gt;metadata file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next I verified all the properties they were looking for. This is where &lt;code&gt;brew install jq&lt;/code&gt; is helpful. Lastly I just &lt;code&gt;cd&lt;/code&gt; into assets directory so my final command was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;metaplex upload . --env devnet --keypair ~/.config/solana/devnet.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The articles mentions multiple errors, I did not get any. Next we need to look at our cache file to grab the config id:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;code .cache/devnet-temp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would then give it a few minutes. The article says to call a &lt;code&gt;metaplex verify&lt;/code&gt; but that cannot be done without a create candy machine. To create one in my terminal I run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;metaplex create_candy_machine --keypair ~/.config/solana/devnet.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it returns: &lt;code&gt;candy machine pubkey&lt;/code&gt;. Keep this value close.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting mint date
&lt;/h3&gt;

&lt;p&gt;To set the mint date you need to pass in a date string. I learned this by running &lt;code&gt;metaplex update_candy_machine -h&lt;/code&gt;&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%2Fotikytte3p9ovfmnbjjd.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%2Fotikytte3p9ovfmnbjjd.png" alt="Metaplex update options"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have all the necessary values set, we need to head over to our .env file on our frontend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// from .cache/devnet-temp
// config value
REACT_APP_CANDY_MACHINE_CONFIG=
// return value from create_candy_machine
// candy machine pubkey
REACT_APP_CANDY_MACHINE_ID=
// I just put my solana wallet address?
REACT_APP_TREASURY_ADDRESS=
// unix date
// 1631923920
REACT_APP_CANDY_START_DATE=1631923920

REACT_APP_SOLANA_NETWORK=devnet
REACT_APP_SOLANA_RPC_HOST=https://explorer-api.devnet.solana.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn't include quotes with my values. After all of this you should be able to &lt;code&gt;Yarn Start&lt;/code&gt; and be able to connect your wallet.&lt;/p&gt;

&lt;p&gt;Shout out &lt;a href="https://twitter.com/levicook_" rel="noopener noreferrer"&gt;Levi Korg&lt;/a&gt; for putting so much work in. I'm excited to learn more about matrix and hopefully host my own auction.&lt;/p&gt;

&lt;p&gt;Hope this helps someone!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Contributing to Fig.io (Autocomplete Tutorial Pt. 2)</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Fri, 17 Sep 2021 22:50:09 +0000</pubDate>
      <link>https://forem.com/apollotoday/contributing-to-fig-io-autocomplete-tutorial-pt-2-3cgh</link>
      <guid>https://forem.com/apollotoday/contributing-to-fig-io-autocomplete-tutorial-pt-2-3cgh</guid>
      <description>&lt;p&gt;Fig has improved my terminal experience in more ways than one. I was able to trim my oh-my-zsh profile to improve terminal start times. Through it VsCode style autocomplete, I'm now aware of flags and options on popular CLI command like &lt;code&gt;git add&lt;/code&gt;, where the &lt;code&gt;--all&lt;/code&gt; flag solved a pesky package.json change I was trying to stage.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;div class="ltag__link__content"&gt;
    &lt;div class="missing"&gt;
      &lt;h2&gt;Article No Longer Available&lt;/h2&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Fig's autocomplete is so good, that when a CLI doesn't have it - you notice. This was the case &lt;code&gt;mongosh&lt;/code&gt;. Mongosh is a way to interact with your mongo clusters through the shell. It starts a node terminal, so you can rip javascript. I love it! However, I often need help crafting that connection query. Once I saw Fig didn't have mongosh autocomplete I honestly got a bit excited. Fig's autocomplete specs are open-sourced. Smart move by the founders, as it's worth it to me, to add certain specs I use a lot. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--42lJeraQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hcu78qhr6aa1zwuiw6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--42lJeraQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hcu78qhr6aa1zwuiw6m.png" alt="CLI Skeleton"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To be frank, when I was first downloading fig I saw the website sections on how you can contribute. My first thought was, this is probably more difficult than my learning tolerance will allow. I was completely wrong. Not only do they have a great guide on how to get your environment set up, but their overview of how command line arguments are made is even better. &lt;/p&gt;

&lt;p&gt;The goal of an autocompletion spec is to outline the path a user can take with certain CLI packages. With npm you might start our with &lt;code&gt;npm run&lt;/code&gt; or &lt;code&gt;npm install&lt;/code&gt;. The available arguments between the two are wildly different. In the grand scheme of things, they are also both pretty simple commands. Luckily, Fig's spec is so flexible, you'll always find a solution to even seemingly abstract CLI. &lt;/p&gt;

&lt;p&gt;After running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run create-example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A file will be created inside the dev folder. Looking at that file we can start to see the template Fig follows. &lt;code&gt;abc&lt;/code&gt; is or command - or in &lt;code&gt;npm run install&lt;/code&gt;, &lt;code&gt;npm&lt;/code&gt; is the command. Then we have our subcommand, &lt;code&gt;checkout&lt;/code&gt;, which is the same as &lt;code&gt;run&lt;/code&gt;. Then finally we have our options and/or arguments. Our main command has options like &lt;code&gt;-v&lt;/code&gt;, as well does our subcommand. Once you get the mental model down of Fig, you can quickly code subcommand after subcommand. I'm also not a guy who can say I spend a lot of time in open source. I would like to, but I just don't feel like I have the technical ability. This is a great entry point into open source.&lt;/p&gt;
&lt;h3&gt;
  
  
  Let's talk about &lt;code&gt;mongosh&lt;/code&gt; and Fig.
&lt;/h3&gt;

&lt;p&gt;Most of the time you are passing a connection string into mongosh. You can think of that as a &lt;strong&gt;command -&amp;gt; argument&lt;/strong&gt; input while most are &lt;strong&gt;command -&amp;gt; subcommand -&amp;gt; argument&lt;/strong&gt;. This trips me up in the beginning. While the options of &lt;code&gt;mongosh&lt;/code&gt; took the majority of the work, the top section is the most important. Here is what I wrote:&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;completionSpec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongosh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The MongoDB Shell, mongosh  is a fully functional JavaScript and Node.js 14.x REPL environment for interacting with MongoDB deployments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connection String&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isOptional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongodb://localhost:27017&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;suggestions&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongodb://localhost:27017&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Default Connection String; Equivalant to running mongosh without any commands&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongodb+srv://cluster0.example.mongodb.net/sample_geospatial&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Atlas Connection String Example&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;35&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;This shows us the capability of suggestions and defaults. When writing this code, I looked at other packages I understood. How did git implement something? The amount of extendibility you have with Fig is empowering. Not only am I just scratching the surface of Fig's capability, I'm sure the team is too. &lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/withfig/autocomplete/pull/580"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat: add autocomplete spec for `mongosh`
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#580&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/nicholasoxford"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s---7GySLTv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars.githubusercontent.com/u/51415676%3Fv%3D4" alt="nicholasoxford avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/nicholasoxford"&gt;nicholasoxford&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/withfig/autocomplete/pull/580"&gt;&lt;time&gt;Sep 10, 2021&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;&lt;strong&gt;What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Introduce CLI completion MongoDB's Command Line Tool.&lt;/p&gt;
&lt;p&gt;I also noticed the PR to delete package-lock from the repo so I went ahead and did that too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is the current behavior? (You can also link to an open issue here)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;No autocomplete&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is the new behavior (if this is a feature change)?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Additional info:&lt;/strong&gt;
&lt;a href="https://docs.mongodb.com/mongodb-shell/reference/options/" rel="nofollow"&gt;https://docs.mongodb.com/mongodb-shell/reference/options/&lt;/a&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/withfig/autocomplete/pull/580"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;If you are wondering how I knew what to add for each field, I followed Mongo's &lt;code&gt;mongosh&lt;/code&gt; &lt;a href="https://docs.mongodb.com/mongodb-shell/reference/options/"&gt;reference spec&lt;/a&gt; 1 for 1. It really became almost a meditative task. Once I made the pull request, their devs made a handful of meaningful comments that improved the quality of code greatly. I think you can learn a lot by looking at my spec, the mongo reference, and it running in the terminal. Thing's like getting someone's filepath to autocomplete is as simple as:&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="nx"&gt;generators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filepaths&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;Since pushing this PR, I've already added features to the &lt;a href="https://cli.github.com/"&gt;Github CLI&lt;/a&gt;, and hope on adding some more in the future. Furthermore, if someone from MongoDB wants to collaborate, my twitter is &lt;a href="https://twitter.com/nick__atl"&gt;@nick__atl&lt;/a&gt;. I feel like I might be missing something from mongosh.&lt;/p&gt;

&lt;p&gt;Nicholas Oxford  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>An Introduction to mongocli, the easiest way to deploy an Atlas cluster!</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Thu, 16 Sep 2021 22:26:38 +0000</pubDate>
      <link>https://forem.com/apollotoday/an-introduction-to-mongocli-the-easiest-way-to-deploy-an-atlas-cluster-51ed</link>
      <guid>https://forem.com/apollotoday/an-introduction-to-mongocli-the-easiest-way-to-deploy-an-atlas-cluster-51ed</guid>
      <description>&lt;p&gt;Deploying infrastructure as code has seemed something worthy of the lucky few in the high castle. Yet, once you get pretty familiar with a product you want to stop going through a UI. With tools like &lt;a href="https://dev.to/nicholasoxford/how-fig-improved-my-zsh-experience-fig-autocomplete-tutorial-pt-1-2aj3"&gt;Fig.io&lt;/a&gt;, using the command line is more accessible than ever. It's now possible that new developers aren't feeling like they are talking into a black-box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bVHUrLc8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ecn4qi8bbbjlhfk7cmlf.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bVHUrLc8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ecn4qi8bbbjlhfk7cmlf.jpeg" alt="salon"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently, I've been creating a lot of weekend projects. Standing up a cluster in Mongo, creating something kinda cool, hit some snag and then abandon the project. This type of coding is super productive. Anyways, because I've used Atlas so much I am constantly looking for ways to automate away the infrastructure. This is the idea behind &lt;a href="https://www.terraform.io/"&gt;terraform&lt;/a&gt; and &lt;a href="https://docs.chef.io/chef_overview/"&gt;chef&lt;/a&gt;. But this is the code for those mysterious SREs. I am sure I could figure it out, but I am a bit afraid I would end up deploying 7 sharded M400s clusters. &lt;/p&gt;

&lt;p&gt;The Mongo Atlas CLI is a sweet spot between full infrastructure automation and using the UI. After running a simple authentication flow, the world is yours. You can &lt;code&gt;mongocli atlas quickstart&lt;/code&gt; which will prompt an interactive cluster creation flow. It's probably helpful to do this at least once. Now, it's going to default you to an &lt;code&gt;M10&lt;/code&gt;. This is probably as much as you need, but you are probably wondering how do I specify what tier I want!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;After running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;brew install mongocli
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to give our mongocli an authentication configuration. Lets create a pair of API keys to be able to fully configure Mongo Atlas services. To do this, navigate to Mongodb.com and &lt;a href="https://account.mongodb.com/account/login"&gt;log in&lt;/a&gt;. Select the dropdown: Access Manager --&amp;gt; Organization Access at the top of the page. We are giving &lt;code&gt;mongocli&lt;/code&gt; more than just the rights to connect to an individual cluster. If you went ahead and tried the &lt;code&gt;quickstart&lt;/code&gt; command, you would see at the end of the flow, it ran &lt;code&gt;mongosh&lt;/code&gt; with your new connection string!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fUa9Cy7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xq48hsz2xy28mfmxn0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fUa9Cy7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xq48hsz2xy28mfmxn0r.png" alt="Screen Shot 2021-09-16 at 5.15.44 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the top right, we need to click Create API Key. You will see an input field for the name of our apiKey and what role we will give it. I named my &lt;code&gt;mongoCli&lt;/code&gt;, and then chose Project Owner for Organization Permissions. While it's possible to give it lower permissions and still be beneficial. I want to transition to start using the UI as little as possible. The next screen will be your public and private api keys. Copy this to a note or VsCode. &lt;/p&gt;

&lt;p&gt;By default, Mongo limits what IP address can access your clusters. This is done at a granular level, or different API keys can have different IP whitelist. Click &lt;code&gt;Add Access List Entry&lt;/code&gt; and then "Us Current IP Address". Forgetting to whitelist my IP is something we will all get hit with at-least-once. Done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;mongocli config
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste your public, then private key. And we are configured. &lt;/p&gt;

&lt;p&gt;What are you, silly? Clearly you want to deploy to AWS, US-East-1. Real ones know if that one goes down - the world ain't working. You are also reasonably worried about the performance issues you will never have. Let us chose M30, 10 gigs. Even if I'm brave enough to adventure past the sample data and upload my own data. I'm sure my collection would never surpass 10k documents. Still, something just doesn't feel right about choosing M10. We're also going to use 5.0, so we need to pass that into our cluster &lt;code&gt;create&lt;/code&gt; argument. You can learn more about Mongo Atlas CLI commands &lt;a href="https://docs.mongodb.com/mongocli/stable/command/mongocli-atlas/"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;mongocli atlas cluster create cliTest2 --provider AWS --region US_EAST_1 --members 3 --tier M30 --mdbVersion 5.0 --diskSizeGB 10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;clusterName&amp;gt;&lt;/code&gt; with whatever your heart desires. But keep it close by, I chose cliTest2. If we head back to our Mongo UI, we should see that Mongo is deploying our cluster. This process takes about 7-10 minutes. Once it is done we can retrieve the connection string for our Atlas instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongocli atlas clusters connectionStrings describe cliTest2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now use that connection string with &lt;code&gt;mongosh&lt;/code&gt; and start querying our databases. We are just scratching the surface with &lt;code&gt;mongocli&lt;/code&gt; - almost criminally so. The last thing we need to do to save our butts financially is terminate this cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongocli atlas clusters delete cliTest2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a few minutes if we return back to our UI. We will see our cluster is now gone. Let me know if you are interested in learning more about the Mongo Atlas CLI.&lt;/p&gt;

&lt;p&gt;Nicholas Oxford &lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>cloudskills</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
