<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: LordGhostX</title>
    <description>The latest articles on DEV Community by LordGhostX (@lordghostx).</description>
    <link>https://dev.to/lordghostx</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%2F523459%2F68fa46da-a2be-4505-8040-92d29b01e92e.png</url>
      <title>DEV Community: LordGhostX</title>
      <link>https://dev.to/lordghostx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lordghostx"/>
    <language>en</language>
    <item>
      <title>SIMD-0204: Building the Foundation for Slashing on Solana</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Sat, 10 May 2025 17:20:40 +0000</pubDate>
      <link>https://dev.to/lordghostx/simd-0204-building-the-foundation-for-slashing-on-solana-1lml</link>
      <guid>https://dev.to/lordghostx/simd-0204-building-the-foundation-for-slashing-on-solana-1lml</guid>
      <description>&lt;p&gt;In proof-of-stake blockchains, validators are responsible for keeping the network secure and functioning by verifying transactions and voting on consensus. To make sure they act honestly, many networks implement slashing. Slashing is a mechanism that punishes validators with bad intentions by taking away some of their staked tokens [1].&lt;/p&gt;

&lt;p&gt;Blockchains like Ethereum, Cosmos, and Polkadot already rely on slashing to discourage bad behavior, like double signing or going offline for too long. The idea is to make attacks expensive and encourage delegators to support trustworthy validators [2].&lt;/p&gt;

&lt;p&gt;Solana, known for its high speed and performance, hasn’t had slashing built into the protocol [3]. Validators could act against the network’s best interests without facing consequences. That’s starting to change with &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0204-slashable-event-verification.md" rel="noopener noreferrer"&gt;SIMD-0204: Slashable Event Verification&lt;/a&gt; [4], which introduces an on-chain program for verifying and recording validator violations. It sets up the infrastructure for slashing to become part of Solana’s future.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Slashing?
&lt;/h2&gt;

&lt;p&gt;Slashing is a protocol-level mechanism used in many proof-of-stake networks to penalize validators that break the rules. When a validator misbehaves, a portion of their staked tokens can be removed or “slashed” to discourage malicious behavior and reinforce honest participation [1][2].&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%2F54fvrnls92pfmc2uwqmb.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%2F54fvrnls92pfmc2uwqmb.png" alt="Slashing Activity on Ethereum" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure: Slashing Activity on Ethereum&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This dashboard from &lt;a href="https://explorer.rated.network/slashings?network=mainnet" rel="noopener noreferrer"&gt;Rated Explorer&lt;/a&gt; [5] shows real-time data on validator slashing in Ethereum, including the total number of penalized validators, how often slashing has occurred, and penalty sizes. As of May 10, 2025, 474 validators have been slashed across 129 separate incidents.&lt;/p&gt;

&lt;p&gt;The types of behavior that lead to slashing vary by network, but common examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Double Signing&lt;/strong&gt;: Signing two different blocks at the same &lt;a href="https://academy.binance.com/en/glossary/block-height" rel="noopener noreferrer"&gt;block height&lt;/a&gt; or &lt;a href="https://docs.chainstack.com/docs/understanding-the-difference-between-blocks-and-slots-on-solana" rel="noopener noreferrer"&gt;block slot&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Equivocation&lt;/strong&gt;: Sending conflicting messages or blocks to different parts of the network during consensus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Downtime&lt;/strong&gt;: Failing to stay online and participate in consensus harms the network’s reliability and can lead to slashing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Surround Voting&lt;/strong&gt;: Submitting votes that contradict earlier ones to try to split the network or manipulate the network.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some proof-of-stake networks also offer rewards to people who detect and report violations. If you submit valid proof of misbehavior, you might get a share of the slashed tokens [13]. This helps keep everyone watching and incentivizes the community to hold validators accountable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Slashing Is Challenging on Solana
&lt;/h2&gt;

&lt;p&gt;Slashing has been part of many proof-of-stake networks for years, but Solana didn’t build it into the protocol early on. That’s mainly because of how the network is designed.&lt;/p&gt;

&lt;p&gt;Solana is built for speed and performance. Validators are expected to cast and share votes quickly, sometimes before memory is fully written to disk. This helps the network stay fast, but it also increases the risk of local-state corruption [3]. In this kind of environment, automatic slashing becomes risky since it could end up punishing validators for errors that aren’t malicious.&lt;/p&gt;

&lt;p&gt;Another challenge is that many types of misbehavior aren’t easy to detect synchronously. Things like duplicate blocks or invalid votes often need to be verified after they happen by collecting and comparing data from across the network [4]. That makes instant punishment harder to get right.&lt;/p&gt;

&lt;p&gt;To handle this, Solana has mostly relied on softer tools like fork choice rules and gossip between validators [6]. These can help correct the network when things go wrong, but they don’t come with penalties or keep a record of what happened. For a network that values speed and resilience, slashing has always been a tricky thing to get right.&lt;/p&gt;

&lt;h2&gt;
  
  
  SIMD-0204: Solana’s First Step Toward Slashing
&lt;/h2&gt;

&lt;p&gt;Slashing on Solana needed a starting point. The network needed a way to prove, not just suspect, that a validator misbehaved. &lt;strong&gt;SIMD-0204&lt;/strong&gt; provides that foundation by introducing a new on-chain program that verifies and records certain types of validator violations.&lt;/p&gt;

&lt;p&gt;The program focuses on a specific violation to start: &lt;code&gt;duplicate block production&lt;/code&gt;. If a valid proof is submitted, the violation is recorded on-chain. These reports don’t result in slashing yet, but they create a permanent, verifiable record of the violation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Duplicate block production has caused real-world issues. In September 2022, a validator malfunction led to duplicate blocks in the same slot, triggering a consensus failure and halting Solana's mainnet for over 8 hours [14].&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This step is intentionally limited in scope. &lt;strong&gt;SIMD-0204&lt;/strong&gt; doesn’t modify stakes or rewards. Its goal is to establish observability, giving the protocol, developers, and stakers a shared view into validator behavior that’s backed by cryptographic proof, not rumor or assumption.&lt;/p&gt;

&lt;h3&gt;
  
  
  How SIMD-0204 Works
&lt;/h3&gt;

&lt;p&gt;When &lt;strong&gt;SIMD-0204&lt;/strong&gt; is activated, it deploys the &lt;a href="https://github.com/solana-program/slashing" rel="noopener noreferrer"&gt;Slashing Program&lt;/a&gt; [7]. This program is enshrined, meaning it's deployed directly by the protocol at a fixed address. To report a violation, a user submits proof using the &lt;code&gt;DuplicateBlockProof&lt;/code&gt; instruction. This proof contains two conflicting shreds for the same slot, signed by the same validator. The program performs a series of checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It verifies that the shreds are formatted correctly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It confirms that the shreds represent a real conflict using known duplication criteria.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It uses the &lt;a href="https://solana.com/docs/core/programs" rel="noopener noreferrer"&gt;Ed25519 Program&lt;/a&gt; [8] to ensure the same validator signed both shreds.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s also a second instruction, &lt;code&gt;CloseViolationReport&lt;/code&gt;, which lets the reporter reclaim the lamports they paid to store the proof. That’s only allowed after a waiting period of three (3) epochs to give indexers and dashboards time to process the data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Thanks to &lt;a rel="noopener noreferrer nofollow" href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0180-vote-account-leader-schedule.md"&gt;SIMD-0180: Vote Account Address Keyed Leader Schedule&lt;/a&gt; [9], block production is now linked to vote accounts rather than validator identities. This makes it possible to associate reported violations with the exact stake that earned a leader slot, which helps slashing in the future.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Future proposals like &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/pull/212" rel="noopener noreferrer"&gt;SIMD-0212: Slashing&lt;/a&gt; [10] will build on this reporting system to enforce actual penalties. But for now, the focus is on proving the network can detect and record violations reliably without introducing risk for honest validators.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Stored On-Chain
&lt;/h3&gt;

&lt;p&gt;After a proof passes verification, the program stores the violation in a new &lt;code&gt;ProofReport&lt;/code&gt; account at a &lt;a href="https://www.alchemy.com/overviews/program-derived-address" rel="noopener noreferrer"&gt;Program Derived Address (PDA)&lt;/a&gt;. This account contains metadata about the violation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;ProofReport&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;// Current version of the report format&lt;/span&gt;
    &lt;span class="n"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Pubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// Public key of the fee payer who submitted the report&lt;/span&gt;
    &lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Pubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Account to receive lamports when the report is closed&lt;/span&gt;
    &lt;span class="n"&gt;epoch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Epoch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// Epoch when the report was created&lt;/span&gt;
    &lt;span class="n"&gt;violator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Pubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// Public key of the violating validator&lt;/span&gt;
    &lt;span class="n"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Slot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="c1"&gt;// Slot at which the violation occurred&lt;/span&gt;
    &lt;span class="n"&gt;violation_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Type of violation (e.g., duplicate block)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to the metadata, the account also stores the submitted proof for future reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;DuplicateBlockProofData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;shred1_length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Length in bytes of the first shred&lt;/span&gt;
    &lt;span class="n"&gt;shred1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;         &lt;span class="c1"&gt;// Byte array containing the first shred’s data&lt;/span&gt;
    &lt;span class="n"&gt;shred2_length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Length in bytes of the second shred&lt;/span&gt;
    &lt;span class="n"&gt;shred2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;         &lt;span class="c1"&gt;// Byte array containing the second shred’s data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This combination ensures that each report includes not only who did what and when but also the raw data needed to verify the violation later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security and Design Considerations
&lt;/h3&gt;

&lt;p&gt;The Slashing Program is deployed using the &lt;code&gt;BPF Upgradeable Loader&lt;/code&gt;, but its upgrade authority is set to &lt;code&gt;None&lt;/code&gt;. This means the program cannot be updated after it’s deployed, ensuring consistent behavior and preventing tampering, even by core developers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;During the &lt;a rel="noopener noreferrer nofollow" href="https://github.com/solana-foundation/solana-improvement-documents/pull/204#discussion_r1866733325"&gt;design review&lt;/a&gt; [11], there was discussion about whether to use the newer &lt;code&gt;Loader-v4&lt;/code&gt;. The team chose to stick with the &lt;code&gt;BPF Upgradeable Loader&lt;/code&gt; for compatibility while leaving the door open to switch if &lt;code&gt;Loader-v4&lt;/code&gt; becomes standard in the future.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To prevent abuse or noise in the program:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The program checks whether a &lt;code&gt;ProofReport&lt;/code&gt; for the same slot and violator already exists. If it does, the new submission is rejected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reports must be properly formed and cryptographically verifiable because malformed or replayed submissions are automatically discarded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A future slashing mechanism will rely on this data, so accuracy and trust in the program matter. &lt;strong&gt;SIMD-0204&lt;/strong&gt; starts with just one type of violation: &lt;code&gt;duplicate block production&lt;/code&gt;. This focused approach keeps things manageable while developers and the community build confidence in the program.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Technical Details to Highlight:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Epoch-bound Activation&lt;/strong&gt;: The program is activated at the boundary of a new epoch when the feature flag is turned on. This keeps integration predictable and reduces risk during rollout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Submission Deadline&lt;/strong&gt;: To prevent stale or delayed reports, proofs must be submitted within approximately one epoch’s worth of slots (432,000 [6]) from when the violation occurred.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Rewards or Penalties (Yet)&lt;/strong&gt;: The program does not currently enforce any penalties or modify validator rewards. Its role is limited to verifying and recording. Future proposals, such as &lt;strong&gt;SIMD-0212&lt;/strong&gt;, are expected to introduce the mechanisms for enforcing penalties based on these reports.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Byte-Level Validation&lt;/strong&gt;: The program performs low-level operations, including fixed-size buffers, little-endian encoding, and offset-based deserialization to interpret and validate proofs. Signature verification is handled through instruction introspection and signature offsets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Minimum Report Retention&lt;/strong&gt;: Reports must remain on-chain for at least three (3) epochs before they can be closed. This window gives dashboards and indexers time to process the data. Only one (1) epoch is truly needed, so this may be reduced in the future.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building Validator Transparency
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SIMD-0204&lt;/strong&gt; lays the groundwork not only for future slashing but also for observing validator behavior in a consistent and verifiable way. Anyone can submit valid proof of violation: validators, bots, monitoring tools, or independent observers running their infrastructure [12]. This open access helps ensure the network is not solely reliant on core validators to flag bad actors.&lt;/p&gt;

&lt;p&gt;As more reports are recorded on-chain, third-party tools are expected to build on top of this data. Dashboards, indexers, and analytics platforms can track validator behavior over time, creating the foundation for metrics like a slashing index or reputation score. These tools help delegators make better-informed staking decisions and encourage validators to maintain good practices [12].&lt;/p&gt;

&lt;p&gt;While no rewards or penalties are enforced yet, this proposal provides a starting point for community-driven transparency. Future incentive structures will likely rely on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next for Slashing on Solana?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SIMD-0204&lt;/strong&gt; introduces the core infrastructure for recording validator violations, but actual slashing requires policy, economics, and enforcement. That’s where future proposals like &lt;strong&gt;SIMD-0212&lt;/strong&gt; come in. This upcoming proposal focuses on how penalties are calculated and applied using the reports generated by &lt;strong&gt;SIMD-0204&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Other improvements and alternatives being discussed include [10][12]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New Violation Types&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Double voting&lt;/li&gt;
&lt;li&gt;Unstaking before a report is recorded (to avoid penalties)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Potential Protocol Changes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cooldown extension: allowing reports to still be submitted after stake deactivation.&lt;/li&gt;
&lt;li&gt;Shorter epochs: reducing the time window during which bad actors can operate before being penalized.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Design Alternatives&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slashing only the validator’s self-stake.&lt;/li&gt;
&lt;li&gt;Deactivating stake without slashing.&lt;/li&gt;
&lt;li&gt;Rewarding reporters for submitting valid proofs.&lt;/li&gt;
&lt;li&gt;Redirecting slashed funds to an insurance pool or protocol treasury.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These decisions will shape how aggressive or conservative Solana’s slashing policy becomes. Community input and governance will play a key role as slashing evolves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implications for the Solana Ecosystem
&lt;/h2&gt;

&lt;p&gt;As with any major protocol change, the introduction of slashing introduces both opportunity and complexity across the Solana ecosystem [4][10][12].&lt;/p&gt;

&lt;h3&gt;
  
  
  Potential Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Increased validator accountability and overall network safety.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enables new incentive structures and more robust slashing economics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transparent violation history (via &lt;code&gt;ProofReports&lt;/code&gt;) supports third-party tools that help delegators evaluate validator behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slashing risk may encourage delegators to spread stakes across more validators, supporting decentralization.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenges and Trade-Offs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;False Positives&lt;/strong&gt;: If verification logic fails, honest validators could be penalized, so rigorous testing and auditing are needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deterrence Risk&lt;/strong&gt;: Without clear education and framing, slashing could discourage new or smaller participants from staking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Operational Overhead&lt;/strong&gt;: Adds complexity for indexers, RPC providers, and dashboard maintainers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Governance Sensitivity&lt;/strong&gt;: Activating slashing and tuning its parameters require broad community alignment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Incentive Complexity&lt;/strong&gt;: Reward systems (e.g., for reporters) must be carefully designed to avoid issues like frontrunning, manipulation, or abuse.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0204-slashable-event-verification.md" rel="noopener noreferrer"&gt;SIMD-0204: Slashable Event Verification&lt;/a&gt; [4] marks a key milestone in Solana’s efforts to promote validator accountability. It introduces an on-chain program for verifiable reporting of validator violations, building the foundation for future slashing logic, economic policy, and governance participation.&lt;/p&gt;

&lt;p&gt;By making validator behavior observable and provable, &lt;strong&gt;SIMD-0204&lt;/strong&gt; empowers dashboards, analytics platforms, and delegators to make more informed decisions. As proposals like &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/pull/212" rel="noopener noreferrer"&gt;SIMD-0212: Slashing&lt;/a&gt; [10] are implemented, this positions the network for a more secure and decentralized validator landscape.&lt;/p&gt;

&lt;p&gt;Looking ahead, the success of slashing in Solana will depend on real-world use. Signals such as valid reports submitted, adoption by validators and tooling, and implementation of slashing mechanisms will matter. A decline in duplicate blocks and growth in tools built around &lt;code&gt;ProofReports&lt;/code&gt; would point to increased transparency and accountability across the network.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] Ledger Academy. “​​What is Slashing in Crypto?”. &lt;a href="https://www.ledger.com/academy/topics/blockchain/what-is-slashing" rel="noopener noreferrer"&gt;https://www.ledger.com/academy/topics/blockchain/what-is-slashing&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[2] Binance Academy. “Slashing”. &lt;a href="https://academy.binance.com/en/glossary/slashing" rel="noopener noreferrer"&gt;https://academy.binance.com/en/glossary/slashing&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[3] Agave Validator Documentation. “Slashing Roadmap”. &lt;a href="https://docs.anza.xyz/proposals/optimistic-confirmation-and-slashing" rel="noopener noreferrer"&gt;https://docs.anza.xyz/proposals/optimistic-confirmation-and-slashing&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[4] Ashwin Sekar. “SIMD-0204: Slashable Event Verification”. &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0204-slashable-event-verification.md" rel="noopener noreferrer"&gt;https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0204-slashable-event-verification.md&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[5] Rated Explorer. “Slashing Activity Dashboard”. &lt;a href="https://explorer.rated.network/slashings" rel="noopener noreferrer"&gt;https://explorer.rated.network/slashings&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[6] Ryan Chern, Helius. “Consensus on Solana”. &lt;a href="https://www.helius.dev/blog/consensus-on-solana" rel="noopener noreferrer"&gt;https://www.helius.dev/blog/consensus-on-solana&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[7] Solana Program Library. “Slashing Program”. &lt;a href="https://github.com/solana-program/slashing" rel="noopener noreferrer"&gt;https://github.com/solana-program/slashing&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[8] Solana Documentation. “Programs”. &lt;a href="https://solana.com/docs/core/programs" rel="noopener noreferrer"&gt;https://solana.com/docs/core/programs&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[9] Justin Starry. “SIMD-0180: Vote Account Address Keyed Leader Schedule”. &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0180-vote-account-leader-schedule.md" rel="noopener noreferrer"&gt;https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0180-vote-account-leader-schedule.md&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[10] Ashwin Sekar. “SIMD-0212: Slashing”. &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/pull/212" rel="noopener noreferrer"&gt;https://github.com/solana-foundation/solana-improvement-documents/pull/212&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[11] Ashwin Sekar and Jon Cinque. “SIMD-0204 Loader Decision”. &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/pull/204#discussion_r1866733325" rel="noopener noreferrer"&gt;https://github.com/solana-foundation/solana-improvement-documents/pull/204#discussion_r1866733325&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[12] Ashwin Sekar. “Solana Foundation Validator Discussion - Dec 12 2024”. &lt;a href="https://youtu.be/7Hmkaj-5QUU?t=709" rel="noopener noreferrer"&gt;https://youtu.be/7Hmkaj-5QUU?t=709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[13] Everstake. “What Is Slashing in Crypto and How Does It Affect You?” &lt;a href="https://everstake.one/blog/what-is-slashing-in-crypto-and-how-does-it-affect-you" rel="noopener noreferrer"&gt;https://everstake.one/blog/what-is-slashing-in-crypto-and-how-does-it-affect-you&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[14] Solana Foundation. “09-30-22 Solana Mainnet Beta Outage Report” &lt;a href="https://solana.com/news/09-30-22-solana-mainnet-beta-outage-report" rel="noopener noreferrer"&gt;https://solana.com/news/09-30-22-solana-mainnet-beta-outage-report&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>solana</category>
      <category>web3</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>Solana at Web2 Speed: Real-Time Performance Without Fragmentation</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Fri, 09 May 2025 06:54:36 +0000</pubDate>
      <link>https://dev.to/lordghostx/solana-at-web2-speed-real-time-performance-without-fragmentation-3b9p</link>
      <guid>https://dev.to/lordghostx/solana-at-web2-speed-real-time-performance-without-fragmentation-3b9p</guid>
      <description>&lt;p&gt;Blockchain performance remains a major hurdle for building real-time applications. Metrics like latency, throughput, and responsiveness determine whether a decentralized network can support use cases such as multiplayer games, financial services, or automated systems.&lt;/p&gt;

&lt;p&gt;Most blockchains are too slow for this. Bitcoin has a block time of 10 minutes and handles around 3 to 7 transactions per second [1][2]. Ethereum produces blocks roughly every 12 seconds and supports about 15 to 30 transactions per second [1][2]. Other networks fall in between: Cardano targets a 20-second block time, and Polkadot ranges from 6 to 12 seconds depending on network configuration [1].&lt;/p&gt;

&lt;p&gt;Solana stands out as the fastest general-purpose blockchain today. It has an average block time of 400 milliseconds and can handle up to 65,000 transactions per second in optimal conditions [2]. This level of speed enables high-frequency, low-cost applications that are not feasible on most other networks. However, when applications demand sub-second responsiveness at a massive scale, even Solana encounters performance bottlenecks.&lt;/p&gt;

&lt;p&gt;This leads to a key question: How can blockchains go faster without compromising the things that make them worth building on? Most existing solutions either fragment the ecosystem, compromise trust assumptions or introduce unnecessary complexities for developers and users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Speed Comes at a Cost
&lt;/h2&gt;

&lt;p&gt;Over the years, several approaches have emerged to improve blockchain performance. While each offers technical benefits, they often introduce trade-offs that reduce composability, increase complexity, or compromise trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2 Rollups: Higher Throughput, Delayed Finality
&lt;/h3&gt;

&lt;p&gt;Layer 2 rollups process transactions off the main chain to reduce congestion and stabilize fees, then publish proofs back to Layer 1 [3]. This setup can significantly increase throughput, taking Ethereum from 15 to 30 transactions per second on-chain to thousands off-chain [1][3]. However, rollups introduce latency due to delayed settlement and rely on fraud or validity proofs for security. They also break atomic composability, making it difficult for contracts on Layer 2 to interact with those on Layer 1 [3].&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%2Frjqlmaffvuxjx2nz3pve.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%2Frjqlmaffvuxjx2nz3pve.png" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure: ZK Rollup Transaction Process&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Transactions are batched off-chain and submitted to Layer 1 with a SNARK proof for verification. This increases throughput and reduces congestion but adds settlement delays and limits composability.&lt;br&gt;&lt;br&gt;
Source: Messari, &lt;a href="https://messari.io/report/polygon-a-multi-sided-approach-to-zk-scaling" rel="noopener noreferrer"&gt;Polygon: A Multi-Sided Approach to ZK Scaling&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  AppChains and Layer 3s: Custom Performance, Isolated State
&lt;/h3&gt;

&lt;p&gt;AppChains and Layer 3 solutions give developers full control over their execution environment, allowing them to tailor performance, security, and governance to the specific needs of a single application [4][5]. This specialization helps reduce congestion, lower fees, and improve efficiency for use cases like gaming or DeFi. However, these systems often operate independently from the main chain, which fragments the state and isolates users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharding: Parallelism with Coordination Overhead
&lt;/h3&gt;

&lt;p&gt;Sharding scales the blockchain by splitting the network into smaller parts called shards. Each shard handles its transactions and data, which helps increase throughput and reduce congestion [6]. However, cross-shard communication is complex, often asynchronous, and can limit how easily apps interact with each other in real-time.&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%2Frdhh80jjplwrbgm6cwib.jpeg" 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%2Frdhh80jjplwrbgm6cwib.jpeg" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure: Sharding Architecture with Beacon Chain Coordination&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This diagram shows a network divided into multiple shard chains, each handling its transactions and data. A central Beacon Chain coordinates between the shards to maintain network consistency.&lt;br&gt;&lt;br&gt;
Source: Ledger Academy, &lt;a href="https://www.ledger.com/academy/what-is-sharding" rel="noopener noreferrer"&gt;What is Sharding?&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sidechains: Flexibility at the Cost of Trust
&lt;/h3&gt;

&lt;p&gt;Sidechains are blockchains that run in parallel to a main chain but operate independently, often with their own consensus mechanisms and execution environments [7]. Assets can be moved between the main chain and the sidechain, typically through a bridge, allowing the sidechain to function with more flexibility. However, this independence comes with weaker security guarantees. Users must trust separate validator sets or bridge infrastructure, which can be vulnerable to failures or attacks.&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%2F8l1monvqwgies706hwlj.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%2F8l1monvqwgies706hwlj.png" width="654" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure: Main Chain and Sidechain Interaction&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sidechains run alongside the main chain and use smart contracts to manage asset transfers and validation. They offer flexibility but rely on separate validators and bridges, which can introduce trust risks.&lt;br&gt;&lt;br&gt;
Source: UC Berkeley, &lt;a href="https://scet.berkeley.edu/blockchain-technology-beyond-cryptocurrencies-case-1-future-last-mile-delivery/" rel="noopener noreferrer"&gt;Blockchain technology beyond cryptocurrencies: the future of last-mile delivery autonomous solutions&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  State Channels: Fast Finality but Limited Scope
&lt;/h3&gt;

&lt;p&gt;This allows high throughput and low fees but requires opening and closing the channel with on-chain transactions. Channels are efficient for repeated interactions between fixed parties which limits flexibility and composability across broader applications [8].&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%2Fa3qccq5vg4j2nmumm0ce.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%2Fa3qccq5vg4j2nmumm0ce.png" width="800" height="740"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure: How State Channels Work&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Participants interact off-chain within a state channel, exchanging signed messages that represent state changes. Only the final state is submitted to the blockchain for settlement, reducing on-chain congestion and enabling faster and cheaper transactions.&lt;br&gt;&lt;br&gt;
Source: CSIRO Blockchain Patterns, &lt;a href="https://research.csiro.au/blockchainpatterns/general-patterns/blockchain-payment-patterns/payment-channel/" rel="noopener noreferrer"&gt;Payment Channel (aka., State Channel)&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Trade-Off
&lt;/h3&gt;

&lt;p&gt;The pattern is clear across these models. Performance improvements often come at the cost of interoperability, additional trust assumptions, or increased development overhead. These trade-offs make it harder to build real-time, composable applications that take full advantage of the blockchain’s potential.&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%2Ffc8eoiv834bemb6sv0br.jpeg" 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%2Ffc8eoiv834bemb6sv0br.jpeg" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure: Trade-offs Across Ethereum's Scaling Solutions&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A side-by-side comparison of Ethereum’s major scaling strategies shows how throughput gains often come at the expense of composability, trust assumptions, or implementation complexity.&lt;br&gt;&lt;br&gt;
Source: Daniel Asaboro, &lt;a href="https://danielandblockchain.hashnode.dev/breaking-the-blockchain-barrier-the-economic-transformation-enabled-by-ephemeral-rollups-on-solana" rel="noopener noreferrer"&gt;Breaking the Blockchain Barrier: The Economic Transformation Enabled by Ephemeral Rollups on Solana&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea of “Ephemeral” in Blockchain
&lt;/h2&gt;

&lt;p&gt;The word &lt;em&gt;ephemeral&lt;/em&gt; means something short-lived or temporary [9]. In the context of blockchain, it refers to execution environments that exist only briefly and do not maintain their permanent state. Rather than creating a new chain or separate network, ephemeral systems handle specific tasks or short bursts of activity and then shut down once they are complete. This idea is now being applied to blockchain performance through Ephemeral Rollups, which offer fast, lightweight execution when needed while avoiding fragmentation and extra infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ephemeral Rollups by MagicBlock
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.magicblock.xyz" rel="noopener noreferrer"&gt;MagicBlock&lt;/a&gt; is building the future of real-time, high-performance, fully on-chain applications that run with the speed and responsiveness of Web2 [9]. It introduced Ephemeral Rollups, a new runtime model that enables low-latency execution for demanding use cases such as games, DeFi protocols, and automation tools without sacrificing speed, security, or composability [10][11].&lt;/p&gt;

&lt;p&gt;At the core, MagicBlock operates as a specialized Solana Virtual Machine (SVM) runtime. Instead of deploying a new chain, developers can delegate specific accounts to Ephemeral Rollups for fast execution [10][11]. The underlying programs, smart contracts, and assets remain on Solana’s mainnet, preserving full composability with the rest of the ecosystem.&lt;/p&gt;

&lt;p&gt;These Ephemeral Rollups support block times as low as 10 to 50 milliseconds, enable gasless transactions and offer features like tick-based execution and custom event loops [10][11]. Developers can spin up high-speed environments as needed without duplicating infrastructure or breaking the unified state of the Solana network.&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%2Flftigfnappf5hs8uhhrk.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%2Flftigfnappf5hs8uhhrk.png" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure: Real-Time Execution with MagicBlock Ephemeral Rollups&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This diagram shows how Ephemeral Rollups operate with 10 millisecond block times and periodically sync back to Solana’s 400 millisecond main runtime. Developers can run high-speed, real-time workloads without leaving Solana’s composable ecosystem.&lt;br&gt;&lt;br&gt;
Source: MagicBlock, &lt;a href="https://docs.magicblock.gg/pages/get-started/introduction/why-magicblock" rel="noopener noreferrer"&gt;Why MagicBlock?&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance and Economic Benefits
&lt;/h2&gt;

&lt;p&gt;Developers can go beyond what is possible on Solana using Ephemeral Rollups while preserving full composability with existing programs and protocols. Developers and users gain the speed and flexibility of a custom execution environment without compromising on security, composability, or ecosystem compatibility [11].&lt;/p&gt;

&lt;h3&gt;
  
  
  No Fragmentation
&lt;/h3&gt;

&lt;p&gt;Programs, assets, and application logic remain on the Solana mainnet. Developers do not need to deploy to a new chain or maintain a separate environment. All improvements to Solana instantly benefit applications using Ephemeral Rollups [11].&lt;/p&gt;

&lt;h3&gt;
  
  
  Atomic Composability
&lt;/h3&gt;

&lt;p&gt;Delegated accounts can still be read by Solana, and undelegated accounts remain fully active [11]. This allows seamless interaction across protocols and avoids interoperability issues seen in many L2, appchains, and sidechain architectures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Familiar Tools and Ecosystem Compatibility
&lt;/h3&gt;

&lt;p&gt;Developers can continue using existing programming languages, libraries, and dev tools without modification. There is no need to rewrite applications or reconfigure infrastructure, making integration straightforward and low-risk [11].&lt;/p&gt;

&lt;h3&gt;
  
  
  High Responsiveness and Custom Execution
&lt;/h3&gt;

&lt;p&gt;Ephemeral Rollups support block times as low as 10 milliseconds. Developers can define custom execution logic, including tick-based updates, event-driven tasks, and session runtimes. This enables real-time UX in areas like gaming, AI, DePIN, or financial automation where responsiveness is critical [11].&lt;/p&gt;

&lt;h3&gt;
  
  
  Low-Cost, Scalable Infrastructure
&lt;/h3&gt;

&lt;p&gt;Gasless or near-zero-cost execution makes high-frequency interactions practical. Ephemeral Rollups are provisioned dynamically and scale with demand, eliminating the need for always-on infrastructure and reducing costs for developers and infra providers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open Infrastructure and DePIN Potential
&lt;/h3&gt;

&lt;p&gt;Anyone can run Ephemeral Rollup environments and earn fees for providing compute. This creates opportunities for decentralized infrastructure networks to emerge, supporting real-time applications and being rewarded for their contributions [11].&lt;/p&gt;

&lt;p&gt;Overall, Ephemeral Rollups give developers the best of both worlds: real-time performance with no compromises on the security, state integrity, or composability that make Solana powerful for on-chain applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases Supercharged by Ephemeral Rollups
&lt;/h2&gt;

&lt;p&gt;Ephemeral Rollups make it possible to build decentralized applications that require high-speed, low-latency execution without relying on centralized infrastructure. By enabling sub-50 millisecond transaction processing with minimal or no fees, MagicBlock opens the door to real-time use cases across several industries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gaming
&lt;/h3&gt;

&lt;p&gt;Games can now run with 10 millisecond block times, allowing players to move, interact, and compete in real-time. Game state updates instantly within the rollup, while assets and logic remain secured on Solana. A working example is &lt;a href="https://github.com/magicblock-labs/solana-generals" rel="noopener noreferrer"&gt;Solana-Generals&lt;/a&gt; [12], a multiplayer strategy game powered by Ephemeral Rollups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Financial Services
&lt;/h3&gt;

&lt;p&gt;MagicBlock enables real-time settlement, live price discovery, and automated trade execution without off-chain oracles. This allows developers to build DeFi protocols with transparent logic and faster execution than what is possible on most L1 or L2 networks. The &lt;a href="https://github.com/magicblock-labs/real-time-pricing-oracle" rel="noopener noreferrer"&gt;Real-Time Pricing Oracle&lt;/a&gt; [13] offers an example of how to build latency-sensitive financial tools on Solana using Ephemeral Rollups.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI and Automation
&lt;/h3&gt;

&lt;p&gt;On-chain AI agents and automation tools can benefit from fast, event-driven execution. Ephemeral Rollups provide the responsiveness needed for real-time inference and decision-making, allowing AI to interact directly with the live blockchain state. Developers can start with templates like &lt;a href="https://github.com/GabrielePicco/super-smart-contracts" rel="noopener noreferrer"&gt;Super Smart Contracts&lt;/a&gt; [14] to create smart contracts enhanced by AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payments and Microtransactions
&lt;/h3&gt;

&lt;p&gt;Ephemeral Rollups support instant, programmable transfers with very low overhead. This makes them ideal for subscriptions, pay-per-use models, or global remittances. MagicBlock's &lt;a href="https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/dummy-token-transfer" rel="noopener noreferrer"&gt;On-Chain Payments Demo&lt;/a&gt; [15] shows a token transfer that can delegate and execute both on-chain and in the Ephemeral Rollup.&lt;/p&gt;

&lt;h3&gt;
  
  
  DePIN and IoT
&lt;/h3&gt;

&lt;p&gt;Real-world infrastructure networks need fast coordination. Ephemeral Rollups offer sub-50 millisecond state updates and horizontal scaling for sensor networks, smart devices, and DePIN protocols [11].&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%2Fqce9v9t867in8skx4lrm.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%2Fqce9v9t867in8skx4lrm.png" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure: Ephemeral Rollup Activity on Solana&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This dashboard from Dune Analytics tracks real-time usage of MagicBlock’s Ephemeral Rollups, including daily delegations and unique users. The upward trend highlights increasing developer adoption and real-world engagement.&lt;br&gt;&lt;br&gt;
Source: MagicBlock, &lt;a href="https://dune.com/magicblock/ephemeral-rollups" rel="noopener noreferrer"&gt;Dune Analytics&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Performance Without Fragmentation Matters
&lt;/h2&gt;

&lt;p&gt;Many scaling solutions improve performance by creating separate environments. Layer 2 rollups, sidechains, and app-specific chains often rely on duplicating infrastructure, deploying new chains, or fragmenting the state of the network [3][4][5][6][7][8]. While these strategies can increase throughput, they make composability harder and add complexity for developers and users.&lt;/p&gt;

&lt;p&gt;MagicBlock takes a different approach. Instead of building a separate chain or relying on trust bridges, it improves Solana directly. Ephemeral Rollups run as part of the Solana runtime with programs, assets, and accounts remaining on the mainnet, and composability is preserved across the entire network [10][11].&lt;/p&gt;

&lt;p&gt;By preserving a single, global state, MagicBlock lets developers scale their applications without losing the benefits of shared infrastructure. Real-time performance and low-cost execution are achieved without isolating users or creating new trust assumptions [10][11].&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future: Composable, Real-Time On-Chain Worlds
&lt;/h2&gt;

&lt;p&gt;As blockchain performance improves, entirely new categories of applications become possible. Autonomous worlds, AI-native agents, real-time multiplayer games, and reactive financial systems can all exist fully on-chain without sacrificing user experience.&lt;/p&gt;

&lt;p&gt;Ephemeral Rollups remove the traditional bottlenecks. Applications can respond in milliseconds, scale dynamically, and remain composable with the broader ecosystem. There is no need to compromise between speed and connectivity.&lt;/p&gt;

&lt;p&gt;MagicBlock makes this a reality by providing real-time execution within Solana’s existing environment. It brings the performance of Web2 to decentralized apps, allowing them to feel fast, interactive, and seamless. For developers, this unlocks new creative and economic possibilities.&lt;/p&gt;

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

&lt;p&gt;Ephemeral Rollups mark a new chapter in blockchain performance. Rather than fragmenting the network or adding layers of complexity, MagicBlock enhances Solana with real-time, composable execution environments. Developers can now build applications that are fast, scalable, and deeply integrated with the rest of the ecosystem.&lt;/p&gt;

&lt;p&gt;By supporting low-latency execution, horizontal scaling, and gasless interactions, Ephemeral Rollups remove the bottlenecks that have long held back decentralized applications. Use cases like real-time games, AI agents, financial automation, and IoT coordination can finally live fully on-chain without compromising on speed or user experience.&lt;/p&gt;

&lt;p&gt;MagicBlock proves that performance and composability no longer need to be trade-offs. Real-time dApps are not just possible, they are the future of blockchain-native applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] Nervos Knowledge Base. “What is Block Time in Blockchain? A Complete Guide”. &lt;a href="https://www.nervos.org/knowledge-base/block_time_in_blockchain_(explainCKBot)" rel="noopener noreferrer"&gt;https://www.nervos.org/knowledge-base/block_time_in_blockchain_(explainCKBot)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] Prachi Pandey. “Solana (SOL) Transaction Fees, Speeds, and Limits: Everything You Need to Know”. &lt;a href="https://fuze.finance/blog/solana-transaction-fees-speeds-and-limits/" rel="noopener noreferrer"&gt;https://fuze.finance/blog/solana-transaction-fees-speeds-and-limits/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] Gemini Cryptopedia. “Blockchain Scalability and Privacy: The Rollup Ecosystem”. &lt;a href="https://www.gemini.com/cryptopedia/layer-2-scaling-zk-rollup-optimistic-rollup-ethereum" rel="noopener noreferrer"&gt;https://www.gemini.com/cryptopedia/layer-2-scaling-zk-rollup-optimistic-rollup-ethereum&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] Coinbase Learn. “What is an application-specific blockchain (AppChain)?”. &lt;a href="https://www.coinbase.com/learn/crypto-glossary/what-is-an-application-specific-blockchain-appchain" rel="noopener noreferrer"&gt;https://www.coinbase.com/learn/crypto-glossary/what-is-an-application-specific-blockchain-appchain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] Coinbase Learn. “What are Layer 3 blockchains and what is the difference with Layer 2 blockchains?”. &lt;a href="https://www.coinbase.com/learn/crypto-glossary/what-are-layer-3-blockchains-and-what-is-the-difference-with-layer-2-blockchains" rel="noopener noreferrer"&gt;https://www.coinbase.com/learn/crypto-glossary/what-are-layer-3-blockchains-and-what-is-the-difference-with-layer-2-blockchains&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] Bitpanda Academy. “What is Sharding?”. &lt;a href="https://www.bitpanda.com/academy/en/lessons/what-is-sharding/" rel="noopener noreferrer"&gt;https://www.bitpanda.com/academy/en/lessons/what-is-sharding/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] Wikipedia. ”Blockchain”. &lt;a href="https://en.wikipedia.org/wiki/Blockchain" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Blockchain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[8] Ledger Academy. “State Channels Meaning”. &lt;a href="https://www.ledger.com/academy/glossary/state-channels" rel="noopener noreferrer"&gt;https://www.ledger.com/academy/glossary/state-channels&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[9] Merriam-Webster. “Ephemeral”. &lt;a href="https://www.merriam-webster.com/dictionary/ephemeral" rel="noopener noreferrer"&gt;https://www.merriam-webster.com/dictionary/ephemeral&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[10] Gabriele Picco and Andrea Fortugno. ”Ephemeral Rollups are All You Need”. arXiv:2311.02650 [cs.DC]. &lt;a href="https://arxiv.org/abs/2311.02650" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2311.02650&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[11] MagicBlock. “MagicBlock Documentation”. &lt;a href="https://docs.magicblock.gg/" rel="noopener noreferrer"&gt;https://docs.magicblock.gg/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[12] MagicBlock. “Solana-Generals”. &lt;a href="https://github.com/magicblock-labs/solana-generals" rel="noopener noreferrer"&gt;https://github.com/magicblock-labs/solana-generals&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[13] MagicBlock. “Real-Time Pricing Oracle”. &lt;a href="https://github.com/magicblock-labs/real-time-pricing-oracle" rel="noopener noreferrer"&gt;https://github.com/magicblock-labs/real-time-pricing-oracle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[14] Gabriele Picco. “Super Smart Contracts”. &lt;a href="https://github.com/GabrielePicco/super-smart-contracts" rel="noopener noreferrer"&gt;https://github.com/GabrielePicco/super-smart-contracts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[15] MagicBlock. “Dummy Token Transfer”. &lt;a href="https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/dummy-token-transfer" rel="noopener noreferrer"&gt;https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/dummy-token-transfer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>solana</category>
      <category>research</category>
      <category>web3</category>
    </item>
    <item>
      <title>Raising Block Limits on Solana: SIMD-0250 and Its Economic Effects</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Fri, 09 May 2025 06:51:57 +0000</pubDate>
      <link>https://dev.to/lordghostx/raising-block-limits-on-solana-simd-0250-and-its-economic-effects-ade</link>
      <guid>https://dev.to/lordghostx/raising-block-limits-on-solana-simd-0250-and-its-economic-effects-ade</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0250-raise-block-limits-to-60M.md" rel="noopener noreferrer"&gt;SIMD-0250&lt;/a&gt;, a Solana Improvement Document (SIMD), proposes raising the network’s maximum block Compute Units (CUs) to 60 million. It builds on &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0207-raise-block-limits-to-50M.md" rel="noopener noreferrer"&gt;SIMD-0207&lt;/a&gt;, which proposes to raise the limit from 48 million to 50 million. The only change made in both proposals is to the &lt;strong&gt;Max Block Units&lt;/strong&gt;. Other limits, like &lt;strong&gt;Max Writable Account Units&lt;/strong&gt;, &lt;strong&gt;Max Vote Units&lt;/strong&gt;, and &lt;strong&gt;Max Block Accounts Data Size Delta&lt;/strong&gt;, stay the same. This means more room for non-vote transactions, which helps boost total transaction throughput.&lt;/p&gt;

&lt;p&gt;With more space in each block, the network can process more transactions per second. This helps reduce congestion and lowers the need for users to outbid each other on fees, especially during periods of high demand. For apps handling a high volume of transactions or those with small dollar values (like games or microtransactions), this kind of fee relief is a big deal. &lt;a href="https://messari.io/report/state-of-solana-q3-2023" rel="noopener noreferrer"&gt;Messari’s State of Solana Q3 2023&lt;/a&gt; report pointed to low fees and fast confirmations as major drivers of growth in consumer-facing use cases like gaming, DePIN, and social platforms.&lt;/p&gt;

&lt;p&gt;For validators, this change comes with trade-offs. While it can increase fee earnings, it also raises hardware demands. Over time, this could raise the bar for running a validator and limit participation to better-resourced operators. This concern is not new. The &lt;a href="https://solana.com/news/validator-health-report-march-2023" rel="noopener noreferrer"&gt;Solana Foundation’s March 2023 Validator Health Report&lt;/a&gt; already emphasized that validator performance and resilience will need to scale alongside network growth.&lt;/p&gt;

&lt;p&gt;Developers, on the other hand, stand to gain from the extra compute available. Apps that rely on batching transactions or updating on-chain state in real-time, like DeFi order books, multiplayer games, or NFT platforms, can run more smoothly. The larger block size also gives the network better breathing room during traffic spikes, helping avoid lags or dropped transactions when demand rises.&lt;/p&gt;

&lt;p&gt;Still, there are risks. Larger blocks may take longer to execute and propagate across the network, placing extra load on RPC nodes, explorers, and indexers. If these systems are not updated to handle the new block size, they might lag or fail to keep up. The change is backward-compatible, but outdated nodes could reject the new, larger blocks entirely.&lt;/p&gt;

&lt;p&gt;In summary, &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0250-raise-block-limits-to-60M.md" rel="noopener noreferrer"&gt;SIMD-0250&lt;/a&gt; makes a relatively simple change with wide-ranging effects. It expands Solana’s ability to handle more activity, improve app performance, and stabilize fees, but it adds more pressure on infrastructure and validators. Like many scalability upgrades, its success depends on how well the ecosystem keeps up and whether that added capacity translates into meaningful new use.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SIMD-0207: Raise the Block Limit to 50M CUs. Retrieved from &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0207-raise-block-limits-to-50M.md" rel="noopener noreferrer"&gt;https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0207-raise-block-limits-to-50M.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SIMD-0250: Increase Block Limit to 60M CUs. Retrieved from &lt;a href="https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0250-raise-block-limits-to-60M.md" rel="noopener noreferrer"&gt;https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0250-raise-block-limits-to-60M.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Messari’s State of Solana Q3 2023. Retrieved from &lt;a href="https://messari.io/report/state-of-solana-q3-2023" rel="noopener noreferrer"&gt;https://messari.io/report/state-of-solana-q3-2023&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Solana Foundation Validator Health Report: March 2023. Retrieved from &lt;a href="https://solana.com/news/validator-health-report-march-2023" rel="noopener noreferrer"&gt;https://solana.com/news/validator-health-report-march-2023&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blockchain</category>
      <category>solana</category>
      <category>research</category>
      <category>web3</category>
    </item>
    <item>
      <title>Decentralizing Starknet: Architecture, Plans, and MEV Impact</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Wed, 11 Sep 2024 05:32:46 +0000</pubDate>
      <link>https://dev.to/lordghostx/decentralizing-starknet-architecture-plans-and-mev-impact-7ck</link>
      <guid>https://dev.to/lordghostx/decentralizing-starknet-architecture-plans-and-mev-impact-7ck</guid>
      <description>&lt;p&gt;Starknet is an Ethereum Layer 2 (L2) that leverages Zero-Knowledge (ZK) technology to deliver high transaction throughput and low costs while maintaining Ethereum's core principles. However, its reliance on a centralized sequencer for transaction processing introduces vulnerabilities such as single points of failure and scalability bottlenecks.&lt;/p&gt;

&lt;p&gt;This article explores Starknet's current centralized architecture, the network's plan toward decentralization, the motivations driving this transition, and how these changes could reshape the future of the blockchain ecosystem, including the dynamics of &lt;a href="https://dev.to/lordghostx/introduction-to-mev-on-starknet-1o0l"&gt;MEV (Maximal Extractable Value)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Starknet's early success can be attributed to its centralized architecture, which facilitated rapid development. However, as the network scales, this centralization poses significant risks, including single points of failure and constraints on scalability.&lt;/p&gt;

&lt;p&gt;Transitioning to a decentralized model is necessary to overcome these limitations and improve security through distributed control, enhance censorship resistance, and ensure long-term sustainability. This shift represents more than just a technical upgrade; it is pivotal for Starknet's continued growth and resilience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.starknet.io/blog/starknet-decentralization-a-roadmap-in-broad-strokes/" rel="noopener noreferrer"&gt;Starknet's move toward decentralization&lt;/a&gt; will set a new benchmark in the blockchain space, inspiring other networks to adopt similar models. This evolution can potentially strengthen the resilience and openness of the entire ecosystem.&lt;/p&gt;

&lt;p&gt;Starknet's strategic plan, as detailed in its &lt;a href="https://community.starknet.io/t/starknet-decentralized-protocol-i-introduction/2671" rel="noopener noreferrer"&gt;introduction&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=GAPU22K0YhY" rel="noopener noreferrer"&gt;presentations&lt;/a&gt;, outlines a gradual transition to decentralization, involving the distribution of control to independent nodes and the implementation of community-driven governance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starknet Sequencer
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-architecture-overview/#sequencers" rel="noopener noreferrer"&gt;Starknet sequencer&lt;/a&gt; is a specialized entity responsible for ordering and processing transactions before they are verified and submitted to Ethereum. Here's how it functions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Ordering&lt;/strong&gt;: The sequencer gathers and organizes incoming transactions in a specific order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution&lt;/strong&gt;: Once ordered, the sequencer executes these transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batching&lt;/strong&gt;: After execution, the sequencer groups multiple transactions into a batch, known as a &lt;code&gt;rollup&lt;/code&gt; for efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block Production&lt;/strong&gt;: The sequencer then produces blocks that contain these processed transaction batches.&lt;/li&gt;
&lt;/ol&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%2Ffzufikxx2v3hk5ka4x97.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%2Ffzufikxx2v3hk5ka4x97.png" alt="Starknet Transaction Flow" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond ordering transactions, the sequencer is also responsible for maintaining the network's liveness. It ensures that the network continues to process transactions and produce new blocks, keeping Starknet responsive and operational.&lt;/p&gt;

&lt;p&gt;However, the centralization of sequencers introduces potential vulnerabilities, such as censorship, where a sequencer might choose to exclude certain transactions, and security risks, where a single point of failure could jeopardize the entire network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decentralization Plans
&lt;/h2&gt;

&lt;p&gt;The following initiatives highlight the steps Starknet is taking to distribute control, minimize vulnerabilities, and strengthen its infrastructure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Community-run sequencers&lt;/strong&gt;: To mitigate the risks of centralized sequencers, Starknet plans to decentralize this role by enabling community-run sequencers. This will distribute power and responsibility across multiple entities, reducing the influence of any single sequencer and enhancing the system's overall resilience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decentralized transaction ordering&lt;/strong&gt;: By decentralizing the transaction ordering process, Starknet aims to prevent any single entity from controlling the sequence of transactions. This ensures a more transparent and equitable process, strengthens network security, and boosts participant trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved security and censorship resistance&lt;/strong&gt;: Deploying multiple sequencers will significantly enhance network security by reducing the risk of censorship and malicious activities. A decentralized sequencer network makes it far more difficult for any single actor to undermine Starknet's integrity, reinforcing its commitment to security and censorship resistance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Due to its proven reliability and robustness, Tendermint has been proposed as a strong candidate for Starknet's &lt;a href="https://community.starknet.io/t/tendermint-for-starknet/98248" rel="noopener noreferrer"&gt;initial consensus mechanism&lt;/a&gt; in its decentralization efforts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tendermint
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tendermint.com/core/" rel="noopener noreferrer"&gt;Tendermint&lt;/a&gt; is a Byzantine Fault Tolerant (BFT) consensus protocol used for securing decentralized networks. It allows a network of validators to agree on the next block in a blockchain, even if some validators are malicious, ensuring high reliability and security.&lt;/p&gt;

&lt;p&gt;The protocol assumes there are &lt;strong&gt;N = 3f + 1&lt;/strong&gt; validators, where &lt;strong&gt;f&lt;/strong&gt; represents the number of potentially malicious (Byzantine) validators. Tendermint operates in two key dimensions: &lt;strong&gt;height&lt;/strong&gt; (the current block) and &lt;strong&gt;round&lt;/strong&gt; (the iterative process to reach consensus). Multiple rounds may be required for each block height, with a single leader or proposer selected per round. This structured approach ensures validators can securely and efficiently agree on the next block while maintaining decentralization and resilience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consensus Process
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Propose&lt;/strong&gt;: In the initial phase, a validator is chosen to propose a new block, typically through a round-robin selection, to ensure fair and systematic rotation among validators. This step starts the consensus process by submitting a candidate block for consideration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prevote&lt;/strong&gt;: After the block is proposed, validators cast their initial votes on whether to accept it. The &lt;code&gt;prevote&lt;/code&gt; phase helps gauge initial support but does not finalize the block. It serves as an early signal of consensus among validators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precommit&lt;/strong&gt;: If a supermajority (usually two-thirds) of validators &lt;code&gt;prevote&lt;/code&gt; in favor of the block, the process moves to the &lt;code&gt;precommit&lt;/code&gt; stage. This stronger agreement shows a more definitive step towards finalizing the block, though it is not yet final.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit&lt;/strong&gt;: In the final phase, if a supermajority of &lt;code&gt;precommits&lt;/code&gt; is reached, the block is committed to the blockchain. This step makes the block final and irreversible, securing it as a permanent part of the blockchain's history. The &lt;code&gt;commit&lt;/code&gt; phase concludes the Tendermint consensus process, ensuring complete agreement among validators on the block.&lt;/li&gt;
&lt;/ul&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%2F8yiyk7qlefyn8bb0ae83.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%2F8yiyk7qlefyn8bb0ae83.png" alt="Tendermint Consensus Process" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Starknet ProofChain
&lt;/h2&gt;

&lt;p&gt;Starknet proposes using the Tendermint protocol with an innovative &lt;a href="https://community.starknet.io/t/starknet-decentralized-protocol-vii-chained-proof-protocols-braiding/18831" rel="noopener noreferrer"&gt;ProofChain&lt;/a&gt; approach. This divides blocks into &lt;strong&gt;K&lt;/strong&gt; proofchains based on height, where &lt;strong&gt;ProofChain(H) = H mod K&lt;/strong&gt;. Each block contains proofs for the latest non-empty block and any empty blocks in its chain, improving security, scalability, and efficiency.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before diving into ProofChains, it's important to understand the two types of blocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blocks containing transactions&lt;/strong&gt; (depicted in green) must include a proof to be valid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Empty blocks&lt;/strong&gt; (depicted in red) contain no transactions and no proof.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&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%2Flwwvpomlxxwzow1v0ree.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%2Flwwvpomlxxwzow1v0ree.png" alt="ProofChain" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are the key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blocks divided into K ProofChains&lt;/strong&gt;: This structure allows parallel processing and verification, improving scalability by allowing multiple proofchains to be processed simultaneously.&lt;/li&gt;
&lt;/ul&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%2F1rmf7l6kxlnlyhwh40yt.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%2F1rmf7l6kxlnlyhwh40yt.png" alt="Dividing ProofChains" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Each block contains proofs for previous blocks&lt;/strong&gt;: Every block includes cryptographic proofs for the preceding blocks, creating a robust verification chain. This ensures that the validity of each block is anchored in earlier blocks, securing the blockchain’s integrity.&lt;/li&gt;
&lt;/ul&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%2F7xzajun77xm8ko3w1jm1.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%2F7xzajun77xm8ko3w1jm1.png" alt="ProofChain Proofs" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced security&lt;/strong&gt;: The braided ProofChain structure makes it significantly harder for an attacker to alter the blockchain's history. Recursive proofs, which include transaction execution and prior block verification, further reinforce network security.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved block verification efficiency&lt;/strong&gt;: By organizing proofs into different chains, the process of verifying new blocks is streamlined, reducing computational demands. This speeds up the consensus process, especially in larger networks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The zero-knowledge proof (ZKP) required for the L1 state update can be efficiently constructed by folding &lt;strong&gt;K ZKPs&lt;/strong&gt; (one from each ProofChain).&lt;/p&gt;
&lt;/blockquote&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%2Fu23kpuxp5tlcd7xgyldf.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%2Fu23kpuxp5tlcd7xgyldf.png" alt="ProofChain Efficiency" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, &lt;strong&gt;Block 12&lt;/strong&gt; must include a recursive proof that verifies the execution of transactions proof in &lt;strong&gt;Block 3&lt;/strong&gt; and also validates the empty blocks &lt;strong&gt;6&lt;/strong&gt; and &lt;strong&gt;9&lt;/strong&gt;.&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%2Fahfue42dl0luto5cfu9l.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%2Fahfue42dl0luto5cfu9l.png" alt="ProofChain Demo" width="800" height="107"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Decentralization Challenges
&lt;/h2&gt;

&lt;p&gt;By distributing the proposing, voting, and committing roles across many validators, Starknet reduces centralization risks while enhancing security and reliability. With its checks and balances, Tendermint's structured consensus process ensures that Starknet remains decentralized and trustless, which is essential for its long-term success and scalability.&lt;/p&gt;

&lt;p&gt;However, there are several challenges to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Network Latency&lt;/strong&gt;: Delays in the message (vote) delivery can cause timeouts and slow down the consensus process, impacting network performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Overhead&lt;/strong&gt;: Tendermint &lt;strong&gt;O(n²)&lt;/strong&gt; message overhead increases with more validators, potentially reducing consensus efficiency as the network scales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed Constraints&lt;/strong&gt;: The slowest validator limits the process, creating a bottleneck and vulnerability to delays as the validator count grows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Starknet Staking
&lt;/h2&gt;

&lt;p&gt;Starknet is introducing STRK staking in Q4 2024 to boost decentralization and secure the network, becoming the first Layer 2 to enable such a mechanism. In this initial phase, neither StarkWare nor the Starknet Foundation will participate in staking, making them ineligible for staking rewards. Additionally, all locked tokens will not be eligible for staking during this phase.&lt;/p&gt;

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

&lt;p&gt;See the &lt;a href="https://community.starknet.io/t/snip-18-staking-s-first-stage-on-starknet/114334" rel="noopener noreferrer"&gt;SNIP 18: Staking's First Stage on Starknet&lt;/a&gt; proposal for more details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Network Rewards
&lt;/h2&gt;

&lt;p&gt;Incentives will be essential for maintaining Starknet's security as it decentralizes. It will motivate participants to stake tokens and act in the network's best interest. This ensures long-term sustainability and attracts a diverse set of validators. The potential reward types include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Fees:&lt;/strong&gt; Validators may earn a share of fees for processing transactions, aligning their incentives with network growth and usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block Rewards:&lt;/strong&gt; Validators could receive newly minted tokens for proposing and validating blocks, providing a consistent base reward for their participation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proof Rewards:&lt;/strong&gt; Unique to Starknet, validators might be rewarded for generating and verifying cryptographic proofs, which is essential for maintaining the network's zero-knowledge proof system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MEV (Maximal Extractable Value):&lt;/strong&gt; Validators can earn additional revenue by optimizing the transaction order within blocks. While profitable, it requires careful management to ensure fairness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staking Rewards:&lt;/strong&gt; Participants who stake tokens to secure the network may earn rewards, encouraging long-term commitment and a healthy distribution of staked tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Decentralization Impact on MEV
&lt;/h2&gt;

&lt;p&gt;Decentralization tends to reduce the potential for extractive MEV (Maximal Extractable Value) by distributing power across a wider array of participants, reducing the chance of any single entity exploiting transaction ordering. However, it can also increase competition among validators, driving the emergence of more advanced and decentralized MEV strategies. Here are some predictions for the MEV landscape when Starknet becomes decentralized:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;More equitable distribution of MEV opportunities&lt;/strong&gt;: As sequencing becomes decentralized, MEV capture will be more evenly distributed among participants, reducing concentration in the hands of a single entity and promoting fairer access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Innovation in transparent MEV strategies&lt;/strong&gt;: Decentralization is likely to drive the development of new MEV strategies that are more transparent and equitable, enabling a level playing field for all participants.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Potential reduction in overall MEV:&lt;/strong&gt; Increased competition due to broader accessibility may decrease the total extractable MEV as more participants compete for the same opportunities, driving down the overall value that can be captured.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emergence of specialized MEV extraction protocols&lt;/strong&gt;: The decentralized environment could lead to the rise of advanced tools and protocols designed for MEV extraction and a more distributed and competitive network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration of MEV-resistant mechanisms&lt;/strong&gt;: Starknet and similar platforms may adopt protocol-level features to mitigate MEV exploitation, promoting greater fairness and stability within the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shift towards community-oriented MEV distribution&lt;/strong&gt;: We may see a move towards models where MEV is distributed more equitably among network participants, potentially through community-driven MEV auctions or collective action mechanisms, reducing monopolization by a select few.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Starknet's transition to decentralization will significantly improve the network's security, scalability, and fairness. By decentralizing the sequencer role and implementing the Tendermint consensus protocol and ProofChain, Starknet aims to overcome centralization risks while preserving a trustless and resilient ecosystem.&lt;/p&gt;

&lt;p&gt;If you're interested in diving deeper into MEV on Starknet, check out my previous posts: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/lordghostx/introduction-to-mev-on-starknet-1o0l"&gt;Introduction to MEV on Starknet&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lordghostx/starknet-protocols-key-features-and-mev-opportunities-574i"&gt;Starknet Protocols: Key Features and MEV Opportunities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lordghostx/queries-to-insights-visualizing-starknet-data-with-dune-j8p"&gt;Queries to Insights: Visualizing Starknet Data with Dune&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lordghostx/data-to-queries-exploring-starknet-data-with-dune-ihd"&gt;Data to Queries: Exploring Starknet Data with Dune&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lordghostx/understanding-starknet-data-with-dune-dashboards-17je"&gt;Understanding Starknet Data with Dune Dashboards&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For additional resources on Starknet MEV, explore the comprehensive materials available here: &lt;a href="https://github.com/Icedcool/StarknetMEV/" rel="noopener noreferrer"&gt;https://github.com/Icedcool/StarknetMEV/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to discuss MEV on Starknet or have valuable insights to share, join our &lt;a href="https://t.me/+TiNIOKAdIyQzNDg0" rel="noopener noreferrer"&gt;MEV discussion group&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>starknet</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>mev</category>
    </item>
    <item>
      <title>Understanding Starknet Data with Dune Dashboards</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Tue, 27 Aug 2024 04:09:11 +0000</pubDate>
      <link>https://dev.to/lordghostx/understanding-starknet-data-with-dune-dashboards-17je</link>
      <guid>https://dev.to/lordghostx/understanding-starknet-data-with-dune-dashboards-17je</guid>
      <description>&lt;p&gt;In my previous posts, &lt;a href="https://dev.to/lordghostx/data-to-queries-exploring-starknet-data-with-dune-ihd"&gt;Data to Queries: Exploring Starknet Data with Dune&lt;/a&gt; and &lt;a href="https://dev.to/lordghostx/queries-to-insights-visualizing-starknet-data-with-dune-j8p"&gt;Queries to Insights: Visualizing Starknet Data with Dune&lt;/a&gt;, I walked you through accessing Starknet's raw data on Dune, writing SQL queries to extract that data, and visualizing it through dashboards.&lt;/p&gt;

&lt;p&gt;Now, let's dive deeper into understanding and interpreting the data in existing Starknet dashboards. This will help you gain meaningful insights from the visualizations, make informed decisions, and fully leverage the value of the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring Starknet Dashboards
&lt;/h2&gt;

&lt;p&gt;Here are a few dashboards on the &lt;a href="https://dune.com/caravanserai" rel="noopener noreferrer"&gt;Caravanserai page&lt;/a&gt; that you might find interesting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dune.com/caravanserai/starknet-overview" rel="noopener noreferrer"&gt;Starknet Overview&lt;/a&gt;: Provides a comprehensive view of key metrics like transaction volumes, active addresses, and contract deployments.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dune.com/caravanserai/starknet-dexs" rel="noopener noreferrer"&gt;Starknet DEXs&lt;/a&gt;: Provides detailed insights into liquidity flows, daily swap volumes, and market sentiment across various decentralized exchanges.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dune.com/caravanserai/starknet-arbitrage-tracker" rel="noopener noreferrer"&gt;Starknet Arbitrage Tracker&lt;/a&gt;: Tracks real-time arbitrage opportunities by monitoring price discrepancies and potential profits within specific blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dune.com/caravanserai/starknet-dex-analytics" rel="noopener noreferrer"&gt;Starknet DEX Analytics&lt;/a&gt;: Analyzes liquidity distribution, swap activities, and identifies market trends and whale movements.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dune.com/caravanserai/starknet-mev" rel="noopener noreferrer"&gt;Starknet MEV&lt;/a&gt;: Focuses on monitoring and analyzing Maximal Extractable Value (MEV) within Starknet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Starknet Overview Dashboard
&lt;/h2&gt;

&lt;p&gt;Let's start with the &lt;a href="https://dune.com/caravanserai/starknet-overview" rel="noopener noreferrer"&gt;Starknet Overview&lt;/a&gt; dashboard and understand its key metrics.&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%2Fz79s44mymgv3m2hilf7q.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%2Fz79s44mymgv3m2hilf7q.png" alt="Starknet Overview" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-overview#strk-price" rel="noopener noreferrer"&gt;Strk Price&lt;/a&gt; section shows the price trends of Starknet's STRK token over time, comparing it with Ethereum (ETH). This comparison helps you assess STRK's performance in relation to ETH.&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%2Fd70u9rm4mcute2r4g20j.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%2Fd70u9rm4mcute2r4g20j.png" alt="STRK Price Section" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-overview#blocks" rel="noopener noreferrer"&gt;Blocks&lt;/a&gt; section provides insight into network activity, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Average Daily Created Blocks&lt;/strong&gt;: The average number of blocks created daily indicates the network's activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average Daily Transactions per Block&lt;/strong&gt;: Tracks the average number of transactions per block, showing how busy the network is and how much each block is used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average Block Creation Time&lt;/strong&gt;: Shows how long it usually takes to make a block, helping you see if the network is running faster or slower.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocks, Average Block Creation Time, and Transactions per Block Over Time&lt;/strong&gt;: A historical view of how many blocks were made, how long they took, and how many transactions were in each block so you can spot trends and changes over time.&lt;/li&gt;
&lt;/ul&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%2Fa146jv6pvsxnlpme1rfd.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%2Fa146jv6pvsxnlpme1rfd.png" alt="Blocks Section" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-overview#transactions" rel="noopener noreferrer"&gt;Transactions&lt;/a&gt; section provides insights into network transaction activity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Count and TPS Over Time&lt;/strong&gt;: Tracks the total number of transactions and the transactions per second (TPS) over time, giving insight into the network's activity and performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average Daily Transaction Count&lt;/strong&gt;: The average number of daily transactions, reflecting the network's regular usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average TPS&lt;/strong&gt;: Displays the average transactions per second, highlighting the network's speed and efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Share L1 vs L2 Accepted Transactions&lt;/strong&gt;: Compares the daily distribution of transactions accepted on Layer 1 (L1) vs Layer 2 (L2), showing where most activity occurs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Share of Blob vs Call Data Transactions&lt;/strong&gt;: This chart breaks down the daily transactions into blob data and call data types, providing insight into the nature of the transactions being processed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Reversion Rate and Number of Successful and Reverted Transactions Over Time&lt;/strong&gt;: Monitors the rate at which transactions are reverted and compares successful vs. reverted transactions over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average Transactions per User&lt;/strong&gt;: The average number of transactions each user makes indicates user engagement and activity levels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Number of Transactions by User Type&lt;/strong&gt;: Categorizes and counts transactions by different users, providing insight into how various user groups interact with the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Share of Reverted Transactions by User Type&lt;/strong&gt;: Analyzes which types of users are most likely to have transactions reverted, offering a deeper understanding of transaction reliability by user category.&lt;/li&gt;
&lt;/ul&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%2Fnbmsx0rqejzv5jtnpq7s.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%2Fnbmsx0rqejzv5jtnpq7s.png" alt="Transaction section" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-overview#users" rel="noopener noreferrer"&gt;Users&lt;/a&gt; section focuses on user engagement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Number of Active and New Addresses Over Time&lt;/strong&gt;: Tracks the number of active users and new addresses created over time, showing growth and engagement trends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total Users&lt;/strong&gt;: Displays the total number of unique users on the network, giving a sense of the overall user base size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average Daily Active Users&lt;/strong&gt;: The average number of users actively engaging with the network daily, reflecting consistent user activity and network usage.&lt;/li&gt;
&lt;/ul&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%2Fm6p8ec8qp4w9horzz2do.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%2Fm6p8ec8qp4w9horzz2do.png" alt="Users section" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-overview#fees" rel="noopener noreferrer"&gt;Fees&lt;/a&gt; section analyzes transaction costs on the network:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total Paid Fees and Average Fee per Transaction Over Time&lt;/strong&gt;: Tracks the total fees paid and the average fee per transaction over time, giving insights into cost trends and network demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total Paid Fees&lt;/strong&gt;: The cumulative fees paid on the network reflect how cheap or expensive it is to use Starknet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average Fee per Transaction&lt;/strong&gt;: Displays the average fee users pay per transaction, helping you understand the cost efficiency of transactions over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Starknet DEXs Dashboard
&lt;/h2&gt;

&lt;p&gt;Let's explore data on Starknet's decentralized exchanges using the &lt;a href="https://dune.com/caravanserai/starknet-dexs" rel="noopener noreferrer"&gt;Starknet DEXs&lt;/a&gt; dashboard.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-dexs#overview" rel="noopener noreferrer"&gt;Overview&lt;/a&gt; section provides a snapshot of DEX activity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Average Daily Volume&lt;/strong&gt;: This shows the average daily trading volume on Starknet DEXs, indicating overall market activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average Daily Swaps&lt;/strong&gt;: Tracks the average number of swaps executed daily, reflecting the frequency of trades on the platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average Daily Swappers&lt;/strong&gt;: Displays the average number of unique users making swaps daily, highlighting user engagement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Volume of Swaps, Number of Swaps, and Number of Swappers&lt;/strong&gt;: Offers a detailed view of daily trading volume, swap counts, and the number of active users, helping you track trends over time.&lt;/li&gt;
&lt;/ul&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%2Fd02oz2t3i1oldgqbyyvj.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%2Fd02oz2t3i1oldgqbyyvj.png" alt="Overview Section" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-dexs#dexs" rel="noopener noreferrer"&gt;DEXs&lt;/a&gt; section details activity across different DEXs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Daily Swapped Volume by DEX&lt;/strong&gt;: Displays the total trading volume on each DEX per day, showing where most trading activity is occurring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Share of Volume by DEX&lt;/strong&gt;: Breaks down the percentage of the total daily volume attributed to each DEX, highlighting the market share of each platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Number of Swaps by DEX&lt;/strong&gt;: Tracks the daily number of swaps executed on each DEX, indicating how frequently trades happen across different exchanges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Share of Swaps by DEX&lt;/strong&gt;: Shows the proportion of total daily swaps that occur on each DEX, providing insight into which platforms are most active.&lt;/li&gt;
&lt;/ul&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%2F0bwlcwf0ra6udku7qcwj.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%2F0bwlcwf0ra6udku7qcwj.png" alt="DEXs section" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-dexs#tokens" rel="noopener noreferrer"&gt;Tokens&lt;/a&gt; section offers insights into token trading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Daily Volume of Swaps by Token&lt;/strong&gt;: Shows the total trading volume for each token per day, indicating which tokens are being traded the most.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Share of Volume by Token&lt;/strong&gt;: This breaks down the percentage of the total daily trading volume attributed to each token, highlighting different tokens popularity and trading activity.&lt;/li&gt;
&lt;/ul&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%2F4qd63y1u22pj55dxuz90.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%2F4qd63y1u22pj55dxuz90.png" alt="Tokens section" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Starknet MEV Dashboard
&lt;/h2&gt;

&lt;p&gt;Next, let's explore MEV activity on Starknet using the &lt;a href="https://dune.com/caravanserai/starknet-mev" rel="noopener noreferrer"&gt;Starknet MEV&lt;/a&gt; dashboard.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-mev#liquidation-overview" rel="noopener noreferrer"&gt;Liquidation Overview&lt;/a&gt; section offers a comprehensive view of liquidation activities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total Repaid Debts&lt;/strong&gt;: Shows the cumulative amount of debts repaid through liquidations, reflecting the scale of debt resolution on the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total Liquidated Collaterals&lt;/strong&gt;: Displays the total value of collaterals liquidated, giving insight into the assets seized during liquidation events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total Paid Fees&lt;/strong&gt;: Indicates the total fees paid in the process of liquidations, highlighting the cost associated with these transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Number of Liquidations, Liquidators, and Users&lt;/strong&gt;: Tracks the daily count of liquidation events, the participants involved in liquidating assets, and the users affected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Volume of Liquidated Debts, Collaterals, and TX Fees&lt;/strong&gt;: A daily breakdown of the volume of debts liquidated, collaterals seized, and transaction fees incurred, offering a detailed view of the liquidation process over time.&lt;/li&gt;
&lt;/ul&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%2Fdznpi55t93rld44cor5l.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%2Fdznpi55t93rld44cor5l.png" alt="Liquidation Overview Section" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-mev#liquidators" rel="noopener noreferrer"&gt;Liquidators&lt;/a&gt; section provides detailed information about those executing liquidations:&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%2F6uz7n6ztngijh3f1au80.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%2F6uz7n6ztngijh3f1au80.png" alt="Liquidators Section" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-mev#platforms-tokens" rel="noopener noreferrer"&gt;Platforms &amp;amp; Tokens&lt;/a&gt; section breaks down liquidation data by platform and token:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Daily Net Profit and Loss of Liquidators by Platform&lt;/strong&gt;: Tracks the daily net profit and loss of liquidators, categorized by platform, showing which platforms are most profitable or costly for liquidators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share of Debts by Token&lt;/strong&gt;: Displays the proportion of total debts associated with each token, highlighting which tokens are most commonly involved in liquidation events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share of Collaterals by Token&lt;/strong&gt;: This chart shows the distribution of collateral types by token, providing insight into the assets most frequently used as collateral in liquidations.&lt;/li&gt;
&lt;/ul&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%2Fr40ldzozqhguazt59reu.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%2Fr40ldzozqhguazt59reu.png" alt="Platforms &amp;amp; Tokens Section" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dune.com/caravanserai/starknet-mev#liquidation-transactions" rel="noopener noreferrer"&gt;Liquidation Transactions&lt;/a&gt; section provides detailed information on liquidation transactions on Starknet:&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%2Fej1q7blr0lq43b9vcbiz.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%2Fej1q7blr0lq43b9vcbiz.png" alt="Liquidation Transactions" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Analysis with Materialized Tables
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.dune.com/query-engine/materialized-views" rel="noopener noreferrer"&gt;Materialized tables&lt;/a&gt; on Dune store query results for faster analysis or reusing query results in other queries. You can explore these through &lt;a href="https://dune.com/discover/content/relevant?q=author:caravanserai&amp;amp;resource-type=queries" rel="noopener noreferrer"&gt;Caravanserai's public queries&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, you can use the &lt;code&gt;dune.caravanserai.result_starknet_dex_pairs&lt;/code&gt; table to identify the most actively traded pairs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;pair_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;total_volume&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;average_price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;max_price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;MIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;min_price&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;dune&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;caravanserai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result_starknet_dex_pairs&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'1 hour'&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="n"&gt;pair_name&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="n"&gt;total_volume&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or retrieve recent liquidation events using the &lt;code&gt;dune.caravanserai.result_starknet_liquidations&lt;/code&gt; table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;liquidation_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;liquidated_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;liquidation_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;timestamp&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;dune&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;caravanserai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result_starknet_liquidations&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'24 hours'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;DESC&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're new to writing and running queries on Dune, I recommend starting with my article &lt;a href="https://dev.to/lordghostx/data-to-queries-exploring-starknet-data-with-dune-ihd"&gt;Data to Queries: Exploring Starknet Data with Dune&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;In this article, we explored Starknet dashboards and materialized tables on Dune and learned how to interpret them for valuable insights. These dashboards can help you better understand Starknet's operations, optimize strategies, and stay ahead of market trends.&lt;/p&gt;

&lt;p&gt;If you're interested in analyzing Starknet data, finding opportunities in the ecosystem, or sharing valuable insights, join our &lt;a href="https://t.me/+TiNIOKAdIyQzNDg0" rel="noopener noreferrer"&gt;MEV discussion group&lt;/a&gt; to connect with like-minded individuals.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>datascience</category>
      <category>starknet</category>
    </item>
    <item>
      <title>Data to Queries: Exploring Starknet Data with Dune</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Mon, 19 Aug 2024 00:36:26 +0000</pubDate>
      <link>https://dev.to/lordghostx/data-to-queries-exploring-starknet-data-with-dune-ihd</link>
      <guid>https://dev.to/lordghostx/data-to-queries-exploring-starknet-data-with-dune-ihd</guid>
      <description>&lt;p&gt;Dune has &lt;a href="https://dune.com/blog/starknet-is-now-live-on-dune" rel="noopener noreferrer"&gt;recently integrated Starknet&lt;/a&gt;, one of Ethereum's most promising Layer 2. This integration allows you to easily interact with, visualize, query, and analyze data from Starknet directly on Dune.&lt;/p&gt;

&lt;p&gt;If you're looking to create dashboards, you may want to check out my detailed guide: &lt;a href="https://dev.to/lordghostx/queries-to-insights-visualizing-starknet-data-with-dune-j8p"&gt;Queries to Insights: Visualizing Starknet Data with Dune&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article will walk you through querying Starknet data on Dune, which you can use to create insightful dashboards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing Starknet's Data
&lt;/h2&gt;

&lt;p&gt;Dune transforms raw blockchain data into SQL databases, enabling you to write &lt;a href="https://dune.com/blog/introducing-dune-sql" rel="noopener noreferrer"&gt;DuneSQL queries&lt;/a&gt; to retrieve and analyze the data, visualize it with dashboards, develop data-driven applications, and many more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Open the "Create" dropdown menu in Dune's navigation bar&lt;/strong&gt;&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%2Fosvcg34xz9lk590c23x0.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%2Fosvcg34xz9lk590c23x0.png" alt="Create Dropdown" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Choose "New Query" from the options&lt;/strong&gt;&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%2Fjrs2dvn2x7nn6g13htb6.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%2Fjrs2dvn2x7nn6g13htb6.png" alt="New Query Button" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. You'll be directed to the "New Query" page&lt;/strong&gt;&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%2F4qhzwpsusl1fz43ys8ah.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%2F4qhzwpsusl1fz43ys8ah.png" alt="New Query Page" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Click "Raw Blockchain Data" on the Data Explorer&lt;/strong&gt;&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%2F6cizwl5mjwxcwv3njw7e.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%2F6cizwl5mjwxcwv3njw7e.png" alt="Raw Blockchain Data Button" width="760" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Search and click on "starknet"&lt;/strong&gt;&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%2Femkharlr2lm4qgq9mqdp.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%2Femkharlr2lm4qgq9mqdp.png" alt="Starknet Search Results" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now explore and filter all Starknet-related tables, accessing data on blocks, calls, on-chain events, and transactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Explore the data tables&lt;/strong&gt;&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%2Ffpt2i95qi041xnejeh4v.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%2Ffpt2i95qi041xnejeh4v.png" alt="Starknet Tables" width="800" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also filter columns within any table. In the image below, you can see the data types of the fields and the SQL editor on the right side for writing queries.&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%2Fis94yh2c2eyovcfxtkbr.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%2Fis94yh2c2eyovcfxtkbr.png" alt="Dune SQL Editor" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take some time to explore the available data on Dune. When ready, you can start writing queries to extract the needed data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing DuneSQL Queries for Starknet
&lt;/h2&gt;

&lt;p&gt;DuneSQL is an easy-to-read query language similar to other SQL variations. To learn more about DuneSQL and its features, check out the &lt;a href="https://docs.dune.com/home" rel="noopener noreferrer"&gt;Dune documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Query Transaction Details by Hash
&lt;/h3&gt;

&lt;p&gt;Let's write a query to retrieve the details of a transaction by its hash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;starknet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transactions&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;transaction_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x0716bd0f37d806ceb45dff6d4d0620034c1d127df8a619e6febe9dfc034ef33e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query fetches all the columns for the &lt;code&gt;transactions&lt;/code&gt; table with a specified &lt;code&gt;transaction_hash&lt;/code&gt;. Click the &lt;strong&gt;"Run"&lt;/strong&gt; button to execute:&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%2F2cjzyu9q5bdq3pl80pw5.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%2F2cjzyu9q5bdq3pl80pw5.png" alt="Query Run Button" width="800" height="191"&gt;&lt;/a&gt;&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%2Fmk53tbc49s6xswjkrvdk.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%2Fmk53tbc49s6xswjkrvdk.png" alt="Query Result" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can create parameters for your queries that allow you to adjust variables on the fly and explore data dynamically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;starknet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transactions&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;transaction_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="n"&gt;tx_hash&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F5pyq1nv01rprgjopzpav.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%2F5pyq1nv01rprgjopzpav.png" alt="Query With Parameters" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Querying Latest Block Details
&lt;/h3&gt;

&lt;p&gt;Let's write a query to retrieve the details of the latest block on Starknet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;tx_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;hash&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;starknet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blocks&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query fetches the creation time, block number, transaction count, and hash of the latest created block on Starknet. Click the &lt;strong&gt;"Run"&lt;/strong&gt; button to execute:&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%2Flxzdxp0vd9demulqx3mo.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%2Flxzdxp0vd9demulqx3mo.png" alt="Query Result" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Sorting Smart Contracts by Transaction Count
&lt;/h3&gt;

&lt;p&gt;Let's write a more practical query that fetches the top contracts on Starknet by the number of transactions over the last 30 days:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;contract_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;transaction_count&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;starknet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transactions&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;block_time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'30'&lt;/span&gt; &lt;span class="k"&gt;DAY&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;contract_address&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="n"&gt;contract_address&lt;/span&gt;
&lt;span class="k"&gt;HAVING&lt;/span&gt;
  &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="n"&gt;transaction_count&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt;
  &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation of the query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SELECT&lt;/code&gt;: The query retrieves two columns: &lt;code&gt;contract_address&lt;/code&gt; and a count of all transactions associated with each &lt;code&gt;contract_address&lt;/code&gt;, labeled &lt;code&gt;transaction_count&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FROM&lt;/code&gt;: The data is pulled from the &lt;code&gt;transactions&lt;/code&gt; table within the &lt;code&gt;starknet&lt;/code&gt; schema.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WHERE&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Filters the transactions to include only those that occurred within the last 30 days &lt;code&gt;(block_time &amp;gt;= CURRENT_TIMESTAMP - INTERVAL '30' DAY)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Excludes rows where &lt;code&gt;contract_address&lt;/code&gt; is NULL to ensure you only count transactions tied to an actual contract address.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;GROUP BY&lt;/code&gt;: Groups the results by &lt;code&gt;contract_address&lt;/code&gt; so that the &lt;code&gt;COUNT&lt;/code&gt; function aggregates the number of transactions per contract address.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;HAVING&lt;/code&gt;: This condition ensures that only contract addresses with at least one transaction &lt;code&gt;(HAVING COUNT(*) &amp;gt; 0)&lt;/code&gt; are included in the results. Although the &lt;code&gt;WHERE&lt;/code&gt; clause already filters out &lt;code&gt;NULL&lt;/code&gt; addresses, this is an additional safeguard.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;ORDER BY&lt;/code&gt;: Orders the grouped results by &lt;code&gt;transaction_count&lt;/code&gt; in descending order, so the most active contract addresses appear first.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;LIMIT&lt;/code&gt;: Limits the output to the top 10 contract addresses with the highest transaction counts.&lt;/li&gt;

&lt;/ul&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%2F6j1ptw4bkxrzjrclwecv.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%2F6j1ptw4bkxrzjrclwecv.png" alt="Query Result" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Retrieving $STRK Token Price
&lt;/h3&gt;

&lt;p&gt;You can also query the price of tokens on Dune! Here's a modified query, inspired by the &lt;a href="https://dune.com/caravanserai/starknet-overview" rel="noopener noreferrer"&gt;Starknet Overview Dashboard&lt;/a&gt;, that retrieves the price of Starknet's $STRK token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"Date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"STRK Price"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usd&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
  &lt;span class="n"&gt;blockchain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ethereum'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;contract_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;xca14007eff0db1f8135f4c25b34de49ab0d42766&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
  &lt;span class="nv"&gt;"Date"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Visualizing Results From Your Queries
&lt;/h2&gt;

&lt;p&gt;You can take your queries a step further by visualizing their generated data and even adding it to a dashboard. We'll be visualizing the query that fetches $STRK prices.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Click the "New" button beside "Query Results"
&lt;/h3&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%2F08ygfzzt7lto7me0a68n.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%2F08ygfzzt7lto7me0a68n.png" alt="New Visualization Button" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Select the chart type you want to create
&lt;/h3&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%2Fzc7z575eutiucr02gdi5.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%2Fzc7z575eutiucr02gdi5.png" alt="Select Chart Dropdown" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Click the "Add Visualization" Button
&lt;/h3&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%2F7pmut6xcfgqw8cs19xer.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%2F7pmut6xcfgqw8cs19xer.png" alt="Add Visualization Button" width="800" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Explore Dune's various visualizations
&lt;/h3&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%2F9dw0manb019mecvo84lg.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%2F9dw0manb019mecvo84lg.png" alt="Area Chart" width="800" height="250"&gt;&lt;/a&gt;&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%2Fiq59ffnrh1dcj085gm8j.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%2Fiq59ffnrh1dcj085gm8j.png" alt="Line Chart" width="800" height="255"&gt;&lt;/a&gt;&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%2Fhwhv3w6say53gc1t92yy.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%2Fhwhv3w6say53gc1t92yy.png" alt="Bar Chart" width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can take your queries and visualizations further by adding them to a dashboard, allowing the data to flow and tell compelling stories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starknet Resources on Dune
&lt;/h2&gt;

&lt;p&gt;Dune provides a growing selection of Starknet-specific queries and dashboards, offering valuable insights into the ecosystem. One standout resource is the &lt;a href="https://dune.com/caravanserai" rel="noopener noreferrer"&gt;Caravanserai page&lt;/a&gt;, featuring in-depth dashboards and queries of various Starknet metrics: &lt;a href="https://dune.com/caravanserai" rel="noopener noreferrer"&gt;https://dune.com/caravanserai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more Starknet-related content, use Dune's search function to discover queries, dashboards, and contributors: &lt;a href="https://dune.com/discover/content/relevant?q=starknet" rel="noopener noreferrer"&gt;https://dune.com/discover/content/relevant?q=starknet&lt;/a&gt;. As Starknet evolves, we can expect these analytics resources on Dune to expand, offering even deeper insights into its on-chain data.&lt;/p&gt;

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

&lt;p&gt;In this article, we've explored how to query and visualize Starknet data on Dune and how to create dynamic queries by creating parameters for them.&lt;/p&gt;

&lt;p&gt;If you're interested in analyzing Starknet data, finding opportunities in the ecosystem, or sharing valuable insights, join our &lt;a href="https://t.me/+TiNIOKAdIyQzNDg0" rel="noopener noreferrer"&gt;MEV discussion group&lt;/a&gt; to connect with like-minded individuals.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>datascience</category>
      <category>starknet</category>
    </item>
    <item>
      <title>Queries to Insights: Visualizing Starknet Data with Dune</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Fri, 09 Aug 2024 20:06:15 +0000</pubDate>
      <link>https://dev.to/lordghostx/queries-to-insights-visualizing-starknet-data-with-dune-j8p</link>
      <guid>https://dev.to/lordghostx/queries-to-insights-visualizing-starknet-data-with-dune-j8p</guid>
      <description>&lt;p&gt;Starknet's on-chain data offers a wealth of insights into its blockchain ecosystem. It provides a comprehensive view of user activity, transaction patterns, and network interactions, allowing analysts to discover valuable trends and behaviors. The ability to analyze on-chain data is important for making informed decisions, optimizing protocols, and identifying emerging opportunities within the network.&lt;/p&gt;

&lt;p&gt;This article will guide you through transforming raw Starknet data into compelling visual narratives using Dune. We'll explore leveraging Dune's powerful querying capabilities and visualization tools to create dynamic, interactive dashboards that bring Starknet's on-chain data to life.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://www.starknet.io/" rel="noopener noreferrer"&gt;Starknet&lt;/a&gt; is an Ethereum Layer 2 (L2) designed to deliver high transaction throughput and low costs while maintaining Ethereum's core principles. Starknet uses Zero-Knowledge (ZK) technology, specifically &lt;a href="https://starkware.co/wp-content/uploads/2022/05/STARK-paper.pdf" rel="noopener noreferrer"&gt;ZK-STARK proofs&lt;/a&gt;, to verify transaction validity off-chain before committing them to the Ethereum mainnet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starknet's Architecture
&lt;/h3&gt;

&lt;p&gt;Starknet's architecture is built to optimize the Ethereum ecosystem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: By processing transactions off-chain and then batching them for submission to Ethereum, Starknet significantly increases the network's capacity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Efficiency&lt;/strong&gt;: The reduced computational load on Ethereum translates to lower gas fees for users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: ZK-STARK proofs ensure that all transactions are valid without revealing sensitive information, maintaining high security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compatibility&lt;/strong&gt;: Starknet is designed to work seamlessly with Ethereum, allowing developers to build scalable applications that benefit from Ethereum's established ecosystem.&lt;/li&gt;
&lt;/ul&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%2Fv2kvg5vcm0suacmpy4oo.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%2Fv2kvg5vcm0suacmpy4oo.png" alt="Starknet Network Architecture" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Value of Starknet Data
&lt;/h3&gt;

&lt;p&gt;Starknet's on-chain data is a goldmine of information for various stakeholders in the blockchain space:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developers&lt;/strong&gt;: Can analyze transaction patterns to optimize their dApps and smart contracts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Investors&lt;/strong&gt;: Gain insights into user adoption, token flows, and emerging trends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Researchers&lt;/strong&gt;: Study the effectiveness of L2 solutions and their impact on the broader Ethereum ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol Designers&lt;/strong&gt;: Use data to identify bottlenecks and improve network efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market Analysts&lt;/strong&gt;: Track the growth of the Starknet ecosystem and its integration with DeFi and other blockchain applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By analyzing Starknet's on-chain data, we can gain valuable insights into the network's health, user behavior, and the adoption of Layer 2 solutions in the Ethereum ecosystem.&lt;/p&gt;

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

&lt;p&gt;Dune is a powerful blockchain data analytics platform that enables users to query, visualize, and share insights from various blockchain networks, including Starknet. By leveraging Dune's capabilities for Starknet analysis, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query Complex Data&lt;/strong&gt;: Use &lt;a href="https://dune.com/blog/introducing-dune-sql" rel="noopener noreferrer"&gt;Dune SQL&lt;/a&gt; to query and extract Starknet's on-chain data, allowing for deep dives into specific metrics and trends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create Dynamic Visualizations&lt;/strong&gt;: Transform raw data into intuitive charts, graphs, and tables that make complex blockchain information understandable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Develop Compelling Dashboards&lt;/strong&gt;: Combine multiple queries and visualizations to create holistic views of Starknet's ecosystem, monitoring key real-time performance indicators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track Ecosystem Metrics&lt;/strong&gt;: Monitor essential data points such as daily active addresses, transaction volumes, gas usage, and smart contract interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analyze Token Flows&lt;/strong&gt;: Gain insights into token transfers, liquidity pools, and trading patterns within the Starknet network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborate and Share&lt;/strong&gt;: Leverage Dune's community features to build upon existing queries, share your findings, and contribute to the collective understanding of Starknet's performance.&lt;/li&gt;
&lt;/ul&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%2Fdya9shj1tnchc1struq6.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%2Fdya9shj1tnchc1struq6.png" alt="Dune" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Starknet Data Points
&lt;/h2&gt;

&lt;p&gt;Let's explore some of the key areas where we can extract valuable insights on Starknet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Data&lt;/strong&gt;: Information about each transaction, including unique identifiers, involved addresses, transferred values, gas fees, and timestamps. This helps understand network usage patterns and economic activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block Data&lt;/strong&gt;: Provides a structural overview of the blockchain, including block numbers, hashes, timestamps, and transaction counts. This helps analyze network growth and validate the chain's integrity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Contract Data&lt;/strong&gt;: Information about deployed contracts and their current state helps developers and analysts study decentralized application (dApp) usage and smart contract interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account Data&lt;/strong&gt;: This includes account balances and transaction counters (nonce), giving a view of user activity and asset distribution across the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rollup-Specific Data&lt;/strong&gt;: Unique to Layer 2 solutions like Starknet, this includes ZK-STARK proofs and state updates, which are important for understanding the roll-up mechanism's efficiency and security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Data&lt;/strong&gt;: Tracks the creation, transfer, and usage of various tokens on the network, including both fungible and non-fungible tokens (NFTs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol Metrics&lt;/strong&gt;: Provides insights into the overall health and performance of the network, including total value locked (TVL), daily active users, and transaction throughput.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperability Data&lt;/strong&gt;: Captures cross-chain interactions and bridge usage information, highlighting Starknet's connection to the broader Ethereum ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Starknet Resources on Dune
&lt;/h2&gt;

&lt;p&gt;Dune provides a growing selection of Starknet-specific queries and dashboards, offering valuable insights into the ecosystem. One standout resource is the &lt;a href="https://dune.com/caravanserai" rel="noopener noreferrer"&gt;Caravanserai page&lt;/a&gt;, featuring in-depth dashboards and queries of various Starknet metrics: &lt;a href="https://dune.com/caravanserai" rel="noopener noreferrer"&gt;https://dune.com/caravanserai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more Starknet-related content, use Dune's search function to discover queries, dashboards, and contributors: &lt;a href="https://dune.com/discover/content/relevant?q=starknet" rel="noopener noreferrer"&gt;https://dune.com/discover/content/relevant?q=starknet&lt;/a&gt;. As Starknet evolves, we can expect these analytics resources on Dune to expand, offering even deeper insights into its on-chain data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualizing Data with Dune Dashboards
&lt;/h2&gt;

&lt;p&gt;Dune dashboards are a powerful tool for visualizing and presenting blockchain data in an intuitive, interactive format. These dashboards allow you to create comprehensive analytical tools by combining various data visualization widgets and explanatory text. Key features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Versatile Widgets&lt;/strong&gt;: You can use various &lt;a href="https://docs.dune.com/web-app/visualizations/charts-graphs" rel="noopener noreferrer"&gt;visualization types&lt;/a&gt; such as charts, graphs, tables, and metrics to represent data effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text Integration&lt;/strong&gt;: Explanatory text widgets can be added to your data visualizations to provide context, analysis, or instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multimedia Support&lt;/strong&gt;: Images and GIFs can be embedded within text widgets, enhancing your dashboard's visual appeal and clarity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization&lt;/strong&gt;: Dashboards are highly customizable, allowing you to arrange widgets and create a cohesive design that best communicates your insights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sharing and Collaboration&lt;/strong&gt;: Easily share your dashboards with others or collaborate on their development.&lt;/li&gt;
&lt;/ul&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%2F0vspz8wpxab7aibzsjjz.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%2F0vspz8wpxab7aibzsjjz.png" alt="Dune Dashboard" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Dune Dashboards
&lt;/h3&gt;

&lt;p&gt;To create a new dashboard on Dune:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Open the "Create" dropdown menu in Dune's navigation bar&lt;/strong&gt;&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%2Fosvcg34xz9lk590c23x0.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%2Fosvcg34xz9lk590c23x0.png" alt="Create Dropdown" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Choose "New Dashboard" from the options&lt;/strong&gt;&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%2F3sema74ytcqnbgx3kt9o.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%2F3sema74ytcqnbgx3kt9o.png" alt="New Dashboard Button" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Enter a descriptive name that reflects your dashboard's focus&lt;/strong&gt;&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%2Fsettxd6zouacj0oo31vh.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%2Fsettxd6zouacj0oo31vh.png" alt="Dashboard Naming" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Click "Save and Open" to create your dashboard&lt;/strong&gt;&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%2Ftccl3fmc8n0acfrfnvqh.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%2Ftccl3fmc8n0acfrfnvqh.png" alt="Saving Dashboard Button" width="800" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Click "Edit" to modify the dashboard and add visualizations&lt;/strong&gt;&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%2Fwfqxpolupis398bv8lec.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%2Fwfqxpolupis398bv8lec.png" alt="Edit Button" width="792" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Click "Add Visualization" and search for queries to visualize&lt;/strong&gt;&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%2Fyceby0fzezo0w7julch5.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%2Fyceby0fzezo0w7julch5.png" alt="Add Visualization Button" width="800" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Click "Add" next to each query you want to include&lt;/strong&gt;&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%2Fk1jv7m4sokpzqsdks237.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%2Fk1jv7m4sokpzqsdks237.png" alt="Queries List" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Click "Done" to finalize your dashboard setup&lt;/strong&gt;&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%2Fb9722c4x79xng56png85.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%2Fb9722c4x79xng56png85.png" alt="Done Button" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After adding queries and arranging the visualizations, your dashboard might resemble the following example:&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%2F2lyypy9zuaxxmvittjgh.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%2F2lyypy9zuaxxmvittjgh.png" alt="Dashboard View" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Important: Dune dashboards are not real-time. To view the latest Starknet data and keep your analysis current:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refresh the dashboard by clicking the &lt;strong&gt;Run&lt;/strong&gt; button in the top right corner.&lt;/li&gt;
&lt;li&gt;Update specific widgets using their refresh icons for dashboards with multiple queries.&lt;/li&gt;
&lt;li&gt;Leverage Dune's scheduling feature to automate regular updates for key queries.&lt;/li&gt;
&lt;li&gt;Consider performance impact when refreshing frequently, especially for complex queries.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;p&gt;The following best practices will help you design insightful, accessible, and engaging dashboards that maximize the value of Dune:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Group related metrics&lt;/strong&gt;: For intuitive navigation, organize by categories such as network activity, economics, and performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize key metrics&lt;/strong&gt;: Focus on the most important data points to maintain clarity and prevent information overload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintain visual consistency&lt;/strong&gt;: Use similar chart types for related data and a cohesive color scheme.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage interactivity&lt;/strong&gt;: Implement filters, parameters, and drill-down options for in-depth exploration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize layout&lt;/strong&gt;: Arrange widgets logically, placing the most important data in prominent positions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide context&lt;/strong&gt;: Add concise text explanations to help users interpret data and understand its significance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensure performance&lt;/strong&gt;: Optimize query efficiency and widget loading for a smooth user experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share and collaborate&lt;/strong&gt;: Share your dashboard and engage with the community by forking existing dashboards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhance discoverability&lt;/strong&gt;: Use clear titles and descriptions to make your dashboard discoverable in Dune&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clarify data freshness&lt;/strong&gt;: Communicate the update frequency for time-sensitive analysis and consider including a &lt;strong&gt;Last Updated&lt;/strong&gt; timestamp.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In this article, we've covered the basics of Starknet and why its data is so valuable, explored Dune, and demonstrated how to find and visualize key resources. We've also learned how to create and manage dashboards for Starknet's unique data landscape.&lt;/p&gt;

&lt;p&gt;If you're interested in analyzing Starknet data, finding opportunities in the ecosystem, or sharing valuable insights, join our &lt;a href="https://t.me/+TiNIOKAdIyQzNDg0" rel="noopener noreferrer"&gt;MEV discussion group&lt;/a&gt; to connect with like-minded individuals.&lt;/p&gt;

</description>
      <category>starknet</category>
      <category>web3</category>
      <category>datascience</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Starknet Protocols: Key Features and MEV Opportunities</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Wed, 31 Jul 2024 22:30:07 +0000</pubDate>
      <link>https://dev.to/lordghostx/starknet-protocols-key-features-and-mev-opportunities-574i</link>
      <guid>https://dev.to/lordghostx/starknet-protocols-key-features-and-mev-opportunities-574i</guid>
      <description>&lt;p&gt;&lt;a href="https://www.starknet.io/" rel="noopener noreferrer"&gt;Starknet&lt;/a&gt; is an Ethereum Layer 2 (L2) designed to deliver high transaction throughput and low costs while maintaining Ethereum's core principles. Starknet uses Zero-Knowledge (ZK) technology, specifically &lt;a href="https://starkware.co/wp-content/uploads/2022/05/STARK-paper.pdf" rel="noopener noreferrer"&gt;ZK-STARK proofs&lt;/a&gt;, to verify transaction validity off-chain before committing them to the Ethereum mainnet.&lt;/p&gt;

&lt;p&gt;You can build a wide range of dApps on Starknet just as you would on Ethereum or other Layer 1 blockchain. Starknet hosts numerous dApps and protocols that offer impressive features and present various MEV opportunities.&lt;/p&gt;

&lt;p&gt;This article explores some protocols and dApps built on Starknet and the MEV opportunities they present.&lt;/p&gt;

&lt;h2&gt;
  
  
  Top Protocols on Starknet
&lt;/h2&gt;

&lt;p&gt;By building on Starknet, you can access a scalable, cost-effective blockchain that leverages Ethereum's benefits while allowing you to innovate beyond limits. You can find the top projects on Starknet by total value locked (TVL) on &lt;a href="https://defillama.com/chain/Starknet" rel="noopener noreferrer"&gt;DeFi Llama&lt;/a&gt;:&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%2Fojpphu1zxs4eeg59l7zn.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%2Fojpphu1zxs4eeg59l7zn.png" alt="Top Starknet Protocols" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Nostra
&lt;/h3&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%2Fh8vm6x56yocw3co0lo9m.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%2Fh8vm6x56yocw3co0lo9m.png" alt="Nostra" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nostra.finance" rel="noopener noreferrer"&gt;Nostra&lt;/a&gt; is a comprehensive DeFi protocol on Starknet that integrates multiple financial services into a single platform. Nostra is on a mission to power flexible crypto actions and provide an excellent user experience. Key features of Nostra include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nostra.finance/stake/" rel="noopener noreferrer"&gt;Staking&lt;/a&gt;: Liquid-stake your $STRK to earn yield and receive Nostra Staked STRK (nstSTRK) tokens. Use nstSTRK in DeFi apps across Starknet and other dApps on Ethereum.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nostra.finance/lend/" rel="noopener noreferrer"&gt;Lending and Borrowing&lt;/a&gt;: With Nostra, you can lend your crypto assets to earn interest or use your deposits to borrow other assets. It supports stablecoins like USDT, USDC, and DAI, as well as volatile assets like ETH and WBTC.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nostra.finance/pools/" rel="noopener noreferrer"&gt;Liquidity Pools&lt;/a&gt;: You can deposit your crypto into Nostra's liquidity pools to earn swap fees and yield.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nostra.finance/swap/" rel="noopener noreferrer"&gt;Swapping&lt;/a&gt;: You can swap and trade various tokens on Starknet. Nostra uses &lt;a href="https://www.avnu.fi/" rel="noopener noreferrer"&gt;AVNU's DEX aggregator&lt;/a&gt; to tap into Starknet's liquidity network, ensuring you get the best available prices.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nostra.finance/bridge/" rel="noopener noreferrer"&gt;Bridging&lt;/a&gt;: Nostra supports seamless bridging of assets across more than 20 blockchains, allowing you to transfer your crypto quickly and securely with minimal fees.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nostra.finance/uno/" rel="noopener noreferrer"&gt;UNO Stablecoin&lt;/a&gt;: Nostra also offers the $UNO stablecoin, a fully collateralized, Starknet-native USD stablecoin. UNO provides a stable asset for transactions, earning yield, and hedging against volatility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ekubo Protocol
&lt;/h3&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%2Fu4fxxgn1ro7638cc1bag.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%2Fu4fxxgn1ro7638cc1bag.png" alt="Ekubo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ekubo.org/" rel="noopener noreferrer"&gt;Ekubo&lt;/a&gt; is a next-generation Automated Market Maker (AMM) on Starknet, designed for super-concentrated liquidity, extensibility, and providing users with low fees and high returns. Key features of Ekubo include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://app.ekubo.org/" rel="noopener noreferrer"&gt;Swapping&lt;/a&gt;: You can efficiently swap your tokens with the lowest gas fees. Ekubo also offers Dollar-Cost Average (DCA) orders, allowing you to place orders that execute over time for more efficient and programmatic entry and exit from positions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://app.ekubo.org/positions" rel="noopener noreferrer"&gt;Liquidity Pools&lt;/a&gt;: You can provide liquidity to Ekubo's pools to earn returns, benefiting from optimized liquidity usage and reduced gas costs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.ekubo.org/integration-guides/extensions" rel="noopener noreferrer"&gt;Extensions&lt;/a&gt;: You can leverage Ekubo's efficient and secure core AMM protocol to create new order types, trading strategies, oracles, and many more using extensions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  zkLend
&lt;/h3&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%2F5ac7m5uebdpm6kit9b04.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%2F5ac7m5uebdpm6kit9b04.png" alt="zkLend" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zklend.com/" rel="noopener noreferrer"&gt;zkLend&lt;/a&gt; is a native lending protocol on Starknet that provides secure and user-friendly lending and borrowing services that are efficient and decentralized. Key features of zkLend include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://zklend.gitbook.io/documentation/using-zklend/supply" rel="noopener noreferrer"&gt;Deposits&lt;/a&gt;: You can deposit assets into zkLend's lending pools to earn competitive interest based on real-time supply and demand.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://zklend.gitbook.io/documentation/using-zklend/borrow" rel="noopener noreferrer"&gt;Borrowing&lt;/a&gt;: You can borrow against your deposits, using them as collateral for secure and efficient access to funds.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://zklend.gitbook.io/documentation/using-zklend/borrow/flash-loans" rel="noopener noreferrer"&gt;Flash Loans&lt;/a&gt;: zkLend supports flash loans for complex and time-sensitive transactions, allowing you to execute loans without upfront collateral requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Nimbora
&lt;/h3&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%2Fb4qy0s3jkv0fkvcols19.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%2Fb4qy0s3jkv0fkvcols19.png" alt="Nimbora" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nimbora.io/" rel="noopener noreferrer"&gt;Nimbora&lt;/a&gt; is a Starknet-based infrastructure enabling users to earn and borrow on Layer 1 protocols with significantly reduced costs. Key features of Nimbora include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://app.nimbora.io/" rel="noopener noreferrer"&gt;Earning&lt;/a&gt;: You can deposit into Nimbora's pools to earn interest on your assets. Nimbora leverages &lt;a href="https://docs.nimbora.io/docs/concepts/products/" rel="noopener noreferrer"&gt;multiple strategies&lt;/a&gt; to maximize yield opportunities and returns.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://app.nimbora.io/" rel="noopener noreferrer"&gt;Borrowing&lt;/a&gt;: You can use your deposits as collateral to borrow other assets from Nimbora's pools. Nimbora helps you discover the best borrowing rates on Ethereum, enhancing your investment strategies for maximum efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vesu
&lt;/h3&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%2Fdn6j7pytf654h0b7pkak.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%2Fdn6j7pytf654h0b7pkak.png" alt="Vesu" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vesu is a fully open, transparent, immutable, and user-friendly lending protocol built on Starknet. Vesu allows you to supply and borrow crypto assets without intermediaries, offering a decentralized public infrastructure that is free for everyone. Key features of Vesu include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.vesu.xyz/lend" rel="noopener noreferrer"&gt;Earning&lt;/a&gt;: You can deposit assets into Vesu's lending pools to earn returns and yield. Vesu ensures maximum capital efficiency by aggregating assets to serve as shared liquidity for all borrowers in the same pool.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vesu.xyz/borrow" rel="noopener noreferrer"&gt;Borrowing&lt;/a&gt;: You can use your deposited assets as collateral to securely and efficiently borrow other assets, gaining access to funds without relying on intermediaries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  mySwap
&lt;/h3&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%2F0y4w5hfbpor3mn8teivs.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%2F0y4w5hfbpor3mn8teivs.png" alt="mySwap" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.myswap.xyz/" rel="noopener noreferrer"&gt;mySwap&lt;/a&gt; is a concentrated liquidity AMM on Starknet, designed to provide an exceptional user experience and APR for users and liquidity providers based on the Uniswap v2 model. Key features of mySwap include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://app.myswap.xyz/" rel="noopener noreferrer"&gt;Swapping&lt;/a&gt;: You can swap your tokens with low gas fees and minimize slippage. By concentrating liquidity within specific price ranges, mySwap facilitates efficient trades and maximizes your returns.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://app.myswap.xyz/#/positions" rel="noopener noreferrer"&gt;Liquidity Pools&lt;/a&gt;: You can earn higher returns on mySwap by concentrating your liquidity within specific price ranges, allowing for more efficient trades and optimized yield.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  MEV Opportunities on Starknet Protocols
&lt;/h2&gt;

&lt;p&gt;Starknet processes transactions using a First-Come-First-Serve (FCFS) model, preventing front-running. However, there are other &lt;a href="https://dev.to/lordghostx/introduction-to-mev-on-starknet-1o0l"&gt;MEV (Maximum Extractable Value) opportunities&lt;/a&gt; you can explore:&lt;/p&gt;

&lt;h3&gt;
  
  
  Arbitrage
&lt;/h3&gt;

&lt;p&gt;Arbitrage involves taking advantage of price differences for an asset across different exchanges or markets. You can profit by simultaneously buying low in one market and selling high in another, provided the transaction fees don’t consume all the profit. Arbitrage benefits traders, helps balance prices across protocols, and improves market liquidity.&lt;/p&gt;

&lt;p&gt;For example, suppose Ethereum (ETH) is priced at $1,900 on Nostra and $1,920 on Ekubo. You can purchase ETH on Nostra and immediately sell it on Ekubo, pocketing a $20 profit per ETH (minus transaction fees). However, performing precise calculations to ensure your arbitrage remains profitable is important, as transaction fees and market fluctuations can impact your potential gains.&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%2Fdtxfsgt9cqiy9nh8vrfk.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%2Fdtxfsgt9cqiy9nh8vrfk.png" alt="Arbitrage" width="571" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are various forms of arbitrage that extend beyond the basic concept:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Layer Arbitrage&lt;/strong&gt;: Conducting arbitrage across multiple blockchain networks or layers. For example, you buy ETH on Ekubo (Starknet), bridge to Ethereum, and sell it on Uniswap (Ethereum).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pool to Pool Arbitrage&lt;/strong&gt;: Taking advantage of price discrepancies between different liquidity pools within the same or different protocols. For example, you buy a token from Nostra's liquidity pool and sell it in Ekubo's pool, where the price is higher.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atomic Arbitrage&lt;/strong&gt;: Executing a series of transactions within a single block to ensure all steps are completed simultaneously, minimizing risk. For example, you can use flash loans to buy and sell assets within the same transaction to capture price differences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Triangular Arbitrage&lt;/strong&gt;: Involves trading between three different assets to take advantage of discrepancies in their exchange rates. For example, you sell STRK for ETH, ETH for NSTR, and then NSTR back to STRK.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Statistical Arbitrage&lt;/strong&gt;: Using statistical models to identify and exploit pricing inefficiencies. For example, you use historical data to predict and trade assets based on expected price movements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To ensure profitability, each type of arbitrage requires a deep understanding of the markets and precise calculations, including transaction fees and market volatility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Liquidation
&lt;/h3&gt;

&lt;p&gt;Liquidation occurs when borrowers fail to maintain their collateral ratios and their assets are sold off. By monitoring lending protocols like zkLend and Vesu for undercollateralized loans, you can execute liquidations and earn a portion of the collateral as a reward. This process helps keep the lending platform solvent and protects lenders' funds.&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%2Frne46632b8vcbpxjuwnv.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%2Frne46632b8vcbpxjuwnv.png" alt="Liquidation" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Starknet's growing DeFi ecosystem presents exciting opportunities for users and developers. Its FCFS model reduces traditional MEV strategies like front-running, but searchers can still profit through arbitrage and liquidations.&lt;/p&gt;

&lt;p&gt;As Starknet evolves, we can expect more innovative protocols and MEV opportunities. Whether you're seeking better yields, developing new dApps, or exploring MEV strategies, Starknet offers many possibilities.&lt;/p&gt;

&lt;p&gt;If you want to discuss MEV on Starknet or have valuable insights to share, join our &lt;a href="https://t.me/+TiNIOKAdIyQzNDg0" rel="noopener noreferrer"&gt;MEV discussion group&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>starknet</category>
      <category>blockchain</category>
      <category>mev</category>
    </item>
    <item>
      <title>Introduction to MEV on Starknet</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Thu, 25 Jul 2024 15:04:59 +0000</pubDate>
      <link>https://dev.to/lordghostx/introduction-to-mev-on-starknet-1o0l</link>
      <guid>https://dev.to/lordghostx/introduction-to-mev-on-starknet-1o0l</guid>
      <description>&lt;p&gt;Maximal extractable value (MEV) refers to the maximum value that can be extracted from block production more than the standard block reward and gas fees by including, excluding, and changing the order of transactions in a block.&lt;/p&gt;

&lt;p&gt;MEV has become more popular since Ethereum transitioned to &lt;a href="https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/" rel="noopener noreferrer"&gt;Proof-of-Stake (PoS)&lt;/a&gt;. The rise of Layer 2's like &lt;a href="https://www.starknet.io" rel="noopener noreferrer"&gt;Starknet&lt;/a&gt; introduced new dynamics to the MEV landscape. Understanding MEV within these ecosystems is important in comprehending the implications of on-chain competition and its effects on network stability and user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  MEV on Ethereum
&lt;/h2&gt;

&lt;p&gt;MEV in the Ethereum ecosystem presents a complex duality with beneficial and potentially detrimental impacts on the network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inefficiency and unfairness&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MEV can lead to network congestion and higher gas fees.&lt;/li&gt;
&lt;li&gt;It may create an uneven playing field, favoring well-resourced and technically sophisticated actors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Innovation and security incentives&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MEV drives advancements in transaction execution mechanisms.&lt;/li&gt;
&lt;li&gt;It offers additional incentives to enhance network security and reliability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Market health&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MEV helps with pricing consistency across protocols. Active MEV ensures that prices remain the same across different platforms, reducing the risk of bad debt on lending positions.&lt;/li&gt;
&lt;li&gt;While some MEV practices can be harmful, useful MEV, such as arbitrage, helps maintain healthy markets by improving liquidity and price discovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MEV extraction strategies
&lt;/h3&gt;

&lt;p&gt;There are multiple strategies to extract value from block production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Front-running&lt;/strong&gt;: Placing a transaction ahead of a known future transaction. For example, if a large trade is detected in the mempool, a front-runner might place a buy order just before it, then sell immediately after, profiting from the price impact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Back-running&lt;/strong&gt;: Positioning a transaction immediately after a target transaction. This can be used to capitalize on state changes caused by the target transaction, such as taking advantage of a newly created arbitrage opportunity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandwich attacks&lt;/strong&gt;: Combining front-running and back-running to profit from price movements. A sandwicher places a buy order before a large swap, then a sell order immediately after, profiting from the temporary price impact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liquidations&lt;/strong&gt;: Liquidating under-collateralized positions to earn fees or acquire discounted collateral. Bots monitor lending protocols for positions close to liquidation thresholds and quickly execute liquidation transactions when conditions are met.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MEV infrastructure and tooling
&lt;/h3&gt;

&lt;p&gt;The MEV ecosystem has developed various tools and platforms to manage and optimize MEV extraction. These solutions seek to balance the benefits of MEV while minimizing its negative impacts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.flashbots.net" rel="noopener noreferrer"&gt;Flashbots&lt;/a&gt;&lt;/strong&gt;: A research and development organization dedicated to addressing the challenges and opportunities of MEV in the Ethereum ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://edennetwork.io" rel="noopener noreferrer"&gt;Eden Network&lt;/a&gt;&lt;/strong&gt;: A transaction ordering protocol designed to democratize MEV extraction and protect users from malicious MEV practices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.manifoldfinance.com" rel="noopener noreferrer"&gt;Manifold Finance&lt;/a&gt;&lt;/strong&gt;: A platform focusing on gas cost optimization and MEV protection for DeFi users, enhancing the overall efficiency and security of transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://boost.flashbots.net" rel="noopener noreferrer"&gt;MEV-Boost&lt;/a&gt;&lt;/strong&gt;: An implementation of &lt;a href="https://ethresear.ch/t/proposer-block-builder-separation-friendly-fee-market-designs/9725" rel="noopener noreferrer"&gt;Proposer-Builder Separation (PBS)&lt;/a&gt; for Ethereum validators. It allows them to access a competitive block-building market and earn a fair share of the MEV extracted in the blocks they propose.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Searchers, solvers, and builders
&lt;/h3&gt;

&lt;p&gt;The MEV ecosystem on Ethereum involves several key participants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Searchers&lt;/strong&gt;: Participants who identify and exploit MEV opportunities using various strategies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solvers&lt;/strong&gt;: Participants that optimize and execute MEV strategies. They work closely with searchers to refine extraction processes, ensuring maximum efficiency and profitability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Builders&lt;/strong&gt;: Participants responsible for constructing bundles of transactions submitted to the network. They collaborate with searchers and solvers to assemble transactions in a way that maximizes extracted value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trading bots (searchers)
&lt;/h3&gt;

&lt;p&gt;Most MEV strategies are executed by automated trading bots that identify and exploit opportunities in real-time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arbitrage bots&lt;/strong&gt;: Monitor token prices across exchanges and protocols, executing trades to profit from differences and help ensure uniform prices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Front-running bots&lt;/strong&gt;: Place buy orders before executing trades to capitalize on price movements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Back-running bots&lt;/strong&gt;: Identify opportunities after specific transactions and quickly execute follow-ups to extract value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandwich bots&lt;/strong&gt;: Implement sandwich attacks by placing orders before and after large trades to profit from price impacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liquidation bots&lt;/strong&gt;: Monitor lending protocols for positions near liquidation thresholds, quickly executing liquidation transactions when conditions are met.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many of these trading bots are integrated within various MEV infrastructure platforms, aiming to reduce the risks of manipulative tactics.&lt;/p&gt;

&lt;h2&gt;
  
  
  MEV on Starknet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.starknet.io/" rel="noopener noreferrer"&gt;Starknet&lt;/a&gt; is an Ethereum Layer 2 (L2) designed to deliver high transaction throughput and low costs while maintaining Ethereum's core principles.&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%2Fv2kvg5vcm0suacmpy4oo.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%2Fv2kvg5vcm0suacmpy4oo.png" alt="Starknet Network Architecture" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Starknet operates as a Zero-Knowledge Rollup (ZK-Rollup), using a &lt;a href="https://starkware.co/wp-content/uploads/2022/05/STARK-paper.pdf" rel="noopener noreferrer"&gt;STARK proof&lt;/a&gt; to bundle transactions off-chain before submitting a single proof to the Ethereum mainnet. MEV on L2's like Starknet differs from L1 due to increased throughput, reduced transaction costs, First-Come-First-Serve (FCFS) model, account abstraction, and censorship resistance. Here's how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Higher TPS&lt;/strong&gt;: L2's process more transactions simultaneously, reducing MEV opportunities and lowering the profitability of front-running.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower transaction fees&lt;/strong&gt;: Reduced fees decrease the incentives for MEV extraction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-Come-First-Serve (FCFS) model&lt;/strong&gt;: The &lt;a href="https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-architecture-overview/#sequencers" rel="noopener noreferrer"&gt;Starknet sequencer&lt;/a&gt; processes transactions as they are received, eliminating the need for transaction reordering and mempool monitoring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account abstraction&lt;/strong&gt;: Starknet's native account abstraction allows anyone to handle transactions, minimizing exposure to MEV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Censorship resistance&lt;/strong&gt;: Starknet's design prevents entities from monopolizing MEV extraction, ensuring a fairer ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, MEV opportunities still exist on Starknet. The interaction between L1 and L2 creates complex transaction flows that are &lt;code&gt;"MEV-exploitable"&lt;/code&gt;, allowing searchers to capitalize on information and timing differences between these layers for profit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Profitable MEV strategies on L2s
&lt;/h2&gt;

&lt;p&gt;Due to the L2 design, MEV strategies that rely on gas fee manipulation are less effective. However, searchers are still exploring profitable strategies. Here are some notable ones:&lt;/p&gt;

&lt;h3&gt;
  
  
  Atomic arbitrage
&lt;/h3&gt;

&lt;p&gt;Atomic arbitrage involves profiting from price differences across exchanges and protocols (such as Ekubo and Nostra). The lower transaction fees and high TPS on L2s like Starknet make it easier and faster for bots to execute these arbitrage strategies efficiently. For a practical guide on creating an atomic arbitrage bot, check out &lt;a href="https://medium.com/@maksim.ryndin/how-to-create-an-atomic-arbitrage-bot-in-starknet-part-1-basics-418333ed9cd3" rel="noopener noreferrer"&gt;Maksim's blog&lt;/a&gt; and &lt;a href="https://lisot.to/posts/starknet-arbitrage-fundamentals/" rel="noopener noreferrer"&gt;Matteo's blog&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Liquidations
&lt;/h3&gt;

&lt;p&gt;MEV bots can profit from liquidations on lending protocols when collateral values drop below certain thresholds. When this happens, bots can quickly act to liquidate these positions for profit. For a practical guide on building a liquidation bot, check out &lt;a href="https://medium.com/@kristianaristi/liquidation-bot-on-zklend-starknet-part-1-introduction-who-is-borrowing-4d2631971a3a" rel="noopener noreferrer"&gt;Kristan's blog on ZKLend&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Statistical arbitrage
&lt;/h3&gt;

&lt;p&gt;This strategy uses statistical models to predict price movements and identify profitable trading opportunities. While it can be riskier, the high throughput and low transaction costs on L2s make it easier to execute effectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-layer sandwich attacks
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://arxiv.org/pdf/2405.00138" rel="noopener noreferrer"&gt;Cross-layer sandwich attacks&lt;/a&gt; involve monitoring interactions between L1 and L2 to place transactions that manipulate prices. Searchers can observe pending transactions on L1 and strategically place transactions on L2 to influence prices in their favor.&lt;/p&gt;

&lt;p&gt;All these strategies are possible on Ethereum and its L2s. However, many L2s are exploring MEV auctions and decentralized sequencers to mitigate MEV risks for end users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starknet ecosystem strategies and MEV mitigation
&lt;/h2&gt;

&lt;p&gt;Starknet actively employs strategies to create a fair ecosystem and mitigate MEV on the mainnet. The community is engaged in &lt;a href="https://collective.flashbots.net/t/it-s-time-to-talk-about-l2-mev/3593" rel="noopener noreferrer"&gt;healthy discussions and multiple initiatives&lt;/a&gt; focused on addressing MEV on Starknet.&lt;/p&gt;

&lt;p&gt;Starknet is improving TPS and performance by implementing parallel transactions, resulting in lower fees, reduced congestion, and fairer transactions.&lt;/p&gt;

&lt;p&gt;The community is also developing tools and engaging in conversations to address MEV's impact. Here are some notable ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Starknet Analyzer&lt;/strong&gt;: This repository is valuable for extracting and analyzing MEV-related data on Starknet. Check it out: &lt;a href="https://github.com/d-s-i/starknet-analyzer" rel="noopener noreferrer"&gt;https://github.com/d-s-i/starknet-analyzer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entro&lt;/strong&gt;: A Python package providing functionalities for Starknet on-chain exploration, analyzing Starknet contract data, and data backfilling. Check it out: &lt;a href="https://github.com/nethermindeth/entro" rel="noopener noreferrer"&gt;https://github.com/nethermindeth/entro&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking ahead, the future of L2s is promising, with the potential implementation of decentralized sequencers to decentralize the network and MEV auctions to reduce MEV risks.&lt;/p&gt;

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

&lt;p&gt;I hope this article has introduced you to the world of MEV on Ethereum and Starknet. You should now be able to compare the MEV dynamics between these layers and better understand how MEV works on Starknet.&lt;/p&gt;

&lt;p&gt;If you want to discuss MEV on Starknet or have valuable insights to share, join our &lt;a href="https://t.me/+TiNIOKAdIyQzNDg0" rel="noopener noreferrer"&gt;MEV discussion group&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This piece is part of a series exploring MEV on Starknet, so stay tuned for more insights and discussions in the upcoming articles.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>starknet</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Build and deploy a web app with Python, Flask, and Doppler</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Mon, 04 Oct 2021 22:57:07 +0000</pubDate>
      <link>https://dev.to/lordghostx/build-and-deploy-a-web-app-with-python-flask-and-doppler-9jm</link>
      <guid>https://dev.to/lordghostx/build-and-deploy-a-web-app-with-python-flask-and-doppler-9jm</guid>
      <description>&lt;p&gt;Picture this: You’re building an app that uses global configuration values (public and private keys, environment execution configurations, database credentials, domain names, and URLs), and you need to update them frequently. The first solution you’ll come up with is to manage your global values using ENV files. Still, soon enough, you’ll realize that this approach can be a burden and is unscalable, especially in a distributed architectural system.&lt;/p&gt;

&lt;p&gt;Suppose you found a solution that serves as a universal secrets manager and allows you to synchronize environment variables at scale efficiently. Would this help you solve your problem better than ENV files? The answer is YES, and the best solution for your issue is Doppler.&lt;/p&gt;

&lt;p&gt;This tutorial will teach you how to integrate Doppler into your apps and store your secrets with it. In this article, you will build and deploy a demo app with Python (Flask) and Heroku, then manage its secrets and environment variables using Doppler.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Doppler?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.doppler.com" rel="noopener noreferrer"&gt;Doppler&lt;/a&gt; is a universal secrets manager that allows you to efficiently synchronize environment variables across devices, environments, and team members. It will enable you to store, share, and access secrets from a centralized source with support for collaboration, access controls, versioning, secrets documentation, and many more.&lt;/p&gt;

&lt;h1&gt;
  
  
  Benefits of using Doppler
&lt;/h1&gt;

&lt;p&gt;Doppler provides many unique features and functionalities that make it more than just a storage for secrets. Here are some of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Doppler simplifies the synchronization of secrets and app configuration across devices, environments, and team members.&lt;/li&gt;
&lt;li&gt;Doppler allows your teams to collaborate and organize secrets across multiple projects and environments.&lt;/li&gt;
&lt;li&gt;Doppler helps developers automate the process of updating secrets in their apps across several locations.&lt;/li&gt;
&lt;li&gt;Doppler lets you deploy everywhere, be it Docker, serverless environments, or anywhere you work.&lt;/li&gt;
&lt;li&gt;Doppler boosts your team's productivity by removing the burden of keeping ENV files in sync.&lt;/li&gt;
&lt;li&gt;Doppler supports secrets versioning, meaning you can easily track changes in real-time and roll back broken changes.&lt;/li&gt;
&lt;li&gt;Doppler also lets you create documentation and notes for secrets values, so you know their usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Getting started with Doppler
&lt;/h1&gt;

&lt;p&gt;To continue with this tutorial, you need an account with Doppler. Create one on the &lt;a href="https://dashboard.doppler.com/register" rel="noopener noreferrer"&gt;Doppler website&lt;/a&gt; using your email address, Google account, or Secure SSO if you don't have one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a Doppler Project
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Projects&lt;/code&gt; are used in Doppler to universally organize and manage your secrets from local development to production.&lt;/p&gt;

&lt;p&gt;Click on the &lt;code&gt;Create Project&lt;/code&gt; button in the Doppler dashboard, as shown in the image below:&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%2Fcf66283ubismsh4yauak.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%2Fcf66283ubismsh4yauak.png" width="800" height="569"&gt;&lt;/a&gt;&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%2F51rqtpn80mvl9fhg47tg.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%2F51rqtpn80mvl9fhg47tg.png" width="800" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Store your secrets in Doppler
&lt;/h2&gt;

&lt;p&gt;To store secrets in Doppler, select the &lt;code&gt;Project&lt;/code&gt; you want to configure from your dashboard. Click on the &lt;code&gt;Project&lt;/code&gt; you created earlier:&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%2Ft3lcxd6jchevuy0s35xi.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%2Ft3lcxd6jchevuy0s35xi.png" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, choose the environment execution mode (development, staging, production) to configure your secrets. Select the &lt;code&gt;dev&lt;/code&gt; config:&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%2F92435fvtqd2yahczyy5o.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%2F92435fvtqd2yahczyy5o.png" width="800" height="261"&gt;&lt;/a&gt;&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%2Fun3utlfpzh21stelxvcn.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%2Fun3utlfpzh21stelxvcn.png" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, configure the &lt;code&gt;Project&lt;/code&gt; config and store secrets in it. Click on the &lt;code&gt;Add First Secret&lt;/code&gt; button to add secrets manually or the &lt;code&gt;Import Secrets&lt;/code&gt; button to fetch them from an ENV, JSON or YAML file.&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%2Fqzrdh730m31qo5xqnqcx.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%2Fqzrdh730m31qo5xqnqcx.png" width="800" height="348"&gt;&lt;/a&gt;&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%2Fktlzgixib2uh6rk25ntw.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%2Fktlzgixib2uh6rk25ntw.png" width="800" height="337"&gt;&lt;/a&gt;&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%2Fcq8m9uok0aiu3eg0zow0.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%2Fcq8m9uok0aiu3eg0zow0.png" width="800" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't forget to press the &lt;code&gt;Save&lt;/code&gt; button after adding/updating your secrets in Doppler.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3: Install the Doppler CLI
&lt;/h2&gt;

&lt;p&gt;The Doppler CLI is a lightweight binary that allows you to access your secrets in any environment (local, development, CI/CD, staging, production). Follow &lt;a href="https://docs.doppler.com/docs/enclave-installation#installation" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; to install it on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Authenticate the Doppler CLI
&lt;/h2&gt;

&lt;p&gt;To connect the Doppler CLI to your account and access the secrets of your &lt;code&gt;Projects&lt;/code&gt;, you need to be authenticated on it using an access token. Doppler CLI provides a &lt;code&gt;doppler login&lt;/code&gt; command to authenticate yourself via your browser (for local development).&lt;/p&gt;

&lt;p&gt;In the terminal, type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;doppler login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fe022cp7b1qblr28djgkw.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%2Fe022cp7b1qblr28djgkw.png" width="800" height="390"&gt;&lt;/a&gt;&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%2Fbxvd8n8e80y4e9s4axj2.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%2Fbxvd8n8e80y4e9s4axj2.png" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You only need to do this once per workplace. If you have multiple workplaces, you can &lt;a href="https://docs.doppler.com/docs/cli#authenticating-multiple-workplaces" rel="noopener noreferrer"&gt;scope each login&lt;/a&gt; to a separate directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 5: Set up a Doppler Project
&lt;/h2&gt;

&lt;p&gt;After installing and authenticating the Doppler CLI, you need to configure it with a &lt;code&gt;Project&lt;/code&gt; in your development environment to fetch its secrets. Doppler CLI provides a &lt;code&gt;doppler setup&lt;/code&gt; command to configure your app with a &lt;code&gt;Project&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Change the current directory to your app directory, then type the following in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ./your/project/directory  
doppler setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, select the &lt;code&gt;Project&lt;/code&gt; and &lt;code&gt;config&lt;/code&gt; you want to configure your app to use:&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%2Fts8f67pcu1r1mvr3bbdc.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%2Fts8f67pcu1r1mvr3bbdc.png" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can also use a &lt;code&gt;doppler.yaml&lt;/code&gt; file to pre-configure the Doppler &lt;code&gt;Project&lt;/code&gt; and &lt;code&gt;config&lt;/code&gt; for your app. Follow &lt;a href="https://docs.doppler.com/docs/enclave-installation#project-setup" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; to learn how.&lt;/p&gt;

&lt;p&gt;Doppler allows you to set up secrets for multiple projects on a single machine simultaneously by scoping them to specific directories.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 6: Inject Doppler into running processes
&lt;/h2&gt;

&lt;p&gt;After setting up the &lt;code&gt;Project&lt;/code&gt; and &lt;code&gt;config&lt;/code&gt; of your secrets for your app, you can inject your secrets as environment variables into running processes using &lt;code&gt;doppler run&lt;/code&gt;. Let’s see an example where we access our secrets from the Python shell.&lt;/p&gt;

&lt;p&gt;In your terminal, type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;doppler run &lt;span class="nt"&gt;--&lt;/span&gt; python3

import os  
print&lt;span class="o"&gt;(&lt;/span&gt;os.getenv&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"DB_URL"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;  
print&lt;span class="o"&gt;(&lt;/span&gt;os.getenv&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PAYMENT_KEY"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ft21ia62xf20d4z44yzxx.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%2Ft21ia62xf20d4z44yzxx.png" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, you launched a process (&lt;code&gt;python3&lt;/code&gt;) and injected your secrets (that we created earlier) into it using &lt;code&gt;doppler run&lt;/code&gt;. Then, you fetched the secrets from environment variables using &lt;code&gt;os.getenv()&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can learn more ways to inject Doppler into running processes from &lt;a href="https://docs.doppler.com/docs/enclave-installation#usage" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Setting up the Python app
&lt;/h1&gt;

&lt;p&gt;Now that you have successfully injected your secrets into a running process using Doppler, let's start building a Python (Flask) web app that uses the secrets you stored in Doppler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install the Flask web framework
&lt;/h2&gt;

&lt;p&gt;You need to install Flask on your machine. In the terminal, type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;Flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Create the Flask app
&lt;/h2&gt;

&lt;p&gt;Create a file named &lt;code&gt;app.py&lt;/code&gt; in the same directory you set up Doppler and save the following code in it:&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;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Start the app with Doppler
&lt;/h2&gt;

&lt;p&gt;Start the app using &lt;code&gt;doppler run&lt;/code&gt; to inject the secrets into the Flask server. In the terminal, type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;doppler run &lt;span class="nt"&gt;--&lt;/span&gt; python3 app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fipkwktrfd7ssd4lb3njx.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%2Fipkwktrfd7ssd4lb3njx.png" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you open the &lt;code&gt;http://127.0.0.1:5000&lt;/code&gt; URL in your browser, you will get a response like this:&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%2F3gcjnuyuyg0rsb1brosz.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%2F3gcjnuyuyg0rsb1brosz.png" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Integrating Doppler with Python and Flask
&lt;/h1&gt;

&lt;p&gt;Let's fetch the secrets from Doppler and use them in the Python (Flask) web app. Since Doppler injects secrets as environment variables, you can easily retrieve them using the built-in &lt;code&gt;os.getenv()&lt;/code&gt; function provided by Python like you would when using ENV files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Update the Flask app
&lt;/h2&gt;

&lt;p&gt;Update the &lt;code&gt;app.py&lt;/code&gt; you created earlier with the code below:&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;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&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;
    &amp;lt;h1&amp;gt;Doppler Secrets&amp;lt;/h1&amp;gt;

    &amp;lt;h3&amp;gt;DB_URL: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_URL&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/h3&amp;gt;
    &amp;lt;h3&amp;gt;API_HOST: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;API_HOST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/h3&amp;gt;
    &amp;lt;h3&amp;gt;PAYMENT_KEY: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PAYMENT_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/h3&amp;gt;
    &amp;lt;h3&amp;gt;ADMIN_USERNAME: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ADMIN_USERNAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/h3&amp;gt;
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Start the app with Doppler
&lt;/h2&gt;

&lt;p&gt;Start the app using &lt;code&gt;doppler run&lt;/code&gt; and open the &lt;code&gt;http://127.0.0.1:5000&lt;/code&gt; URL in your browser to confirm Doppler injected your secrets correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;doppler run &lt;span class="nt"&gt;--&lt;/span&gt; python3 app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fi73ert39t89ok2qz50dh.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%2Fi73ert39t89ok2qz50dh.png" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Update the secrets in Doppler
&lt;/h2&gt;

&lt;p&gt;Change the secrets from your Doppler dashboard to see how easy, efficient, and scalable the synchronization of your environment variables has become.&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%2Fknutmseph38js9sdzqb7.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%2Fknutmseph38js9sdzqb7.png" width="800" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Deploying the Flask app
&lt;/h1&gt;

&lt;p&gt;Doppler provides integrations for many cloud providers, including Heroku, AWS, Digital Ocean, Azure, Docker, GCP, &lt;a href="https://www.doppler.com/integrations" rel="noopener noreferrer"&gt;and many more&lt;/a&gt; to keep your secrets synchronized wherever you develop and deploy.&lt;/p&gt;

&lt;p&gt;Doppler also simplifies the whole cloud provider integration process, only requiring you to set things up with a couple of clicks. Let's see how to integrate Doppler with Heroku.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create an app in Heroku
&lt;/h2&gt;

&lt;p&gt;Login to your &lt;a href="https://id.heroku.com/login" rel="noopener noreferrer"&gt;Heroku dashboard&lt;/a&gt; and create a new app to deploy your Python (Flask) app.&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%2Fh37d4au88b4cqpqmvc4d.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%2Fh37d4au88b4cqpqmvc4d.png" width="800" height="485"&gt;&lt;/a&gt;&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%2Foe89hsw21ols2zjblxkb.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%2Foe89hsw21ols2zjblxkb.png" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Integrate Doppler with Heroku
&lt;/h2&gt;

&lt;p&gt;Head over to the &lt;code&gt;INTEGRATIONS&lt;/code&gt; tab in the &lt;code&gt;stg&lt;/code&gt; (staging) config setup of your Doppler &lt;code&gt;Project&lt;/code&gt;.&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%2Fxy2tf3z139phw3yx4iby.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%2Fxy2tf3z139phw3yx4iby.png" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't forget to configure your secrets in the &lt;code&gt;stg&lt;/code&gt; config of your &lt;code&gt;Project&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, click on the &lt;code&gt;Add Integration&lt;/code&gt; button and select Heroku from the list of cloud providers.&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%2Fbm2v69gcnnchvhjp3jjb.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%2Fbm2v69gcnnchvhjp3jjb.png" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, authorize Doppler to have access to your Heroku account.&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%2Fyhcshue4tc77g7ayicj3.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%2Fyhcshue4tc77g7ayicj3.png" width="800" height="944"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, complete the integration process by setting the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heroku Project Type: Either a Heroku &lt;code&gt;App&lt;/code&gt; or &lt;code&gt;Pipeline&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;App: The name of the Heroku app that you created earlier (&lt;code&gt;doppler-demo&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Config to sync: The config that Doppler should inject into your app (&lt;code&gt;stg&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Import Options: Whether to import previously configured environment variables in Heroku to Doppler.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click on the &lt;code&gt;Set Up Integration&lt;/code&gt; button after providing all the necessary information.&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%2Fvh4qv97zfblojgg4uq27.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%2Fvh4qv97zfblojgg4uq27.png" width="800" height="1004"&gt;&lt;/a&gt;&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%2F3a8kih7a9mtklo7s4o2q.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%2F3a8kih7a9mtklo7s4o2q.png" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You have successfully integrated Doppler with Heroku. Whenever you make changes (adding/updating) to your &lt;code&gt;Project&lt;/code&gt; secrets, Doppler will automatically synchronize them with your Heroku app's &lt;code&gt;Config Vars&lt;/code&gt;.&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%2F6uzt4119q3xunxp9qigx.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%2F6uzt4119q3xunxp9qigx.png" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Deploy your app to Heroku
&lt;/h2&gt;

&lt;p&gt;Deploy your app to Heroku as you would typically do.&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%2Fh8k2mxp7n2beok16pbam.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%2Fh8k2mxp7n2beok16pbam.png" width="800" height="522"&gt;&lt;/a&gt;&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%2Fv064aj8bz0ics8moq4rf.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%2Fv064aj8bz0ics8moq4rf.png" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;By integrating Doppler with Python (Flask) and Heroku, you built and deployed a web app with efficient and scalable secrets management using minimal effort. You saw how to store, share, and access secrets using &lt;a href="https://www.doppler.com" rel="noopener noreferrer"&gt;Doppler&lt;/a&gt; and integrate your &lt;code&gt;Project&lt;/code&gt; with a cloud provider.&lt;/p&gt;

&lt;p&gt;You can also learn more about Doppler from the &lt;a href="https://docs.doppler.com/docs" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. If you have any questions, contact me on Twitter: &lt;a href="https://twitter.com/LordGhostX" rel="noopener noreferrer"&gt;@LordGhostX&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Streaming Fauna Documents with Python</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Fri, 30 Jul 2021 18:44:53 +0000</pubDate>
      <link>https://dev.to/lordghostx/streaming-fauna-documents-with-python-18c3</link>
      <guid>https://dev.to/lordghostx/streaming-fauna-documents-with-python-18c3</guid>
      <description>&lt;p&gt;With Fauna’s document streaming feature, you can get real-time updates about changes made to your database. &lt;/p&gt;

&lt;p&gt;In this tutorial, you will learn how to use Fauna’s document streaming feature in a Python application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here for the code alone? Head over to the &lt;a href="//#h.yqdu04ukzkz1"&gt;implementation section&lt;/a&gt; of this article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

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

&lt;p&gt;Streaming refers to when a program continuously reads and fetches data from a given source in real-time. For example, while watching a YouTube video or downloading a file from the internet, you stream the data from the origin and process it on your client’s device instantaneously.&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%2Fs5h55hnzrab1bhowmlxm.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%2Fs5h55hnzrab1bhowmlxm.png" width="773" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Streaming, in some ways, can arguably be a better alternative to polling. Polling refers to when a client periodically makes queries to a data source to get updates. It is more expensive than streaming as the client sends many requests only to get a single update or none at all. Polling is only aware of changes when the query results return.&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%2Fg1m9etlwcigbalgp4tnn.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%2Fg1m9etlwcigbalgp4tnn.png" width="753" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://fauna.com/" rel="noopener noreferrer"&gt;Fauna&lt;/a&gt; is a flexible database delivered as a secure data API providing two interfaces: GraphQL and the Fauna Query Language (FQL). It offers functionality to store collections, indexes, and other databases. To learn more about Fauna, visit the &lt;a href="https://docs.fauna.com/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: The rest of this article assumes you have a fair understanding of Fauna and Python. Check out my &lt;a href="https://dev.to/lordghostx/building-a-telegram-bot-with-python-and-fauna-494i"&gt;introductory tutorial&lt;/a&gt; first if you don't.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Setting up our Fauna database
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Creating the Fauna database
&lt;/h2&gt;

&lt;p&gt;We need to first create the database to use in Fauna’s dashboard. If you have not created an account on Fauna before now, &lt;a href="https://dashboard.fauna.com/accounts/register" rel="noopener noreferrer"&gt;do so here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the dashboard, click on the &lt;code&gt;NEW DATABASE&lt;/code&gt; button, provide a name for the database, then press &lt;code&gt;SAVE.&lt;/code&gt; We will also be ticking the &lt;code&gt;Pre-populate&lt;/code&gt; option to get demo data that will be used in this article:&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%2Fgsgmiu8a20uhltha7560.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%2Fgsgmiu8a20uhltha7560.png" width="800" height="526"&gt;&lt;/a&gt;&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%2Fwjyrjch8ws5q4nlnsd2q.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%2Fwjyrjch8ws5q4nlnsd2q.png" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate the database security key
&lt;/h2&gt;

&lt;p&gt;Then, we need to create a security key to connect the database to the application. Go to the &lt;code&gt;Security&lt;/code&gt; tab on the Fauna sidebar (located on the left side of the screen), click the &lt;code&gt;NEW KEY&lt;/code&gt; button, provide the necessary information, and press &lt;code&gt;SAVE:&lt;/code&gt;&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%2F07rfqvz5d6ovfzhts2t4.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%2F07rfqvz5d6ovfzhts2t4.png" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fauna will then present you with your &lt;code&gt;Secret Key.&lt;/code&gt; Copy the key immediately and store it somewhere easily retrievable because it will only be displayed once.&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementing document streaming with Python
&lt;/h1&gt;

&lt;p&gt;Fauna features built-in support for document streaming. Whenever changes in a particular document are streamed, all the clients subscribed to it will be notified in real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing our Fauna client
&lt;/h2&gt;

&lt;p&gt;Let’s write some code to implement this functionality!.&lt;/p&gt;

&lt;p&gt;First, we will install the Fauna Python driver, importing the required libraries, and creating a database client.&lt;/p&gt;

&lt;p&gt;In the terminal, type:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;After that, create a Python script and save the code below in it:&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;from&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;faunadb&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;  
&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ref&lt;/span&gt;  
&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;faunadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;FaunaClient&lt;/span&gt;  

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FaunaClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAUNA_SECRET_KEY&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;h2&gt;
  
  
  Selecting a document to stream
&lt;/h2&gt;

&lt;p&gt;Next, we will fetch the document from the Fauna database collections that we want to stream:&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%2Fs1km54sq0hmb8d1rp9un.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%2Fs1km54sq0hmb8d1rp9un.png" width="800" height="386"&gt;&lt;/a&gt;&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="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;q&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="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customers&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;101&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating an OnStart function
&lt;/h2&gt;

&lt;p&gt;We will start by defining an &lt;code&gt;on_start&lt;/code&gt; function, which will be triggered when a document stream starts:&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;def&lt;/span&gt; &lt;span class="nf"&gt;on_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&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;started stream at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txn&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;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&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;firstName&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;John&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;lastName&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;Smith&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;telephone&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;719-872-4470&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ref&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;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our &lt;code&gt;on_start&lt;/code&gt; function, we printed out the current timestamp of the transaction emitting the event (in microseconds) provided by &lt;code&gt;event.txn.&lt;/code&gt; Then, the streamed document, so Fauna notifies our application in real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an OnVersion function
&lt;/h2&gt;

&lt;p&gt;Next, we will define an &lt;code&gt;on_version&lt;/code&gt; function. It will be triggered when there is a change in the streamed document and Fauna has sent a notification to the subscribing application:&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;def&lt;/span&gt; &lt;span class="nf"&gt;on_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&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;on_version event at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txn&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;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;Event action: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&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;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;Changes made: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;diff&lt;/span&gt;&lt;span class="sh"&gt;'&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;data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&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;In our &lt;code&gt;on_version&lt;/code&gt; function, we printed out the current timestamp again (in microseconds), then printed out the event action provided by &lt;code&gt;event.event['action'].&lt;/code&gt; We then printed out the changes made to the document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an OnError function
&lt;/h2&gt;

&lt;p&gt;After that, we will define an &lt;code&gt;on_error&lt;/code&gt; function. It will be triggered when an error occurs while processing the data in the &lt;code&gt;on_version:&lt;/code&gt;&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;def&lt;/span&gt; &lt;span class="nf"&gt;on_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&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;Received error event &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&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;In our &lt;code&gt;on_error&lt;/code&gt; function, we printed out the event that triggered the issue along with its error message.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting the document streaming
&lt;/h2&gt;

&lt;p&gt;We will now begin  document streaming:&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="n"&gt;options&lt;/span&gt; &lt;span class="o"&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;fields&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;document&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;diff&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;action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ref&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, we defined the fields we want in every event update. Then, we passed the &lt;code&gt;on_start,&lt;/code&gt; &lt;code&gt;on_error,&lt;/code&gt; and &lt;code&gt;on_version&lt;/code&gt; functions to the stream object and triggered it with the &lt;code&gt;start&lt;/code&gt; method. &lt;/p&gt;

&lt;p&gt;You should get an image like the one below when the entire script executes:&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%2Fq658zoc9xxgyh4o4og3x.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%2Fq658zoc9xxgyh4o4og3x.png" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: You can stop active streams using the &lt;code&gt;stream.close()&lt;/code&gt; method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  A few things to note
&lt;/h1&gt;

&lt;p&gt;At the time of writing, Fauna’s document streaming is still an Early Access feature. Hence there are some limitations to using it, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You cannot have more than 100 active stream connections to Fauna from a single client device.&lt;/li&gt;
&lt;li&gt;Document streaming is currently not supported in Node.js clients due to an HTTP/2 implementation issue.&lt;/li&gt;
&lt;li&gt;You can only stream Fauna documents. It is not possible to stream collections or any schema document.&lt;/li&gt;
&lt;li&gt;Streams can only report events to the fields and values within a document’s &lt;code&gt;data&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;There is currently no support for GraphQL subscriptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this article, we learned about Fauna’s document streaming capabilities and how easy it is to integrate Fauna’s document streaming into a Python application.&lt;/p&gt;

&lt;p&gt;You can learn more about Fauna document streaming from the &lt;a href="https://docs.fauna.com/fauna/current/drivers/streaming.html" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. If you have any questions, don't hesitate to contact me on Twitter: &lt;a href="https://twitter.com/LordGhostX" rel="noopener noreferrer"&gt;@LordGhostX&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>fauna</category>
      <category>database</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building a Contact Manager with Python, Flask, and HarperDB</title>
      <dc:creator>LordGhostX</dc:creator>
      <pubDate>Wed, 02 Jun 2021 19:45:13 +0000</pubDate>
      <link>https://dev.to/lordghostx/building-a-contact-manager-with-python-flask-and-harperdb-1h53</link>
      <guid>https://dev.to/lordghostx/building-a-contact-manager-with-python-flask-and-harperdb-1h53</guid>
      <description>&lt;h1&gt;
  
  
  What is HarperDB?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://studio.harperdb.io/sign-up?utm_source=solomon" rel="noopener noreferrer"&gt;HarperDB&lt;/a&gt; is an easy database solution that helps collect, distribute, and analyze data throughout your organization. It provides unmatched flexibility, speed, security, and value for every data use case your organization and project require.&lt;/p&gt;

&lt;h1&gt;
  
  
  Benefits of Using HarperDB in Your Next Project
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Seamless integration into any project and tool using a straightforward REST API. It also comes with support for multiple languages via various drivers and plugins.&lt;/li&gt;
&lt;li&gt;HarperDB provides the ability to run your database anywhere, ranging from edge to cloud and anywhere in between.&lt;/li&gt;
&lt;li&gt;Support for executing complex, performant, ACID-compliant SQL queries on JSON with no data duplication.&lt;/li&gt;
&lt;li&gt;Functionality to search databases with JSON filters and SQL queries without the need of an ORM.&lt;/li&gt;
&lt;li&gt;You enjoy the flexibility of a NoSQL database with the security, consistency, and durability of an RDBMS by leveraging a dynamic schema with attribute level and role-based security in a single storage engine.&lt;/li&gt;
&lt;li&gt;HarperDB Studio offers a sleek and intuitive management UI that allows you to browse, query, and manage data all in one place, with no coding required.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Getting Started with HarperDB
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Creating the HarperDB Database Instance
&lt;/h2&gt;

&lt;p&gt;We need to create a database for the contact manager. If you have not created an account on HarperDB before now, create one on &lt;a href="https://studio.harperdb.io/sign-up?utm_source=solomon" rel="noopener noreferrer"&gt;HarperDB’s website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the dashboard, click on &lt;code&gt;Create New HarperDB Cloud Instance&lt;/code&gt; as shown in the image below.&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%2Fx20gtfhfpd6y5dgrvieg.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%2Fx20gtfhfpd6y5dgrvieg.png" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, select a database instance type. A HarperDB instance is where you host your database. It can either be local (user-installed instance) or configured and managed on HarperDB servers (cloud instance). In this tutorial, we will be using the cloud instance.&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%2Fzdwatm8tuiuqfw5hu6cx.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%2Fzdwatm8tuiuqfw5hu6cx.png" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will need to provide information about your cloud instance, like name and authentication credentials. Click on the &lt;code&gt;Instance Details&lt;/code&gt; button after supplying this information.&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%2F36n1g53vovrx6pp79y1q.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%2F36n1g53vovrx6pp79y1q.png" width="800" height="728"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Store the credentials somewhere secure and easily retrievable as we will need them in later parts of this tutorial.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You are also required to provide the specification of the cloud instance. HarperDB allows you to choose the RAM, storage size, and region your instance should have.&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%2Fhc95trszs9rsncquue6u.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%2Fhc95trszs9rsncquue6u.png" width="800" height="1077"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have provided all the configuration details for the cloud instance, click on the &lt;code&gt;Confirm Instance Details&lt;/code&gt; button, then finalize everything to create it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: Cloud instances take several minutes to create. You’ll need to wait throughout this process. HarperDB also sends notifications via email on the instance creation status.&lt;/p&gt;
&lt;/blockquote&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%2Fa1esdhzd4ipe23zf8g18.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%2Fa1esdhzd4ipe23zf8g18.png" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Database Schemas
&lt;/h2&gt;

&lt;p&gt;Let’s set up the necessary database &lt;code&gt;schema&lt;/code&gt; for our application. A &lt;code&gt;schema&lt;/code&gt; is a collection of tables in HarperDB, analogous to a database in SQL. Without schemas, you cannot store data in the database.&lt;/p&gt;

&lt;p&gt;To create a schema, first select the cloud instance in your dashboard, navigate to the &lt;code&gt;schemas&lt;/code&gt; section by the left, and then provide a name for it. In this tutorial, we will be using the name &lt;code&gt;contacts_repo&lt;/code&gt; as displayed in the image below:&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%2Ffqmedmlrrsom79jm9pqa.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%2Ffqmedmlrrsom79jm9pqa.png" width="702" height="392"&gt;&lt;/a&gt;&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%2Fjz4npej2r7pcz8s5s2js.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%2Fjz4npej2r7pcz8s5s2js.png" width="736" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Schema Tables
&lt;/h2&gt;

&lt;p&gt;Let’s set up &lt;code&gt;tables&lt;/code&gt; in our database schema. A &lt;code&gt;table&lt;/code&gt; is analogous to &lt;code&gt;tables&lt;/code&gt; in SQL databases like MySQL and &lt;code&gt;collections&lt;/code&gt; in NoSQL databases like MongoDB.&lt;/p&gt;

&lt;p&gt;To create a table. First, navigate to the &lt;code&gt;tables&lt;/code&gt; section by the left side of your dashboard, then provide a name and &lt;code&gt;hash_attribute&lt;/code&gt; for it. A &lt;code&gt;hash_attribute&lt;/code&gt; identifies every record in the database uniquely, and it is synonymous with &lt;code&gt;Primary Keys&lt;/code&gt; in a relational database.&lt;/p&gt;

&lt;p&gt;Here, we will set the name to &lt;code&gt;contacts&lt;/code&gt; and &lt;code&gt;hash_attribute&lt;/code&gt; to &lt;code&gt;contact_id&lt;/code&gt; as shown in the image below:&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%2Fmy0xs0o44kukw62gulny.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%2Fmy0xs0o44kukw62gulny.png" width="770" height="610"&gt;&lt;/a&gt;&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%2Ft2vgu71r45z6v1gdlnts.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%2Ft2vgu71r45z6v1gdlnts.png" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting Up the Demo Application
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Cloning the Contact Manager Repository
&lt;/h2&gt;

&lt;p&gt;For the sake of convenience, I have written the user interface of the contact manager (with Flask and Bootstrap) that we will use in this article. To get started, you will need to clone &lt;a href="https://github.com/LordGhostX/harperdb-contact-manager" rel="noopener noreferrer"&gt;my repository&lt;/a&gt; and initialize the app like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/LordGhostX/harperdb-contact-manager
&lt;span class="nb"&gt;cd &lt;/span&gt;harperdb-contact-manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fa4ahfl5ffpog51loy8ob.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%2Fa4ahfl5ffpog51loy8ob.png" width="596" height="744"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;user-interface&lt;/code&gt; directory contains only the user interface of the contact manager. In contrast, the &lt;code&gt;full-application&lt;/code&gt; directory contains the entire application (HarperDB + Python + Flask) that we will build in this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing the Project’s Requirements
&lt;/h2&gt;

&lt;p&gt;You need to install the contact manager’s requirements before you can run it. In your terminal, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;user-interface  
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the application to make sure it’s working. In your terminal, type:&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%2Fewfymxxmsotxz3gz45w5.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%2Fewfymxxmsotxz3gz45w5.png" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To view the user interface of our application, head to your browser and open the URL &lt;code&gt;http://127.0.0.1:5000&lt;/code&gt;, you should get a response similar to the image below:&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%2F9ybmqika6sn4wvllqcm4.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%2F9ybmqika6sn4wvllqcm4.png" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Integrating HarperDB with Python and Flask
&lt;/h1&gt;

&lt;p&gt;Now that we have set up the base application and database schemas, let’s move to communicating with the database using Python, as shown in the &lt;a href="https://github.com/HarperDB/harperdb-sdk-python" rel="noopener noreferrer"&gt;SDK documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing HarperDB Python SDK
&lt;/h2&gt;

&lt;p&gt;We need to get the Python SDK for HarperDB. It provides functionalities that allow an application to make queries to the HarperDB database instance. It’s available on pip, making it installable with a single command in the terminal.&lt;/p&gt;

&lt;p&gt;In the terminal, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;harperdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring HarperDB Python SDK
&lt;/h2&gt;

&lt;p&gt;We need to import the HarperDB SDK into our Flask application to use it. To do this, add the following code to the &lt;code&gt;app.py&lt;/code&gt; file:&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;harperdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also have to initialize the Python SDK client with the database instance authentication credentials we saved earlier. Add the following code to the &lt;code&gt;app.py&lt;/code&gt; file right after initializing the Flask app.&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="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;harperdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HarperDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HARPERDB_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HARPERDB_USERNAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HARPERDB_PASSWORD&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;blockquote&gt;
&lt;p&gt;Note: Don’t forget to replace the credentials placeholders with the appropriate values for your application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;HARPERDB_URL&lt;/code&gt; is present in the HarperDB dashboard, where all the database instances are displayed.&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%2Fbg29y116ui5s8uc5v4i1.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%2Fbg29y116ui5s8uc5v4i1.png" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the HarperDB Database Connection
&lt;/h2&gt;

&lt;p&gt;To test our HarperDB cloud instance and credentials, we will be querying our database for its description. To do this, add the block of code below right before running the application in the &lt;code&gt;app.py&lt;/code&gt; file.&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe_all&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F36ct1ash8a5nzjsd087a.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%2F36ct1ash8a5nzjsd087a.png" width="800" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the &lt;code&gt;app.py&lt;/code&gt; file. If you get a response like an image below, the configuration is correct. If you don’t, check if your credentials are valid and correct.&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%2Fv4nt7mafk9hr5xmcpp5a.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%2Fv4nt7mafk9hr5xmcpp5a.png" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Making Queries to HarperDB
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Creating New Documents in HarperDB
&lt;/h2&gt;

&lt;p&gt;To create new documents in our HarperDB schema, we need to run an &lt;code&gt;INSERT&lt;/code&gt; query in the database via the Python SDK. HarperDB provides two methods to do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The SQL way: This involves running a SQL query to insert data into the database.&lt;/li&gt;
&lt;li&gt;The NoSQL way: This involves using the &lt;code&gt;insert&lt;/code&gt; method of the Python SDK to insert data into the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is sample Python code to demonstrate both methods:&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="c1"&gt;# SQL way
&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSERT INTO contacts_repo.contacts (name, email) VALUES (&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;LordGhostX&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lordghostx@email.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# NoSQL way
&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts_repo&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;contacts&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;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;LordGhostX&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;email&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;lordghostx@email.com&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;blockquote&gt;
&lt;p&gt;NOTE: If you omit the &lt;code&gt;hash_attribute&lt;/code&gt; metadata when executing an &lt;code&gt;INSERT&lt;/code&gt; query, HarperDB will automatically generate one for you and store it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code above executes an &lt;code&gt;INSERT&lt;/code&gt; query to your HarperDB cloud database. It creates a document in the &lt;code&gt;contacts&lt;/code&gt; table, in the &lt;code&gt;contacts_repo&lt;/code&gt; schema with the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt; metadata.&lt;/p&gt;

&lt;p&gt;We can integrate this into our contact manager by updating the &lt;code&gt;contacts&lt;/code&gt; route with the code below:&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="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/contacts/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&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;GET&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;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&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;action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;contact_data&lt;/span&gt; &lt;span class="o"&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="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&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;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="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;job&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&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;job&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="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&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;email&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="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&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;phone&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="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&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="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;addContact&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts_repo&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;contacts&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="n"&gt;contact_data&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="nf"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully added new contact&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;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts.html&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;&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%2Ft79id6vnfbizhvdsygww.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%2Ft79id6vnfbizhvdsygww.png" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading Documents from HarperDB
&lt;/h2&gt;

&lt;p&gt;To read documents from our HarperDB tables, we need to run a &lt;code&gt;SELECT&lt;/code&gt; or &lt;code&gt;SEARCH&lt;/code&gt; query in the database via the Python SDK. HarperDB provides two methods to do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The SQL way: This involves running a SQL query to select the data from the database.&lt;/li&gt;
&lt;li&gt;The NoSQL way: This involves using either the &lt;code&gt;search_by_hash&lt;/code&gt; or &lt;code&gt;search_by_value&lt;/code&gt; methods of the Python SDK to select data from the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is sample Python code to demonstrate both methods:&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="c1"&gt;# SQL way
&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM contacts_repo.contacts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# NoSQL way
&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search_by_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts_repo&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;contacts&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;hash_attribute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# returns all documents with the specified hash attributes
&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search_by_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts_repo&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;contacts&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;LordGhostX&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# returns all documents with the specified values
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above executes a &lt;code&gt;SELECT&lt;/code&gt; and &lt;code&gt;SEARCH&lt;/code&gt; query to your HarperDB cloud database. It fetches all the documents in the &lt;code&gt;contacts&lt;/code&gt; table, in the &lt;code&gt;contacts_repo&lt;/code&gt; schema with the specified hash attributes or values.&lt;/p&gt;

&lt;p&gt;We can integrate this into our contact manager by updating the rendering of the &lt;code&gt;contacts&lt;/code&gt; route in the &lt;code&gt;app.py&lt;/code&gt; file with the code below:&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="n"&gt;contacts_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM contacts_repo.contacts ORDER BY name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contacts_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;contacts_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ft3m1ceub30pqsa5t0n7o.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%2Ft3m1ceub30pqsa5t0n7o.png" width="800" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also need to update the contacts page to render the data fetched from the HarperDB request. Update the contacts table body &lt;code&gt;&amp;lt;tbody&amp;gt;&lt;/code&gt; in the &lt;code&gt;contacts.html&lt;/code&gt; file with the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
  {% for contact in contacts_data %}
  &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"contactName-{{ contact.contact_id }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ contact.name }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"contactEmail-{{ contact.contact_id }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ contact.email }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"contactPhone-{{ contact.contact_id }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ contact.phone }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"contactJob-{{ contact.contact_id }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ contact.job }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-primary"&lt;/span&gt; &lt;span class="na"&gt;data-toggle=&lt;/span&gt;&lt;span class="s"&gt;"modal"&lt;/span&gt; &lt;span class="na"&gt;data-target=&lt;/span&gt;&lt;span class="s"&gt;"#contactModal"&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"displayContactInfo('{{ contact.contact_id }}')"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;View Details&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  {% endfor %}
&lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fxrd46pn332eayyxusqza.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%2Fxrd46pn332eayyxusqza.png" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating Documents in HarperDB
&lt;/h2&gt;

&lt;p&gt;To update documents in our HarperDB tables, we need to run an &lt;code&gt;UPDATE&lt;/code&gt; query in the database via the Python SDK. HarperDB provides two methods to do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The SQL way: This involves running a SQL query to update the data in the database.&lt;/li&gt;
&lt;li&gt;The NoSQL way: This involves using the &lt;code&gt;update&lt;/code&gt; method of the Python SDK to update data in the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is sample Python code to demonstrate both methods:&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="c1"&gt;# SQL way
&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPDATE contacts_repo.contacts SET email=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lordghostx@newemail.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; WHERE contact_id=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sample_hash_attribute&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# NoSQL way
&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts_repo&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;contacts&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;contact_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;sample_hash_attribute&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;email&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;lordghostx@newemail.com&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;The code above executes an &lt;code&gt;UPDATE&lt;/code&gt; query to your HarperDB cloud database. It updates the document in the &lt;code&gt;contacts&lt;/code&gt; table, in the &lt;code&gt;contacts_repo&lt;/code&gt; schema with the specified hash attributes with the new values supplied.&lt;/p&gt;

&lt;p&gt;We can integrate this into our contact manager by updating the action handling in the &lt;code&gt;contacts&lt;/code&gt; route with the code below:&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;if&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;updateContact&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;contact_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;contact_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&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;contactID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts_repo&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;contacts&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="n"&gt;contact_data&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully updated contact information&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;success&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;&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%2Fc1k9ti0jt9wdumw7612o.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%2Fc1k9ti0jt9wdumw7612o.png" width="800" height="583"&gt;&lt;/a&gt;&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%2F2sqxk8a3ibf93acgx93b.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%2F2sqxk8a3ibf93acgx93b.png" width="800" height="422"&gt;&lt;/a&gt;&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%2Fltvdxfwn5btr3tps5m5o.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%2Fltvdxfwn5btr3tps5m5o.png" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting Documents from HarperDB
&lt;/h2&gt;

&lt;p&gt;To delete documents from our HarperDB tables, we need to run a &lt;code&gt;DELETE&lt;/code&gt; query in the database via the Python SDK. HarperDB provides two methods to do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The SQL way: This involves running a SQL query to delete the data from the database.&lt;/li&gt;
&lt;li&gt;The NoSQL way: This involves using the &lt;code&gt;delete&lt;/code&gt; method of the Python SDK to delete data from the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is sample Python code to demonstrate both methods:&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="c1"&gt;# SQL way
&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DELETE FROM contacts_repo.contacts WHERE name=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;LordGhostX&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# NoSQL way
&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts_repo&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;contacts&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;sample_hash_attribute&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;The code above executes a &lt;code&gt;DELETE&lt;/code&gt; query to your HarperDB cloud database. It deletes the document in the &lt;code&gt;contacts&lt;/code&gt; table, in the &lt;code&gt;contacts_repo&lt;/code&gt; schema with the specified &lt;code&gt;hash_attribute&lt;/code&gt;, or has the value &lt;code&gt;LordGhostX&lt;/code&gt; in the &lt;code&gt;name&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;We can integrate this into our contact manager by updating the &lt;code&gt;logout&lt;/code&gt; route with the code below:&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="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/contacts/delete/&amp;lt;string:contact_id&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_contact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contact_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts_repo&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;contacts&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="n"&gt;contact_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully deleted contact information&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;success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contacts&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;&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%2Fzq33tr58ggecxug58sy4.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%2Fzq33tr58ggecxug58sy4.png" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;By integrating HarperDB with Python and Flask, we built a contact manager with CRUD functionalities with minimal effort. We saw how to create cloud databases, manage them, and execute queries using HarperDB.&lt;/p&gt;

&lt;p&gt;The source code of the contact manager is available on &lt;a href="https://github.com/LordGhostX/harperdb-contact-manager" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. It was exciting integrating HarperDB into a Flask application, and I can’t wait to see the amazing things you create with it!&lt;/p&gt;

&lt;p&gt;If you have any questions, don't hesitate to contact me on Twitter: &lt;a href="https://twitter.com/LordGhostX" rel="noopener noreferrer"&gt;@LordGhostX&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>database</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
