<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Benjamin Bourgeois</title>
    <description>The latest articles on Forem by Benjamin Bourgeois (@bengeois).</description>
    <link>https://forem.com/bengeois</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%2F469420%2F047dc4ba-f9c6-4b06-8ba7-64a282370741.png</url>
      <title>Forem: Benjamin Bourgeois</title>
      <link>https://forem.com/bengeois</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bengeois"/>
    <language>en</language>
    <item>
      <title>🤖 Comment structurer la mémoire de vos agents avec Google ADK</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Fri, 03 Apr 2026 13:09:58 +0000</pubDate>
      <link>https://forem.com/techtown-fr/comment-structurer-la-memoire-de-vos-agents-avec-google-adk-2o58</link>
      <guid>https://forem.com/techtown-fr/comment-structurer-la-memoire-de-vos-agents-avec-google-adk-2o58</guid>
      <description>&lt;p&gt;Le plus gros défi avec les LLMs, c'est qu'ils sont fondamentalement « stateless ». Sans une couche de gestion de session et de mémoire, chaque requête est une page blanche. Pour un développeur, la difficulté est de savoir &lt;strong&gt;quoi stocker&lt;/strong&gt;, &lt;strong&gt;où le stocker&lt;/strong&gt; et &lt;strong&gt;combien de temps&lt;/strong&gt; le garder.&lt;/p&gt;

&lt;p&gt;Pour transformer un simple chatbot en un agent intelligent, il faut mettre en place une architecture de contexte. &lt;a href="https://google.github.io/adk-docs/" rel="noopener noreferrer"&gt;Agent Development Kit&lt;/a&gt; (ADK) de Google répond à ce besoin en structurant la persistance autour de trois piliers : la &lt;strong&gt;Session&lt;/strong&gt;, le &lt;strong&gt;State&lt;/strong&gt; et la &lt;strong&gt;Memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;En maîtrisant ces concepts, vous permettez à votre agent d'apprendre de ses interactions et de devenir plus pertinent au fil du temps, tout en gérant intelligemment la fenêtre de contexte limitée des modèles.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏗️ Architecture du contexte dans ADK
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🚦 Session, State et Memory
&lt;/h3&gt;

&lt;p&gt;Il est crucial de différencier ces trois piliers pour ne pas surcharger la mémoire de travail de l'agent :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;« &lt;strong&gt;Session&lt;/strong&gt; » : Le conteneur de la discussion actuelle (le « thread »). Elle contient la liste chronologique des événements.&lt;/li&gt;
&lt;li&gt;« &lt;strong&gt;State&lt;/strong&gt; » : Le « bloc-notes » temporaire. On y stocke des données de travail (ex: un panier d'achat) qui disparaissent ou s'archivent à la fin de la discussion.&lt;/li&gt;
&lt;li&gt;« &lt;strong&gt;Memory&lt;/strong&gt; » : La bibliothèque d'archives inter-sessions. Elle est consultable via une recherche sémantique pour ramener du contexte passé dans le présent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🧠 Mémoire court-terme vs long-terme
&lt;/h3&gt;

&lt;p&gt;Pour concevoir un agent performant, il faut séparer les flux comme le fait le cerveau humain :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Short-Term Memory (Sessions &amp;amp; State)&lt;/strong&gt; : Mémoire de travail active uniquement durant la conversation en cours . Elle sert à suivre la progression ou stocker des calculs intermédiaires. Une fois la session fermée, cette mémoire disparaît (ou est envoyée vers l'archivage).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-Term Memory (Memory Bank)&lt;/strong&gt; : Elle ne contient pas le texte brut, mais des faits consolidés (ex: « L'utilisateur préfère Python »). L'agent consulte cette archive au début de chaque nouvelle session pour ne pas repartir de zéro.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🔄 SessionService : Garantir la continuité
&lt;/h3&gt;

&lt;p&gt;L'objet &lt;strong&gt;Session&lt;/strong&gt; est le composant fondamental du suivi. Sans lui, chaque interaction repartirait de zéro.&lt;/p&gt;

&lt;p&gt;Une session se définit par plusieurs propriétés clés :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identification&lt;/strong&gt; : Elle lie un identifiant unique (&lt;code&gt;id&lt;/code&gt;), un nom d'application (&lt;code&gt;app_name&lt;/code&gt;) et un identifiant utilisateur (&lt;code&gt;userId&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historique&lt;/strong&gt; (&lt;code&gt;events&lt;/code&gt;) : Une séquence chronologique de tous les objets Event (messages utilisateur, réponses de l'agent, appels d'outils) survenue dans ce thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;État&lt;/strong&gt; (&lt;code&gt;state&lt;/code&gt;) : Un dictionnaire de données temporaires servant de « bloc-notes » à l'agent durant l'interaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suivi d'activité&lt;/strong&gt; (&lt;code&gt;lastUpdateTime&lt;/code&gt;) : Un horodatage indiquant la dernière interaction dans la session.&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%2F10q8tlghfqpf3109g77s.webp" 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%2F10q8tlghfqpf3109g77s.webp" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Le choix du service dépend de votre besoin de persistance et de contrôle :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Persistance&lt;/th&gt;
&lt;th&gt;Usage recommandé&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;InMemorySessionService&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nulle&lt;/td&gt;
&lt;td&gt;Développement local et tests unitaires.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VertexAiSessionService&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Élevée&lt;/td&gt;
&lt;td&gt;Production managée sur Google Cloud.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DatabaseSessionService&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Élevée&lt;/td&gt;
&lt;td&gt;Contrôle total sur votre propre base (PostgreSQL, SQLite).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Le Rewind : Annuler et corriger&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Le Rewind permet de faire revenir une session à un état précédent via un &lt;code&gt;invocation_id&lt;/code&gt;. Cela restaure le &lt;strong&gt;State&lt;/strong&gt; tel qu'il était avant une erreur de l'agent, permettant de repartir sur une base saine sans perdre tout l'historique.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  📝 State : Le bloc-notes dynamique de l'agent
&lt;/h3&gt;

&lt;p&gt;Dans ADK, l'attribut state d'une session est un dictionnaire clé-valeur servant de mémoire de travail. Contrairement à l'historique complet des événements, il stocke des détails structurés nécessaires au tour de conversation actuel (ex: statut d'authentification, étape d'un formulaire).&lt;/p&gt;

&lt;h4&gt;
  
  
  💡 Gestion de la portée via les préfixes
&lt;/h4&gt;

&lt;p&gt;ADK utilise des &lt;strong&gt;préfixes&lt;/strong&gt; pour définir automatiquement la visibilité et la durée de vie des données:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Préfixe&lt;/th&gt;
&lt;th&gt;Portée (Scope)&lt;/th&gt;
&lt;th&gt;Persistance&lt;/th&gt;
&lt;th&gt;Cas d'usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Aucun&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Session actuelle&lt;/td&gt;
&lt;td&gt;Liée au service de session&lt;/td&gt;
&lt;td&gt;Étape d'un tunnel d'achat.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;user:&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Identité utilisateur&lt;/td&gt;
&lt;td&gt;Partagée entre toutes ses sessions&lt;/td&gt;
&lt;td&gt;Préférences, nom.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;app:&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Application globale&lt;/td&gt;
&lt;td&gt;Partagée entre tous les utilisateurs&lt;/td&gt;
&lt;td&gt;Version API, code promo.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;temp:&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Invocation en cours&lt;/td&gt;
&lt;td&gt;Éphémère (effacée après la réponse)&lt;/td&gt;
&lt;td&gt;Calculs intermédiaires.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Exemple d'utilisation&lt;/strong&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="c1"&gt;# The ADK automatically replaces {user:name} with the value found in state
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;adk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Greet the user by saying: Hello {user:name}!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Updating state within a tool safely
&lt;/span&gt;&lt;span class="nd"&gt;@adk.tool&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_preference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;adk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToolContext&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user:fav_color&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;color&lt;/span&gt; &lt;span class="c1"&gt;# Captured and persisted automatically
&lt;/span&gt;    &lt;span class="k"&gt;return&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;Preference saved.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧠 MemoryService : Choisir son moteur de connaissances
&lt;/h3&gt;

&lt;p&gt;Dans ADK, le &lt;strong&gt;MemoryService&lt;/strong&gt; est l'interface qui gère l'archivage et la récupération des connaissances à long terme. Sa mission est double : ingérer les informations pertinentes d'une session terminée (&lt;code&gt;add_session_to_memory&lt;/code&gt;) et permettre à l'agent de les retrouver via une recherche (&lt;code&gt;search_memory&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Il existe deux implémentations principales selon vos besoins en persistance et en intelligence :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Caractéristique&lt;/th&gt;
&lt;th&gt;InMemoryMemoryService&lt;/th&gt;
&lt;th&gt;VertexAiMemoryBankService&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Persistance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nulle (perdue au redémarrage)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Élevée&lt;/strong&gt; (Managée par Vertex AI)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extraction&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stocke l'historique brut&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Intelligente&lt;/strong&gt; (extraite et consolidée par LLM)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Type de recherche&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mots-clés basiques&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Sémantique avancée&lt;/strong&gt; (Embeddings)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Usage idéal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prototypage et tests rapides&lt;/td&gt;
&lt;td&gt;Production et apprentissage continu&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;🚀 Le workflow complet&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Pour bien comprendre comment ces composants interagissent, voici le cycle de vie d'une information, de sa captation à sa réutilisation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Interaction&lt;/strong&gt; : L'utilisateur échange avec l'agent via une &lt;strong&gt;Session&lt;/strong&gt;. Chaque message et action est enregistré comme un &lt;strong&gt;Event&lt;/strong&gt;, et le &lt;strong&gt;State&lt;/strong&gt; gère les données de travail immédiates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Archivage&lt;/strong&gt; : Lorsqu'une session est jugée riche en informations, l'application appelle &lt;code&gt;add_session_to_memory(session)&lt;/code&gt;. Le système extrait les faits marquants de l'historique et les consolide dans le &lt;code&gt;MemoryService&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mémoire&lt;/strong&gt; : Dans une session future, l'agent utilise un outil dédié (&lt;code&gt;LoadMemoryTool&lt;/code&gt; ou &lt;code&gt;PreloadMemoryTool&lt;/code&gt;) s'il détecte un besoin de contexte passé.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recherche Sémantique&lt;/strong&gt; : L'outil interroge le service de mémoire (&lt;code&gt;search_memory&lt;/code&gt;). S'il s'agit de la Memory Bank, une recherche par similarité vectorielle est effectuée pour trouver les souvenirs les plus proches du sens de la requête.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restitution &amp;amp; Réponse&lt;/strong&gt; : Le service renvoie les souvenirs pertinents (&lt;code&gt;MemoryResult&lt;/code&gt;). L'agent les intègre alors dans ses instructions système pour formuler une réponse personnalisée et historiquement cohérente.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🤖 Vers une IA qui apprend vraiment
&lt;/h2&gt;

&lt;p&gt;En maîtrisant ce trio, &lt;strong&gt;Session&lt;/strong&gt;, &lt;strong&gt;State&lt;/strong&gt; et &lt;strong&gt;Memory&lt;/strong&gt;, vous sortez enfin du mode "stateless" des LLM. Cette architecture, propulsée par ADK et Google Cloud, garantit que vos agents ne se contentent pas de répondre, mais s'adaptent et valorisent chaque interaction sur le long terme.&lt;/p&gt;

</description>
      <category>adk</category>
      <category>googlecloud</category>
      <category>vertexai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Web3 : Le bilan de Google Cloud sur la blockchain en 2025</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Thu, 11 Dec 2025 09:48:02 +0000</pubDate>
      <link>https://forem.com/zenika/web3-le-bilan-de-google-cloud-sur-la-blockchain-en-2025-431p</link>
      <guid>https://forem.com/zenika/web3-le-bilan-de-google-cloud-sur-la-blockchain-en-2025-431p</guid>
      <description>&lt;p&gt;Comme chaque année (&lt;a href="https://medium.com/zenika/web3-le-bilan-de-google-cloud-sur-blockchain-80da566e628d" rel="noopener noreferrer"&gt;2023&lt;/a&gt; et &lt;a href="https://dev.to/zenika/web3-le-bilan-de-google-cloud-sur-la-blockchain-en-2024-2i4"&gt;2024&lt;/a&gt;), je fais le point sur les avancées de &lt;strong&gt;Google Cloud sur le Web3&lt;/strong&gt;. En 2025, ce domaine est également concerné par l’arrivée de l’Intelligence Artificielle (IA). Le géant du cloud mise désormais sur la &lt;strong&gt;convergence entre la blockchain et l’IA&lt;/strong&gt;. De l’infrastructure aux agents autonomes, en passant par les paiements programmables, Google étend son empreinte bien au-delà des simples services de nœuds.&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%2Ffqrp9v4zt5asp83h2522.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%2Ffqrp9v4zt5asp83h2522.png" alt="Schéma de l'IA dans le Web3 pour GCP" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 Des agents IA connectés à la blockchain
&lt;/h2&gt;

&lt;p&gt;L’un des temps forts de l’année est la publication par Google d’un &lt;strong&gt;guide complet pour créer des « Web3 AI agents »&lt;/strong&gt;, des agents autonomes capables d’interagir directement avec des smart-contracts et des données « on-chain ». S’appuyant sur &lt;strong&gt;Vertex AI Agent Engine&lt;/strong&gt; et &lt;strong&gt;Agent Development Kit (ADK)&lt;/strong&gt;, ces agents peuvent lire des transactions, exécuter des contrats et gérer des flux en toute autonomie.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/build-web3-ai-agents-with-google-cloud?hl=en" rel="noopener noreferrer"&gt;Lire l’article officiel sur le blog Google Cloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google ne se contente plus de fournir des outils d’accès à la blockchain, il devient un acteur du Web3 intelligent, où les IA ne sont plus seulement “off-chain” mais véritablement connectées à l’écosystème décentralisé. Les agents deviennent des entités économiques à part entière, capables d’échanger, d’apprendre et d’agir dans un écosystème numérique interconnecté et sécurisé.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏦 Stablecoins et “Universal Ledger” : Google veut sa propre infrastructure de paiement
&lt;/h2&gt;

&lt;p&gt;L’annonce la plus stratégique de 2025 reste toutefois la mise en avant d’un &lt;strong&gt;protocole de paiement pour agents IA&lt;/strong&gt;, appuyé sur les stablecoins ainsi que sa &lt;strong&gt;propre blockchain maison&lt;/strong&gt; baptisée &lt;a href="https://cloud.google.com/application/web3/universal-ledger" rel="noopener noreferrer"&gt;Google Cloud Universal Ledger&lt;/a&gt;. GCUL ne reposerait pas sur l’Ethereum Virtual Machine (EVM) mais plutôt sur une infrastructure indépendante avec des smart contracts écrits en Python. &lt;a href="https://www.theblock.co/post/368399/google-cloud-blockchain-gcul" rel="noopener noreferrer"&gt;Selon&lt;/a&gt; &lt;em&gt;Rich Widmann&lt;/em&gt;, responsable Web3 chez Google Cloud, GCUL est conçue pour être une plateforme stable, flexible, conforme aux réglementations et « crédiblement neutre », dédiée aux paiements institutionnels et les cas d’usage IA-to-IA. &lt;/p&gt;

&lt;p&gt;Cette initiative rapproche Google des acteurs comme &lt;strong&gt;Stripe&lt;/strong&gt; et &lt;strong&gt;Circle&lt;/strong&gt;, tout en renforçant son positionnement face à des besoins émergents : permettre à des &lt;strong&gt;agents autonomes d’effectuer des transactions stables, traçables et programmables&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://journalducoin.com/actualites/economie-google-lance-protocole-paiement-pour-ia-booste-stablecoins/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Article du Journal du Coin sur le protocole de paiement IA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://journalducoin.com/economie/google-cloud-universal-ledger-nouvelle-solution-paiement-stablecoin/" rel="noopener noreferrer"&gt;Article du Journal du Coin sur GCUL&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cryptoast.fr/google-construit-propre-blockchain-voici-dernieres-infos-officielles/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Cryptoast - Google construirait sa propre blockchain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cryptodnes.bg/fr/google-cloud-blockchain-stripe-circle/" rel="noopener noreferrer"&gt;CryptoDNES - Google Cloud lance sa blockchain pour concurrencer Stripe et Circle&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🌐 Un écosystème Web3 en expansion
&lt;/h2&gt;

&lt;p&gt;En parallèle, Google Cloud a multiplié les &lt;strong&gt;partenariats dans l’écosystème blockchain&lt;/strong&gt;, confirmant sa volonté de ne pas rester seul fournisseur mais de jouer un rôle de catalyseur :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Collaboration avec &lt;strong&gt;Lava Network&lt;/strong&gt; autour de la “&lt;strong&gt;future économie autonome&lt;/strong&gt;”, mêlant IA et blockchain. 👉 &lt;a href="https://www.cryptopolitan.com/fr/google-cloud-and-lava-network-lead-discussion-on-the-future-of-the-autonomous-economy/" rel="noopener noreferrer"&gt;Article sur Cryptopolitan&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partenariat avec &lt;strong&gt;Etherlink&lt;/strong&gt; pour renforcer les outils de développement Web3 et améliorer les performances des infrastructures décentralisées. 👉 &lt;a href="https://phemex.com/news/article/google-cloud-and-etherlink-collaborate-to-enhance-web3-development-28751" rel="noopener noreferrer"&gt;Source Phemex News&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Coopérations avec des projets blockchain pour stimuler l’innovation Web3 à l’échelle mondiale. 👉 &lt;a href="https://cryptodnes.bg/en/blockchain-project-partners-with-google-cloud-to-strengthen-web3-innovation/" rel="noopener noreferrer"&gt;Article de CryptoDnes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ces alliances traduisent une stratégie pragmatique : &lt;strong&gt;favoriser un écosystème performant plutôt qu’un modèle fermé&lt;/strong&gt;, tout en s’assurant que les briques critiques, données, IA, paiements, passent par Google Cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ce qu’il faut retenir
&lt;/h2&gt;

&lt;p&gt;En résumé, voici les quelques pistes à explorer en priorité :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Expérimenter les architectures d’agents IA connectés à la blockchain&lt;/strong&gt; : les tutoriels et SDK proposés par Google facilitent les prototypes. Il y a d’ailleurs un codelab &lt;a href="https://www.skills.google/focuses/61475?parent=catalog" rel="noopener noreferrer"&gt;ici&lt;/a&gt; ou encore un exemple &lt;a href="https://cloud.google.com/blog/products/ai-machine-learning/build-web3-ai-agents-with-google-cloud" rel="noopener noreferrer"&gt;là&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surveiller de près Google Cloud Universal Ledger et les initiatives de paiement stablecoin&lt;/strong&gt; : elles pourraient transformer la manière dont les agents IA échangent de la valeur.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garder un œil sur la gouvernance et la neutralité&lt;/strong&gt; : plus Google s’implique dans l’infrastructure financière on-chain, plus la question de la “neutralité crédible” deviendra importante.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;En 2025, Google Cloud franchit une nouvelle étape : du simple accès à la blockchain à la création d’une infrastructure complète pour les agents intelligents et les paiements programmables. Avec ses nouveaux outils, ses partenariats stratégiques et ses ambitions dans les paiements, le cloud de Google devient un acteur structurant de la convergence &lt;strong&gt;Web3 × IA&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Les clouds de demain seront-ils « &lt;em&gt;on-chain&lt;/em&gt; et &lt;em&gt;intelligents »&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Rendez-vous en 2026 !&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>googlecloud</category>
      <category>cloud</category>
    </item>
    <item>
      <title>🤖 Déployer son agent sur Google Vertex AI Agent Engine</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Wed, 05 Nov 2025 15:14:01 +0000</pubDate>
      <link>https://forem.com/zenika/deployer-son-agent-sur-google-vertex-ai-agent-engine-342l</link>
      <guid>https://forem.com/zenika/deployer-son-agent-sur-google-vertex-ai-agent-engine-342l</guid>
      <description>&lt;p&gt;Google Cloud a récemment introduit &lt;a href="https://cloud.google.com/agent-builder/agent-engine/overview" rel="noopener noreferrer"&gt;&lt;strong&gt;Vertex AI Agent Engine&lt;/strong&gt;&lt;/a&gt;, une plateforme intégrée à l’écosystème Vertex AI conçue pour centraliser et déployer des agents à grande échelle dans unun environnement cloud sécurisé et scalable.&lt;/p&gt;

&lt;p&gt;Dans cet article, nous allons voir les avantages de Vertex AI Agent Engine et les différentes façons de déployer un agent dessus : l'approche native avec &lt;a href="https://google.github.io/adk-docs/" rel="noopener noreferrer"&gt;&lt;strong&gt;ADK (Agent Development Kit)&lt;/strong&gt;&lt;/a&gt; et l'approche flexible via le &lt;strong&gt;SDK Vertex AI&lt;/strong&gt; pour les agents conçus avec des frameworks comme &lt;a href="https://www.langchain.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;LangChain&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;, &lt;a href="https://www.langchain.com/langgraph" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt;&lt;/strong&gt; ou &lt;a href="https://www.crewai.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;CrewAI&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A travers cet article, nous allons comprendre comment passer d’un agent local à un agent opérationnel dans le cloud, prêt à interagir avec vos données et vos utilisateurs.&lt;/p&gt;

&lt;h2&gt;
  
  
  ❓Comprendre Vertex AI Agent Engine et ses avantages
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Vertex AI Agent Engine&lt;/strong&gt; est un service de Google Cloud conçu pour simplifier le déploiement et l’orchestration d’agents IA. L’idée derrière Agent Engine est simple : proposer une infrastructure centralisée pour gérer des agents, qu’ils soient conversationnels, analytiques ou autonomes.&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%2F8lpizra942a1v8r2enbw.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%2F8lpizra942a1v8r2enbw.png" title="Interaction avec Vertex AI Agent Engine" alt="Interaction avec Vertex AI Agent Engine" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💡 Les principaux avantages de Vertex AI Agent Engine
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;➡️ Gestion des mémoires et des sessions&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%2Frxjvn81luuvvcaj7svb3.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%2Frxjvn81luuvvcaj7svb3.png" title="Gestion des mémoires et des sessions" alt="Gestion des mémoires et des sessions" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vertex AI Agent Engine intègre nativement la &lt;a href="https://docs.cloud.google.com/agent-builder/agent-engine/memory-bank/overview" rel="noopener noreferrer"&gt;gestion des sessions et des mémoires&lt;/a&gt; conversationnelles. Cela permet à un agent de :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;garder le contexte entre plusieurs interactions d’un même utilisateur,&lt;/li&gt;
&lt;li&gt;s’appuyer sur l’historique d’échanges,&lt;/li&gt;
&lt;li&gt;enrichir sa compréhension du contexte au fil du temps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;➡️ Support multi-frameworks&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%2F7gtqnda9abxraqsw3v5q.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%2F7gtqnda9abxraqsw3v5q.png" title="Ecosystème Vertex AI Agent Engine" alt="Ecosystème Vertex AI Agent Engine" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vertex AI Agent Engine ne se limite pas à un framework. Il prend en charge plusieurs frameworks d’agents (ADK, LangChain, LlamaIndex, frameworks maison, etc.), ce qui permet de l’adapter à différents contextes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;➡️ Intégration native à Google Cloud&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les agents peuvent facilement se connecter à d’autres services. Grâce aux &lt;strong&gt;Tools&lt;/strong&gt; comme Google Cloud, &lt;a href="https://modelcontextprotocol.io/docs/getting-started/intro" rel="noopener noreferrer"&gt;MCP (Model Context Protocol)&lt;/a&gt;, &lt;a href="https://a2a-protocol.org/latest/" rel="noopener noreferrer"&gt;A2A (Agent2Agent)&lt;/a&gt; ou encore des “custom tools”, ils peuvent interagir avec des API, des bases de données ou des applications métiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;➡️ Auto-scaling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agent Engine gère automatiquement le scaling et le déploiement des agents. Le compute s’ajuste automatiquement selon la demande.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;➡️ Sécurité et gouvernance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chaque agent hérite d’une identité sécurisée. Vous pouvez ainsi &lt;a href="https://docs.cloud.google.com/agent-builder/agent-engine/manage/access" rel="noopener noreferrer"&gt;définir des permissions&lt;/a&gt; précises pour les accès aux données ou aux APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;➡️ Monitoring&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chaque exécution d’agent est monitorée : logs détaillés, métriques, et suivi des appels aux modèles. Cela facilite le debug, l’optimisation et l’analyse de performances.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Déployer son agent avec le framework ADK (Agent Development Kit)
&lt;/h2&gt;

&lt;p&gt;Le framework ADK (Agent Development Kit) est le framework proposé par Google pour construire des agents et disponible actuellement en &lt;a href="https://github.com/google/adk-python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; et en &lt;a href="https://github.com/google/adk-java" rel="noopener noreferrer"&gt;Java&lt;/a&gt;. Il offre une structure claire pour le développement, le test et le déploiement d’agents, tout en s’intégrant nativement avec les services Vertex AI.&lt;/p&gt;

&lt;p&gt;Le premier déploiement peut s’effectuer en quelques minutes.&lt;/p&gt;

&lt;p&gt;Pré-requis :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La CLI Google Cloud (&lt;a href="https://docs.cloud.google.com/sdk/docs/install?hl=fr" rel="noopener noreferrer"&gt;gcloud&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Installation et initialisation du projet
&lt;/h3&gt;

&lt;p&gt;Création d’un environnement virtuel Python (ici à l’aide de &lt;a href="https://docs.astral.sh/uv/guides/install-python/" rel="noopener noreferrer"&gt;uv&lt;/a&gt;):&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;mkdir &lt;/span&gt;deploy-with-adk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;deploy-with-adk
uv venv &lt;span class="nt"&gt;--python&lt;/span&gt; 3.12
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialisation d’un projet d’agent avec ADK :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv pip &lt;span class="nb"&gt;install &lt;/span&gt;google-adk
adk create personal_assistant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;L’arborescence du projet est automatiquement créée :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;└── deploy-with-adk
    └── personal_assistant
        ├── __init__.py
        ├── .env
        └── agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Création d’un agent
&lt;/h3&gt;

&lt;p&gt;Dans mon fichier agent.py, j’ai créé, pour cet article, un agent tout simple capable de répondre à mes questions tout en se basant sur un datastore dans VertexAI Search contenant différents documents personnels.&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;google.adk.agents.llm_agent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.adk.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VertexAiSearchTool&lt;/span&gt;

&lt;span class="n"&gt;root_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&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;root_agent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Answer questions using Vertex AI Search to find information from internal documents. Always cite sources when available.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enterprise document search assistant with Vertex AI Search capabilities&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;VertexAiSearchTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_store_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DATASTORE_ID&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Déploiement
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adk deploy agent_engine &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--staging_bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gs://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BUCKET_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--display_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Personal Assistant"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    personal_assistant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cette commande :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;construit une image container de votre agent,&lt;/li&gt;
&lt;li&gt;la déploie sur &lt;strong&gt;Vertex AI Agent Engine&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;et génère un &lt;strong&gt;endpoint&lt;/strong&gt; accessible via API ou depuis d’autres agents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une fois déployé, votre agent peut être intégré dans des workflows plus complexes.&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%2Fchnrg2bh5hyfxv2c0kby.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%2Fchnrg2bh5hyfxv2c0kby.png" title="Dashboard Vertex AI Agent Engine" alt="Dashboard Vertex AI Agent Engine" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Déployer un agent avec un autre framework grâce au SDK Vertex AI
&lt;/h2&gt;

&lt;p&gt;Si ADK intègre simplement le déploiement, Agent Engine est aussi compatible avec de nombreux autres frameworks d’agents IA comme LangChain, LlamaIndex ou CrewAI via la SDK de Vertex AI.&lt;/p&gt;

&lt;p&gt;Cette approche permet d’intégrer un agent existant (déjà conçu avec LangChain par exemple) dans l’écosystème Vertex AI pour le monitorer, le scaler et le connecter à d’autres services Google Cloud.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Installation et initialisation du projet
&lt;/h3&gt;

&lt;p&gt;Commençons par initialiser Vertex AI avec le projet, la région, et un “staging bucket” (nécessaire pour le packaging de l’agent).&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;mkdir &lt;/span&gt;deploy-with-vertex &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;deploy-with-vertex &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;agent.py

uv venv &lt;span class="nt"&gt;--python&lt;/span&gt; 3.12
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

uv pip &lt;span class="nb"&gt;install &lt;/span&gt;google-cloud-aiplatform[agent_engines,langchain]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Création d’un agent
&lt;/h3&gt;

&lt;p&gt;Dans le fichier agent.py, nous allons repartir du même cas d’usage que l’agent précédent, mais cette fois en utilisant LangChain.&lt;/p&gt;

&lt;p&gt;Cet agent sera capable de répondre à des questions en interrogeant un datastore Vertex AI Search contenant différents documents personnels.&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;vertexai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agent_engines&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_retrievers.google_vertex_ai_search&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VertexAISearchRetriever&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Tool&lt;/span&gt;

&lt;span class="c1"&gt;# Init Vertex AI
&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PROJECT_REGION&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;staging_bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gs://${STAGING_BUCKET}&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="c1"&gt;# Create retriever
&lt;/span&gt;&lt;span class="n"&gt;retriever&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;VertexAISearchRetriever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_store_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;DATASTORE_ID&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# Define search tool
&lt;/span&gt;&lt;span class="n"&gt;search_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;(&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;vertex_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;retriever&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_relevant_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Searches your private document store via Vertex AI Search.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# System prompt
&lt;/span&gt;&lt;span class="n"&gt;system_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;re an intelligent assistant that can answer questions using internal document search. Use the search tool when necessary.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# Create Langchain Agent
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_engines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LangchainAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;system_instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;search_tool&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;model_kwargs&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;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;top_p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Intégration de l’agent dans Vertex AI
&lt;/h3&gt;

&lt;p&gt;La ligne clé suivante permet d’envelopper l’agent LangChain dans une classe compatible avec Vertex AI Agent Engine. C’est cette abstraction qui rend possible son déploiement dans l’infrastructure Vertex AI.&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;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_engines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LangchainAgent&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vertex AI fournit également d’autres classes pour intégrer différents frameworks comme par exemple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;agent_engines.LlamaIndexAgent&lt;/code&gt; pour LlamaIndex,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;agent_engines.CrewAIAgent&lt;/code&gt; pour CrewAI.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Déploiement
&lt;/h3&gt;

&lt;p&gt;J’ajoute ensuite la méthode ci-dessous pour le déploiement. &lt;a href="https://cloud.google.com/agent-builder/agent-engine/deploy#create-agent-engine" rel="noopener noreferrer"&gt;Plusieurs options sont disponibles&lt;/a&gt; pour configurer le déploiement et notamment le paramètre “requirements” pour définir les packages nécessaires à l’agent.&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;remote_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_engines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agent_engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;requirements&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;google-cloud-aiplatform[agent_engines,langchain]&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;langchain_community&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="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;✅ Agent deployed with 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;Ce code va :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“sérialiser” l’agent&lt;/li&gt;
&lt;li&gt;envoyer le code vers le staging bucket,&lt;/li&gt;
&lt;li&gt;déployer l’agent sur Vertex AI Agent Engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il ne me reste plus qu’à exécuter mon fichier et l’agent sera déployé en quelques minutes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run index.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  💬 Interagir avec l’agent déployé
&lt;/h2&gt;

&lt;p&gt;Une fois l’agent déployé sur Vertex AI Agent Engine, il est possible de l’interroger directement depuis le code Python à l’aide du SDK Vertex AI, quelle que soit la méthode de déploiement (ADK ou via le SDK VertexAI).&lt;/p&gt;

&lt;p&gt;Les agents déployés via ADK ou via le SDK Vertex AI sont compatibles avec la même API.&lt;/p&gt;

&lt;p&gt;Voici un exemple minimaliste d’interaction :&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;vertexai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;agent_engines&lt;/span&gt;

&lt;span class="c1"&gt;# Get the deployed agent engine
&lt;/span&gt;&lt;span class="n"&gt;agent_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_engines&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="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;RESOURCE_ID&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# Send a request to the agent
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_engine&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="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Who won the FIFA World Cup in 2018?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Display the text response
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  💡 En résumé
&lt;/h2&gt;

&lt;p&gt;Dans cet article, nous avons vu deux manières de déployer un agent sur &lt;strong&gt;Vertex AI Agent Engine&lt;/strong&gt; : le &lt;strong&gt;framework ADK&lt;/strong&gt;, idéal pour un déploiement rapide et standardisé, et le &lt;strong&gt;SDK Vertex AI&lt;/strong&gt;, plus flexible pour intégrer des frameworks comme &lt;strong&gt;LangChain&lt;/strong&gt; et des outils personnalisés.&lt;/p&gt;

&lt;p&gt;L’exemple présenté reste volontairement simple, mais il est possible d’aller beaucoup plus loin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;configurer le &lt;strong&gt;service account&lt;/strong&gt; associé à chaque agent,&lt;/li&gt;
&lt;li&gt;ajuster les &lt;strong&gt;paramètres d’exécution&lt;/strong&gt;, ou activer le monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 Update 10/11/2025 – Vertex AI Agent Engine Express Mode
&lt;/h2&gt;

&lt;p&gt;Quelques jours après la sortie de cet article, Google a introduit le mode Express pour Vertex AI Agent Engine.&lt;/p&gt;

&lt;p&gt;Ce mode permet d’utiliser Agent Engine sans créer de projet Google Cloud, simplement avec un compte Gmail et une clé API depuis Vertex AI Studio.&lt;/p&gt;

&lt;p&gt;ℹ️ Depuis le 1er novembre 2025, un nouveau free tier est également disponible pour permettre aux développeurs d’expérimenter Agent Engine gratuitement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pour approfondir le sujet :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.cloud.google.com/agent-builder/agent-engine/overview" rel="noopener noreferrer"&gt;Documentation Vertex AI Agent Engine&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://google.github.io/adk-docs/deploy/" rel="noopener noreferrer"&gt;Guide de déploiement ADK&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/GoogleCloudPlatform/agent-starter-pack" rel="noopener noreferrer"&gt;agent-starter-pack&lt;/a&gt;: Une collection de modèles d'agents IA prêts à l'emploi, conçus pour Google Cloud.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.skills.google/" rel="noopener noreferrer"&gt;Google Skills pour monter en compétence sur les produits Google&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>googlecloud</category>
      <category>ai</category>
      <category>agents</category>
      <category>cloud</category>
    </item>
    <item>
      <title>DuckDB on AWS Lambda: The Easy Way with Layers</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Fri, 12 Sep 2025 19:23:30 +0000</pubDate>
      <link>https://forem.com/zenika/duckdb-on-aws-lambda-the-easy-way-with-layers-2o75</link>
      <guid>https://forem.com/zenika/duckdb-on-aws-lambda-the-easy-way-with-layers-2o75</guid>
      <description>&lt;p&gt;A few weeks ago, I faced a recurring task: every week, a batch of TSV files (which is just like a CSV, Comma-Separated Values file, but it uses tabs instead of commas to separate the values) needed to be ingested and loaded into an RDS database. Maintaining a full database for this simple weekly operation felt overkill, and the process itself was time-consuming.&lt;/p&gt;

&lt;p&gt;It seemed like the perfect opportunity to explore &lt;a href="https://duckdb.org/" rel="noopener noreferrer"&gt;DuckDB&lt;/a&gt;, an in-process analytical database known for its efficiency and simplicity&lt;/p&gt;

&lt;p&gt;💡 The idea was to process the TSV files directly in a serverless environment, transform them with SQL queries, and store the results without running a persistent database.&lt;/p&gt;

&lt;h2&gt;
  
  
  🦆 What is DuckDB
&lt;/h2&gt;

&lt;p&gt;DuckDB is an open-source, in-process analytical database often described as “the SQLite of analytics”. It is optimized specifically for analytical queries and can scan large datasets efficiently.&lt;/p&gt;

&lt;p&gt;One of its standout features is the ability to read columnar storage formats like &lt;a href="https://en.wikipedia.org/wiki/Apache_Parquet" rel="noopener noreferrer"&gt;Parquet&lt;/a&gt; directly from local files, S3 buckets, or HTTP endpoints. DuckDB scans and aggregates data on the fly without loading entire datasets into memory, which is particularly useful in serverless environments where memory and compute usage directly impact cost.&lt;/p&gt;

&lt;p&gt;Now combine that with &lt;a href="https://aws.amazon.com/lambda/" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; : instead of &lt;a href="https://docs.aws.amazon.com/athena/latest/ug/querying-athena-tables.html" rel="noopener noreferrer"&gt;Athena queries&lt;/a&gt;, RDS instances, or complex ETL pipelines, DuckDB allows you to run analytical workloads on-demand in a Lambda function, paying only for what you actually use. Existing AWS services like Athena or RDS can address similar needs, but they come with different scaling models and pricing strategies. Athena, for example, charges per scanned byte and introduces query latency, while RDS requires you to maintain an always-on database.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤯 The Challenge with DuckDB on Lambda
&lt;/h2&gt;

&lt;p&gt;To configure my Lambda, I rely on Terraform to manage the infrastructure. However, I quickly ran into a major issue: DuckDB is a compiled library.&lt;/p&gt;

&lt;p&gt;This means you can’t just &lt;code&gt;pip install duckdb&lt;/code&gt; locally and upload it through Terraform. If the binary hasn’t been compiled for the Lambda runtime environment, the function will fail to import it. Simply zipping the code is usually not enough, due to &lt;a href="https://en.wikipedia.org/wiki/Application_binary_interface" rel="noopener noreferrer"&gt;ABI&lt;/a&gt; incompatibilities and OS differences.&lt;/p&gt;

&lt;p&gt;To get around this, I had to set up a Docker container, build DuckDB inside it, copy the resulting files back to my machine, zip them, and then upload everything to Lambda.&lt;/p&gt;

&lt;p&gt;This approach works, but it’s far from ideal for small projects or when you just need to get a Lambda running quickly. You're forced to deal with problems like installing Docker and setting up a container build process, which adds significant complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Solution
&lt;/h2&gt;

&lt;p&gt;That’s why I decided to create prebuilt Lambda layers for each architecture, Python version, and DuckDB version, then make them public.&lt;/p&gt;

&lt;p&gt;A Lambda layer is a convenient way to package and share dependencies across multiple Lambda functions, without having to include them in every single deployment package. This completely eliminates the need for a local build, so anyone can use DuckDB without repeating the same tedious setup.&lt;/p&gt;

&lt;p&gt;These layers are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Pre-compiled for every Lambda-supported Python runtime (3.8 → 3.13).&lt;/li&gt;
&lt;li&gt;✅ Supports both architectures (x86_64 and arm64).&lt;/li&gt;
&lt;li&gt;✅ Available in all AWS regions.&lt;/li&gt;
&lt;li&gt;✅ Easy to attach to your Lambda without increasing your deployment package size.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding DuckDB to a Lambda function is as simple as attaching a Lambda layer with its &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html#lambda-layer-versions" rel="noopener noreferrer"&gt;ARN&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda update-function-configuration &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; your-function-name &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--layers&lt;/span&gt; LAYER_ARN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then inside your handler:&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;duckdb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&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="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;duckdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:memory:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&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 &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello from DuckDB!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; AS msg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the layer is attached, DuckDB is immediately available in your Lambda function, eliminating the need to build it from source or worry about architecture mismatches.&lt;/p&gt;

&lt;p&gt;These layers make serverless analytics accessible: tasks that previously required RDS, Athena, or complex ETL pipelines can now be handled entirely within Lambda.&lt;/p&gt;

&lt;p&gt;💙 The project is open-source. You can find all layer ARNs and usage instructions on &lt;a href="https://github.com/bengeois/aws-layer-duckdb-python" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  👉🏼 Back to the Initial Problem
&lt;/h2&gt;

&lt;p&gt;The original problem I wanted to solve was quite simple: every week I had to fetch a set of TSV files and import them into a MySQL database hosted on RDS.&lt;/p&gt;

&lt;p&gt;With DuckDB, this workflow became surprisingly straightforward. Once the files are downloaded and available locally in the Lambda /tmp directory, DuckDB can both read them directly and push the data into MySQL using its extension system.&lt;/p&gt;

&lt;p&gt;Here’s the core of what it looks like:&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;duckdb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handler&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="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Connect to DuckDB in memory
&lt;/span&gt;        &lt;span class="n"&gt;con&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;duckdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;:memory:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Install and load the MySQL extension
&lt;/span&gt;        &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install_extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mysql&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_extension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mysql&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Attach to the target MySQL database
&lt;/span&gt;        &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        ATTACH &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host=... user=... password=... port=... database=...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; AS mysql (TYPE mysql);
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USE mysql;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Write directly the TSV into a table
&lt;/span&gt;    &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        CREATE TABLE users AS
        SELECT * FROM read_csv(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/tmp/users.txt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, header=true, delim=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;t&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;# Example query
&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;con&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&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 COUNT(*) FROM users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&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;Users imported: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Working with DuckDB inside AWS Lambda can feel tricky at first because of the binary and platform compatibility issues. But with prebuilt layers, the whole process becomes much simpler: you can focus on writing your Lambda logic instead of worrying about how to build and package DuckDB.&lt;/p&gt;

&lt;p&gt;For my use case, this meant going from a manual Docker build and zip dance to a simple Terraform deployment with a ready-to-use layer. Hopefully, by making these layers public, others can save the same time and frustration.&lt;/p&gt;

&lt;p&gt;💙 The project is open-source. You can find all layer ARNs and usage instructions on &lt;a href="https://github.com/bengeois/aws-layer-duckdb-python" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It also exists for NodeJS, thanks to a great initiative by &lt;em&gt;tobilg&lt;/em&gt;, you can find it &lt;a href="https://github.com/tobilg/duckdb-nodejs-layer" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;⭐ Star the repo, give it a try, and do not hesitate to open a PR!&lt;/p&gt;

</description>
      <category>duckdb</category>
      <category>aws</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Google Agent Development Kit : Core Concept</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Mon, 30 Jun 2025 16:51:26 +0000</pubDate>
      <link>https://forem.com/zenika/google-agent-development-kit-core-concept-4phc</link>
      <guid>https://forem.com/zenika/google-agent-development-kit-core-concept-4phc</guid>
      <description>&lt;p&gt;Recently, Google announced their Agent Development Kit (ADK), which is an open-source &lt;a href="https://github.com/google/adk-python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; (and &lt;a href="https://github.com/google/adk-java" rel="noopener noreferrer"&gt;Java&lt;/a&gt; recently) library to help developers build agents.&lt;/p&gt;

&lt;p&gt;We’re entering a new phase where AI doesn’t just respond; it can act. These agents can search the web, write and execute code, read documents, call APIs, and perform many other tasks to get things done, often without needing step-by-step instructions.&lt;br&gt;
Since May 20th 2025, the framework is officially stable in Python so I was immediately interested in diving in to understand all the possibilities it offers.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through all the core concepts, what it is, and what it offers.&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%2F4073zbcotevcircq8uiy.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%2F4073zbcotevcircq8uiy.png" alt="Google Agent Development Kit Logo" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🔍 What is Google Agent Development Kit?
&lt;/h2&gt;

&lt;p&gt;﻿&lt;strong&gt;Agent Development Kit&lt;/strong&gt; is a &lt;strong&gt;framework to build, run, and evaluate AI agents&lt;/strong&gt;. These agents can be simple (answering a question with a tool) or more advanced (planning tasks, calling APIs, interacting with files, or even spawning sub-agents).&lt;/p&gt;

&lt;p&gt;💡 Google says it uses the same underlying framework as its internal systems, like &lt;em&gt;Agentspace&lt;/em&gt; or those powering Gemini experiences in tools like Gmail or Docs.&lt;/p&gt;

&lt;p&gt;ADK is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Open-source&lt;/strong&gt;, promoting community collaboration.&lt;/li&gt;
&lt;li&gt;  Designed for both &lt;strong&gt;solo agents and multi-agent systems&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  Is able to work seamlessly with Google Cloud services like Vertex AI and Cloud Run, but is also capable of &lt;strong&gt;running locally or with other models&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ADK helps us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create agents that use &lt;strong&gt;LLMs&lt;/strong&gt; to plan and reason&lt;/li&gt;
&lt;li&gt;  Add &lt;strong&gt;tools&lt;/strong&gt; that connect to APIs or run code&lt;/li&gt;
&lt;li&gt;  Run workflows with &lt;strong&gt;multiple agents working together&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Deploy our agents &lt;strong&gt;locally or in the cloud&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🧩 Core Concept and Architecture of ADK
&lt;/h2&gt;

&lt;p&gt;So how does ADK actually work under the hood? It’s built around a few &lt;strong&gt;key building blocks&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%2F18i22rh7n9agr3gmppfg.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%2F18i22rh7n9agr3gmppfg.png" alt="Representation of ADK Core Concept" width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ADK is built around several key building blocks that enable its powerful capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;🧠 Agent:&lt;/strong&gt; The fundamental unit designed to perform specific jobs. This includes LlmAgent (driven by LLMs) and various WorkflowAgent types (SequentialAgent, ParallelAgent, LoopAgent), and Custom Agents for maximum flexibility.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;🛠️ Tools:&lt;/strong&gt; Functions or capabilities that extend an agent's abilities, allowing it to interact with external systems (e.g., searching, calculating, API calls, MCP).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;📞 Callbacks:&lt;/strong&gt; Custom code snippets that allow you to insert logic at specific points in an agent's process, useful for logging, monitoring, or modifying behavior.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;🧾 Events:&lt;/strong&gt; Records of everything happening within a session (user messages, agent replies, tool calls), providing a clear historical trace for debugging and evaluation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;💾 State, Session, and Memory:&lt;/strong&gt; A Session represents an ongoing interaction, managing its short-term State (current context), while Memory provides longer-term recall across sessions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;📁 Artifact Management:&lt;/strong&gt; A mechanism for agents to manage and store files and data blobs (like generated CSVs or images) associated with a session.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;⚙️ Code Execution:&lt;/strong&gt; A powerful capability allowing agents to dynamically write and run code during their process to solve complex problems or automate tasks.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;🧭 Planning:&lt;/strong&gt; An advanced feature where agents can break down complex goals into a sequence of steps, determining the optimal approach using their tools and reasoning.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;🧬 Models:&lt;/strong&gt; The Large Language Models (LLMs) that LlmAgents rely on for reasoning. ADK is model-agnostic, supporting various providers while being optimized for Gemini and the Google ecosystem.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;🏃 Runner:&lt;/strong&gt; The orchestrator within ADK that manages the flow of events between the user, the agent, and its tools, ensuring everything executes in the correct order.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🚀 Let’s implement our first multi-agent system
&lt;/h2&gt;

&lt;p&gt;For this hands-on part, our goal is to build a smart system that can organize a weekend trip to a city, planning an optimized itinerary to visit the most popular places efficiently.&lt;/p&gt;
&lt;h3&gt;
  
  
  1️⃣ Step 1: Defining our specialized agents
&lt;/h3&gt;
&lt;h4&gt;
  
  
  👤 The &lt;code&gt;places_finder&lt;/code&gt; Agent
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;places_finder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;(&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;places_finder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.0-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An agent to find popular places to visit in a city.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruction&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;You are a helpful travel researcher. Your task is to find the top 5 most popular or highly-rated tourist attractions in the given city.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use the Google Search tool for this. For each place, provide its exact name and, if possible, its full address or a clear identifier.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return the list of places, clearly separated.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;google_search&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;places_finder&lt;/code&gt; is an &lt;code&gt;LlmAgent&lt;/code&gt; equipped with the Google Search tool, giving it the ability to browse the web for information.&lt;/p&gt;
&lt;h4&gt;
  
  
  👤 The &lt;code&gt;geocode_finder&lt;/code&gt; Agent
&lt;/h4&gt;

&lt;p&gt;Before we can plan a path, we need precise coordinates for our places of interest.&lt;br&gt;
That's where the &lt;code&gt;geocode_finder&lt;/code&gt; comes in.&lt;br&gt;
It takes a human-readable address or place name and converts it into a geocode (latitude and longitude) leveraging the MCPToolset for Google Maps to perform its core function.&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;geocode_finder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;(&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;geocode_finder&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.0-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent to geocode addresses and place names into coordinates.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruction&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;You are a precise geocoding assistant. You will receive an address or a place name.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your only task is to use the provided Google Maps MCP tool to get its exact geographic coordinates (latitude and longitude).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return ONLY the latitude and longitude, formatted as a string &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;latitude,longitude&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; (e.g., &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;48.8584,2.2945&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If you cannot find the geocode, return &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ERROR&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="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;MCPToolset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;connection_params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;StdioServerParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npx&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;args&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;-y&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;@modelcontextprotocol/server-google-maps&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;env&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;GOOGLE_MAPS_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;google_maps_api_key&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  👤 The &lt;code&gt;path_planner&lt;/code&gt; Agent
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;path_planner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;(&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;path_planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.0-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An agent to optimize the visiting path for a list of geocoded locations.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruction&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;You are an expert route optimization specialist. You will receive a list of geocodes (latitude,longitude strings) &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;representing places to visit in a city. Your goal is to use the Google Maps MCP tool to find the most efficient travel path &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;to visit all these locations, minimizing travel time and avoiding unnecessary backtracking.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return the optimized list of geocodes in the recommended visiting order, each on a new line. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Also, provide a brief, clear textual description of the optimized route.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;MCPToolset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;connection_params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;StdioServerParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npx&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;args&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;-y&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;@modelcontextprotocol/server-google-maps&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;env&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;GOOGLE_MAPS_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;google_maps_api_key&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;path_planner&lt;/code&gt; is an &lt;code&gt;LlmAgent&lt;/code&gt; equipped with the &lt;code&gt;MCPToolset&lt;/code&gt; for Google Maps, giving it the power to calculate routes.&lt;br&gt;
This agent's job is to figure out the best route. It's smart enough to understand geographical points and use Google Maps to optimize a visiting path.&lt;/p&gt;
&lt;h4&gt;
  
  
  👤 The &lt;code&gt;root_agent&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This is the main agent the user will interact with. Its role is to orchestrate the entire planning process by calling upon the other specialized agents.&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;root_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&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;city_trip_planner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.0-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An agent to plan an optimized city visit itinerary.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruction&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;You are an experienced travel agent specializing in city tours. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;When a user asks to plan a visit in a city, follow these steps meticulously:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1. First, use the `places_finder` tool to get a list of the top popular places in that city.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2. For each place found, use the `geocode_agent` tool *one by one* to obtain its geographic coordinates. Handle any places that cannot be geocoded by noting them but continuing with the others.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3. Once you have geocodes for all successfully identified places, pass this *list of geocodes* to the `path_planner` tool to get the most optimized visiting route.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4. Finally, present the complete, optimized itinerary to the user in a clear and friendly manner. Include the order of places to visit and the route description provided by the path planner. Do not include internal tool outputs in the final user response.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If you encounter any issues (e.g., unable to find places or geocode them), inform the user about the problem.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;agent_tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AgentTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;path_planner&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;agent_tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AgentTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;geocode_finder&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;agent_tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AgentTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;places_finder&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;root_agent&lt;/code&gt; is also an &lt;code&gt;LlmAgent&lt;/code&gt; acting as our "City Trip Planner" : first find places, then use &lt;code&gt;geocode_agent&lt;/code&gt; to get their coordinates, and finally pass those coordinates to &lt;code&gt;path_planner&lt;/code&gt; for routing.&lt;/p&gt;

&lt;p&gt;Notice the tools list for &lt;code&gt;root_agent&lt;/code&gt;: it uses &lt;code&gt;agent_tool.AgentTool&lt;/code&gt; to include &lt;code&gt;places_finder&lt;/code&gt;, &lt;code&gt;path_planner&lt;/code&gt; and &lt;code&gt;geocode_agent&lt;/code&gt; as its own tools.&lt;br&gt;
This is an ADK feature, agents can directly call other agents as if they were simple functions, enabling multi-agent hierarchies.&lt;/p&gt;
&lt;h3&gt;
  
  
  2️⃣ Step 2: Running the agent
&lt;/h3&gt;

&lt;p&gt;The Agent Development Kit can be easily installed following these instructions : &lt;a href="https://github.com/google/adk-python" rel="noopener noreferrer"&gt;https://github.com/google/adk-python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, to open the ADK developer interface, simply run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adk web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the ADK UI is open, we can start a new conversation. Let's ask our agent team to plan a weekend trip to Nantes.&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%2F3onowdhwa6n043jclv5y.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%2F3onowdhwa6n043jclv5y.png" alt="Conversation result with the agent" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ADK UI provides a powerful visual representation of our agents working behind the scenes.&lt;br&gt;
The interaction graph is helpful to understand multi-agent systems.&lt;br&gt;
We’ll see the &lt;code&gt;root_agent&lt;/code&gt; delegating tasks, the &lt;code&gt;places_finder&lt;/code&gt; researching attractions, the &lt;code&gt;geocode_agent&lt;/code&gt; converting addresses to coordinates, and finally, the &lt;code&gt;path_planner&lt;/code&gt; optimizing the route.&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%2Fvcwtj8njmzm97g3uw7rf.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%2Fvcwtj8njmzm97g3uw7rf.png" alt="Image showing agent event properties" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;I hope this first article has provided you with a clearer understanding of what Google ADK is and how you can begin creating your own agents to help with daily tasks. You've seen a concrete example of setting up a multi-agent system, and had an overview of the multitude of tools you can connect to these agents.&lt;/p&gt;

&lt;p&gt;In the next article, we'll try to use other tools provided by this framework, explore custom functions, deep dive into MCP, and look into deploying your agents to Google Cloud.&lt;/p&gt;

</description>
      <category>adk</category>
      <category>google</category>
      <category>ai</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>🤖 Using Gemini Code Assist for Code Reviews in My Personal Project</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Mon, 28 Apr 2025 11:01:40 +0000</pubDate>
      <link>https://forem.com/zenika/using-gemini-code-assist-for-code-reviews-in-my-personal-project-cl4</link>
      <guid>https://forem.com/zenika/using-gemini-code-assist-for-code-reviews-in-my-personal-project-cl4</guid>
      <description>&lt;p&gt;I work solo on a few side projects, and even though I enjoy coding, &lt;strong&gt;reviewing my own pull requests isn’t exactly fun&lt;/strong&gt; (or efficient). I tend to skip reviews, miss obvious bugs, and come back weeks later thinking “what was I thinking?”&lt;/p&gt;

&lt;p&gt;So I tried working with a new teammate : Hello Gemini Code Assist 👋🏼&lt;/p&gt;

&lt;p&gt;If you haven’t heard of &lt;strong&gt;Gemini Code Assist&lt;/strong&gt;, It is a generative AI coding assistant to help you with tasks across the Software Development Lifecycle and &lt;strong&gt;&lt;a href="https://blog.google/technology/google-deepmind/gemini-model-thinking-updates-march-2025/" rel="noopener noreferrer"&gt;powered by Gemini 2.5&lt;/a&gt;.&lt;/strong&gt; Think of it like a reviewer that gives instant feedback, suggests ready-to-commit code fixes, and even summarizes your pull requests.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Spoiler: It’s like having a helpful teammate who never sleeps ☕&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🚀 What Gemini Actually Does on my PR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When I open a PR&lt;/strong&gt; Gemini jumps in within ~5 minutes. It adds itself as a reviewer (&lt;code&gt;gemini-code-assist[bot]&lt;/code&gt;) and I get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;summary&lt;/strong&gt; of the PR ;&lt;/li&gt;
&lt;li&gt;A list of &lt;strong&gt;code comments&lt;/strong&gt; with suggestions ;&lt;/li&gt;
&lt;li&gt;Sometimes even &lt;strong&gt;fixes I can commit directly&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can also talk with it, asking for clarifying questions on the review that it creates, etc.&lt;/p&gt;

&lt;p&gt;The available commands are the following : &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Review code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/gemini review&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full review of the current PR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Summarize PR&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/gemini summary&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TL;DR of your PR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ask something&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@gemini-code-assist&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ask it anything in a comment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Help&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/gemini help&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List of available commands&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I usually trigger a &lt;code&gt;/gemini review&lt;/code&gt; just before merging to double-check everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  📄 1. Pull Request Summary
&lt;/h3&gt;

&lt;p&gt;Right after I open a PR, Gemini write a &lt;strong&gt;summary comment&lt;/strong&gt; to give a quick heads-up. It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A short overview of what’s been changed&lt;/li&gt;
&lt;li&gt;Highlights of the major updates or refactors&lt;/li&gt;
&lt;li&gt;A mini &lt;strong&gt;changelog&lt;/strong&gt; listing the important modifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perfect if you want your team (or future you) to instantly understand what’s going on without digging into every 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%2Fq0lzwvbtrkkepeye5iop.jpg" 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%2Fq0lzwvbtrkkepeye5iop.jpg" alt="A screenshot of Pull Request Summary from Gemini Code Assist" width="800" height="881"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🕵🏼‍♂️ 2. Code Review Summary
&lt;/h3&gt;

&lt;p&gt;A few seconds (or minutes) later, Gemini posts a second comment, this one focuses on &lt;strong&gt;what it found&lt;/strong&gt; during its review. It covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A general overview of all detected issues&lt;/li&gt;
&lt;li&gt;Severity and potential impact of each issue (from small nitpicks to critical bugs)&lt;/li&gt;
&lt;li&gt;Suggested improvements to fix or enhance the code&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%2F7vqgvdlswlj8z2gypdv3.jpg" 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%2F7vqgvdlswlj8z2gypdv3.jpg" alt="A screenshot of Code Review Summary from Gemini Code Assist" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔍 3. Code Reviews comments and proposals
&lt;/h3&gt;

&lt;p&gt;For each specific issue spotted, Gemini also leaves &lt;strong&gt;inline comments&lt;/strong&gt; right where the problems are in code. Each detailed review includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;priority level&lt;/strong&gt; of the issue (critical, high, medium, or low)&lt;/li&gt;
&lt;li&gt;A clear explanation of &lt;strong&gt;what to change&lt;/strong&gt; (sometimes with examples)&lt;/li&gt;
&lt;li&gt;A reference to the &lt;strong&gt;style guide rule&lt;/strong&gt; (either Gemini’s defaults or your custom rules)&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%2F05a82ya9ty4tfvx9x5di.jpg" 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%2F05a82ya9ty4tfvx9x5di.jpg" alt="A screenshot of Code Review comments from Gemini Code Assist" width="800" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Gemini Code Assist is currently in preview and may make mistakes. &lt;br&gt;
You can react with 👍 and 👎 on gemini-code-assist's comments to provide feedback.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🙋🏼 4. Answer questions
&lt;/h3&gt;

&lt;p&gt;You can directly ask Gemini Code Assist questions inside pull request comments!&lt;/p&gt;

&lt;p&gt;Just mention it manually, and it will read the surrounding code and answer right in the thread with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A clear, concise answer based on the code and the context.&lt;/li&gt;
&lt;li&gt;Additional insights or clarifications if needed (e.g., explaining a complex change, suggesting alternatives).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is super useful when you want a second opinion or quick advice without waiting for a human reviewer.&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%2Fxe66g536jyyeh9tm8z4j.jpg" 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%2Fxe66g536jyyeh9tm8z4j.jpg" alt="A screenshot of a question on a line of code for Gemini Code Assist" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a really simple question here 😄&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🛠️ Customizing Gemini for Your Project
&lt;/h2&gt;

&lt;p&gt;By default, Gemini Code Assist acts like a well-trained reviewer even without any customization.&lt;/p&gt;

&lt;p&gt;Here’s what it looks for when reviewing your pull requests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Correctness&lt;/strong&gt;: It checks if your code actually does what it’s supposed to. Gemini looks for logic errors, bad API usage, forgotten edge cases, or even race conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency&lt;/strong&gt;: It spots performance issues like unnecessary loops, memory leaks, inefficient data structures, and heavy logging that could slow down your app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Gemini cares about your future self. It flags messy variable names, overly complex functions, code duplication, missing documentation, inconsistent formatting, and anything that could make your code harder to read or maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: It keeps an eye out for common security issues like input validation problems, insecure data storage, missing access controls, or vulnerabilities like CSRF and IDOR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Miscellaneous&lt;/strong&gt;: It can also comment on things like testing, scalability, modularity, and error handling/logging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Guiding Gemini on how to review your code.
&lt;/h3&gt;

&lt;p&gt;Just add a &lt;code&gt;.gemini/&lt;/code&gt; folder at the root of your repo with these two files:&lt;/p&gt;

&lt;h4&gt;
  
  
  🔧 &lt;code&gt;config.yaml&lt;/code&gt; — Control what Gemini does
&lt;/h4&gt;

&lt;p&gt;This file controls &lt;strong&gt;how much&lt;/strong&gt; Gemini talks and &lt;strong&gt;when&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;have_fun&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;code_review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;comment_severity_threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MEDIUM&lt;/span&gt;
  &lt;span class="na"&gt;max_review_comments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="na"&gt;pull_request_opened&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;code_review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration tells Gemini to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only flag issues that are medium severity or higher.&lt;/li&gt;
&lt;li&gt;Cap the number of comments to avoid overwhelming you.&lt;/li&gt;
&lt;li&gt;Always post a PR summary and code review when a PR is opened.&lt;/li&gt;
&lt;li&gt;And most important, to enable fun features such as a poem in the initial pull request summary.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📘 &lt;code&gt;styleguide.md&lt;/code&gt; — Teach it your rules
&lt;/h4&gt;

&lt;p&gt;You can write your own &lt;strong&gt;custom coding rules&lt;/strong&gt; for Gemini to follow.&lt;/p&gt;

&lt;p&gt;For this Go Project, mine’s really simple but you can include stuff like project structure, naming convention, tooling, code style, etc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Always return early in functions to reduce nesting.&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Avoid using `panic` outside of `main()` or tests.&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Always check for `err` immediately after a function call.&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Use `log/slog` instead of `fmt.Println`.&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Group standard library imports separately from third-party imports.&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Avoid magic numbers; define them as constants.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s not just basic linting — it actually &lt;em&gt;adjusts its review&lt;/em&gt; based on what &lt;em&gt;you&lt;/em&gt; care about.&lt;/p&gt;

&lt;p&gt;You can check a complete example &lt;a href="https://developers.google.com/gemini-code-assist/docs/customize-gemini-behavior-github#style-guide" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧵 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you’re working solo or on a small team, Gemini Code Assist is a super assistant. It saves time, catches issues, and makes your PRs feel way more professional, even if they’re just for a weekend side project.&lt;/p&gt;

&lt;p&gt;I’ll keep using it to double-check my PRs and level up my code reviews (even if it's just me reviewing myself 😅).&lt;/p&gt;

&lt;p&gt;If you already use it, let me know what your config looks like or if you’ve found creative ways to use it!&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 Official docs
&lt;/h2&gt;

&lt;p&gt;Check out the official docs here :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/gemini-code-assist/docs/review-github-code" rel="noopener noreferrer"&gt;https://developers.google.com/gemini-code-assist/docs/review-github-code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/gemini-code-assist/docs/customize-gemini-behavior-github" rel="noopener noreferrer"&gt;https://developers.google.com/gemini-code-assist/docs/customize-gemini-behavior-github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>google</category>
      <category>gemini</category>
      <category>programming</category>
    </item>
    <item>
      <title>Web3 : Le bilan de Google Cloud sur la blockchain en 2024</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Wed, 11 Dec 2024 07:55:31 +0000</pubDate>
      <link>https://forem.com/zenika/web3-le-bilan-de-google-cloud-sur-la-blockchain-en-2024-2i4</link>
      <guid>https://forem.com/zenika/web3-le-bilan-de-google-cloud-sur-la-blockchain-en-2024-2i4</guid>
      <description>&lt;p&gt;Google Cloud continue de renforcer sa présence dans l'écosystème blockchain, avec des innovations technologiques, des partenariats stratégiques, et une volonté affichée de démocratiser le Web3.&lt;/p&gt;

&lt;p&gt;Tour d'horizon des initiatives marquantes pour cette année 2024&lt;/p&gt;




&lt;h2&gt;
  
  
  Un nouveau portail Web3, enrichi et consolidé
&lt;/h2&gt;

&lt;p&gt;En Avril 2024, Google Cloud a lancé &lt;a href="https://cloud.google.com/application/web3/" rel="noopener noreferrer"&gt;&lt;strong&gt;un portail dédié au Web3&lt;/strong&gt;&lt;/a&gt;, centralisant outils et ressources pour les développeurs, entreprises et startups.&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%2Fc8t4w3exlq19u8pkgmv5.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%2Fc8t4w3exlq19u8pkgmv5.png" alt="Google Cloud Web3 Portal" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ce portail propose une gamme complète d’outils et de services, structurée autour de plusieurs axes majeurs :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;L’onglet&lt;/strong&gt; « &lt;strong&gt;Discover&lt;/strong&gt; » : Tous les produits que Google Cloud et la communauté ont conçus pour les développeurs avec des outils dédiés à l’infrastructure, du data warehousing, de l’analytics pour l’analyse des données blockchain, etc. De nombreux réseaux blockchain sont supportés : Ethereum Mainnet et Goerli, Arbitrum, Avalanche, Cronos, Fantom, etc.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;L’onglet&lt;/strong&gt; « &lt;strong&gt;Faucet&lt;/strong&gt; »: Un espace permettant le déploiement et les tests sur les réseaux Ethereum (Sepolia et Holesky)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;L’onglet&lt;/strong&gt; « &lt;strong&gt;Events&lt;/strong&gt; »: Un espace regroupant tous les événements passés ou futurs autour du Web3 et de ses partenaires&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;L’onglet&lt;/strong&gt; « &lt;strong&gt;Learn&lt;/strong&gt; »: Toutes les ressources pour vous former dans ce domaine. Vous pouvez retrouver des tutoriels vidéos tels que “Develop an NFT on Ethereum”, “Using Firebase with Web3Auth” ou encore “Secure Digital Assets with MPC”.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;L’onglet&lt;/strong&gt; « &lt;strong&gt;Community&lt;/strong&gt; »: Des liens vers des communautés et les réseaux supportés par Google Cloud&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;L’onglet&lt;/strong&gt; « &lt;strong&gt;Startup Program&lt;/strong&gt; »: Un  &lt;a href="https://cloud.google.com/startup/web3" rel="noopener noreferrer"&gt;programme&lt;/a&gt;  dédié aux startups Web3, proposant deux parcours distincts selon le stade de développement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cette approche témoigne de la volonté de Google Cloud de démocratiser l’accès aux technologies Web3, même si certains outils restent encore très spécialisés pour le grand public.&lt;/p&gt;




&lt;h2&gt;
  
  
  SUI : Une collaboration centrée sur l’IA
&lt;/h2&gt;

&lt;p&gt;L’une des collaborations majeures de l’année est celle avec &lt;a href="https://sui.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;SUI, une blockchain Layer 1&lt;/strong&gt;&lt;/a&gt; issue des travaux de l’équipe derrière les projets &lt;a href="https://fr.wikipedia.org/wiki/Diem_%28cryptomonnaie%29" rel="noopener noreferrer"&gt;Libra et Diem de Facebook&lt;/a&gt;. En partenariat avec &lt;a href="https://www.mystenlabs.com/" rel="noopener noreferrer"&gt;Mysten Labs&lt;/a&gt;, Google Cloud a travaillé sur plusieurs axes stratégiques :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Analyse des données&lt;/strong&gt; : l’intégration des données de la blockchain SUI dans BigQuery permettant aux développeurs d’accéder à des outils analytiques avancés pour la création de dApps.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;IA et sécurité&lt;/strong&gt; : grâce à Vertex AI, entrainé sur le &lt;a href="https://sui.io/move" rel="noopener noreferrer"&gt;langage de programmation de smart-contract MOVE&lt;/a&gt;, SUI a développé des outils d’audit et de génération de code basés sur l’intelligence artificielle pour améliorer la sécurité et optimiser le développement.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Amélioration de l’expérience utilisateur&lt;/strong&gt; : la technologie &lt;a href="https://sui.io/zklogin" rel="noopener noreferrer"&gt;zkLogin&lt;/a&gt; permet de combler certaines lacunes entre les applications traditionnelles (Web2) et décentralisées (Web3). Elle utilise des identifiants OAuth de Google et d’autres plateformes Web2 de confiance pour simplifier l’authentification sur les applications Web3 et les portefeuilles numériques.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Infrastructure&lt;/strong&gt; : la scalabilité de l’infrastructure Google Cloud garantit la performance du réseau SUI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Amit Zavery&lt;/em&gt;, Vice-Président, General Manager et Responsable des plateformes chez Google Cloud, &lt;a href="https://www.googlecloudpresscorner.com/2024-04-30-Sui-Teams-Up-with-Google-Cloud-to-Drive-Web3-Innovation-with-Enhanced-Security,-Scalability-and-AI-Capabilities" rel="noopener noreferrer"&gt;souligne&lt;/a&gt; :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;« Nous nous engageons à soutenir l’innovation Web3 grâce à notre infrastructure cloud sécurisée et nos capacités en intelligence artificielle. »&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Comme le &lt;a href="https://www.googlecloudpresscorner.com/2024-04-30-Sui-Teams-Up-with-Google-Cloud-to-Drive-Web3-Innovation-with-Enhanced-Security,-Scalability-and-AI-Capabilities" rel="noopener noreferrer"&gt;rappelle&lt;/a&gt; également &lt;em&gt;Evan Cheng&lt;/em&gt;, CEO et co-fondateur de Mysten Labs :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;« La collaboration avec Google Cloud nous aide à propulser le développement d’expériences Web3 sécurisées, évolutives et centrées sur l’utilisateur. »&lt;br&gt;
Ce partenariat illustre parfaitement la synergie entre l’expertise technologique de Google Cloud et l’innovation de SUI.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Une infrastructure RPC renforcée
&lt;/h2&gt;

&lt;p&gt;Google Cloud a étendu ses capacités avec le lancement du service &lt;a href="https://cloud.google.com/products/blockchain-rpc?hl=fr" rel="noopener noreferrer"&gt;&lt;strong&gt;Blockchain Remote Procedure Call (RPC)&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt; Ce service offre des fonctionnalités clés :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Compatibilité&lt;/strong&gt;: Un support pour Ethereum mainnet et testnet&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Performance et accessibilité&lt;/strong&gt; : jusqu’à 100 appels par seconde dans son niveau gratuit.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Interopérabilité&lt;/strong&gt; : compatible avec le protocole Ethereum JSON-RPC, facilitant son intégration dans des systèmes existants.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Extension future&lt;/strong&gt; : Google prévoit d’ajouter la prise en charge de nouveaux réseaux blockchain en 2025.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Un service RPC est essentiel pour interagir avec une blockchain. Il permet aux développeurs et aux applications de communiquer avec les nœuds du réseau blockchain en envoyant des requêtes et en recevant des réponses. Grâce à cette couche d’abstraction, les développeurs et les utilisateurs peuvent interagir facilement avec la blockchain sans devoir gérer la complexité technique sous-jacente, comme la synchronisation des nœuds ou le traitement des données brutes.&lt;/p&gt;

&lt;p&gt;L’engagement de Google Cloud pour améliorer l’interaction avec les données blockchain &lt;a href="https://cloud.google.com/blog/topics/financial-services/introducing-blockchain-rpc-service-for-web3-builders?hl=en" rel="noopener noreferrer"&gt;a été salué&lt;/a&gt;, notamment par &lt;em&gt;Kyle Quintal&lt;/em&gt; de &lt;a href="https://www.0xarc.io/" rel="noopener noreferrer"&gt;0xArc&lt;/a&gt; :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;« Les offres RPC de Google Cloud offrent des temps de réponse rapides — exactement ce que vous attendez. »&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Blockchain et gaming : GameStack et l’essor du Web3 dans les jeux
&lt;/h2&gt;

&lt;p&gt;L’année 2024 a également vu un rapprochement entre Google Cloud et l’industrie du jeu vidéo via des partenariats comme celui avec &lt;a href="https://sequence.xyz/" rel="noopener noreferrer"&gt;&lt;strong&gt;Sequence&lt;/strong&gt;&lt;/a&gt;. Cette &lt;strong&gt;plateforme tout-en-un pour le développement de jeux Web3&lt;/strong&gt; est désormais disponible sur Google Cloud Marketplace, facilitant l’intégration de technologies blockchain dans les jeux vidéo.&lt;/p&gt;

&lt;p&gt;Les outils fournis incluent des Unity APIs et des fonctionnalités pour gérer portefeuilles, NFT et transactions. Sequence prend en charge toutes les blockchains EVM, y compris les Layers 1 et 2, ainsi que les Layers 3/App Chains.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dai Vu&lt;/em&gt;, directeur général des programmes Marketplace et ISV GTM chez Google Cloud, a déclaré :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;« Amener Sequence sur Google Cloud Marketplace aidera les clients à déployer, gérer et développer rapidement la plateforme de développement de jeux Web3 sur l’infrastructure de Google Cloud. Sequence peut désormais évoluer en toute sécurité et accompagner ses clients dans leur transformation numérique. »&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Comme l’a &lt;a href="https://x.com/_michaelsanders/status/1849452302203064499" rel="noopener noreferrer"&gt;expliqué&lt;/a&gt; &lt;em&gt;Michael Sanders&lt;/em&gt;, cofondateur de Sequence :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;« Nous nous sommes lancés sur Google Cloud Marketplace en tant que fournisseur d’infrastructure pour les jeux Web3, afin d’aider les développeurs à attirer, fidéliser et monétiser les joueurs tout en offrant des expériences de jeu disruptives. »&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Un message fort contre la fraude
&lt;/h2&gt;

&lt;p&gt;Google Cloud démontre également son engagement dans la &lt;strong&gt;sécurisation de l’écosystème Web3&lt;/strong&gt; en adoptant des mesures juridiques inédites. L’entreprise a engagé une action en justice contre un groupe ayant proposé des applications frauduleuses sur la plateforme Google Play pendant plusieurs années. Ces applications, qui promettaient des gains exceptionnels à ceux investissant dans les cryptomonnaies, ont en réalité permis de détourner des sommes considérables.&lt;/p&gt;

&lt;p&gt;Pour la première fois, &lt;strong&gt;Google&lt;/strong&gt; a choisi de poursuivre &lt;strong&gt;en justice&lt;/strong&gt; les deux principaux instigateurs de cette fraude, en s’appuyant sur la &lt;a href="https://fr.wikipedia.org/wiki/Racketeer_Influenced_and_Corrupt_Organizations_Act#:~:text=Le%20Racketeer%20Influenced%20and%20Corrupt,des%20activit%C3%A9s%20d%27une%20organisation" rel="noopener noreferrer"&gt;loi &lt;strong&gt;RICO&lt;/strong&gt;&lt;/a&gt; (&lt;em&gt;Racketeer Influenced and Corrupt Organizations&lt;/em&gt;), habituellement utilisée dans des affaires de crime organisé. Cette initiative positionne Google comme pionnier parmi les entreprises technologiques dans l’utilisation de ce cadre juridique pour lutter contre les escroqueries.&lt;/p&gt;

&lt;p&gt;Comme &lt;a href="https://www.linkedin.com/posts/halimah-delaine-prado-2002895_google-sues-crypto-scammers-for-allegedly-activity-7181685413785284608-4Yco/" rel="noopener noreferrer"&gt;le souligne&lt;/a&gt; &lt;em&gt;Halimah DeLaine Prado&lt;/em&gt;, avocat pour Google :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;« Rien qu’en 2023, nous avons vu plus d’un milliard de dollars de fraudes et d’escroqueries aux cryptomonnaies aux États-Unis et ce dossier nous permet non seulement d’utiliser nos ressources pour protéger les utilisateurs, mais également de servir en quelque sorte de précédent aux futurs mauvais acteurs dont nous ne pouvons tolérer le comportement. »&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  La suite en 2025
&lt;/h2&gt;

&lt;p&gt;En 2024, Google Cloud confirme son ambition de devenir un acteur majeur du Web3 en proposant une infrastructure complète et sécurisée. Entre innovations techniques, partenariats stratégiques et engagement contre la fraude, la plateforme pose les jalons d’un écosystème Web3 plus mature et accessible. Les développements à venir, notamment l’extension du support RPC à d’autres réseaux blockchain, laissent présager de nouvelles avancées significatives dans les mois à venir.&lt;/p&gt;

&lt;p&gt;Rendez-vous l’année prochaine.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>googlecloud</category>
      <category>blockchain</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Reflecting on my Hacktoberfest 2024 journey</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Tue, 29 Oct 2024 22:01:37 +0000</pubDate>
      <link>https://forem.com/bengeois/reflecting-on-my-hacktoberfest-2024-journey-816</link>
      <guid>https://forem.com/bengeois/reflecting-on-my-hacktoberfest-2024-journey-816</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest"&gt;2024 Hacktoberfest Writing challenge&lt;/a&gt;: Contributor Experience&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This month, I had the pleasure of diving into Hacktoberfest proactively with a few clear goals in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Hacktoberfest 🎉
&lt;/h2&gt;

&lt;p&gt;1️⃣ First, I wanted to discover the world of open source, as I’ve always admired the collaborative nature of these projects.&lt;/p&gt;

&lt;p&gt;2️⃣ Secondly, I was motivated to contribute to projects that I personally use or find useful, because I believe in helping to maintain and improve projects that I hope will continue to be available to the community.&lt;/p&gt;

&lt;p&gt;3️⃣ Finally, I saw Hacktoberfest as a great technical challenge. Working on real projects helps me learn faster, and solving real problems while getting feedback directly is the best way to improve my skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Projects I Contributed To 🏗️
&lt;/h2&gt;

&lt;p&gt;I chose two projects that intrigued me for different reasons:&lt;/p&gt;

&lt;h3&gt;
  
  
  Git Town
&lt;/h3&gt;

&lt;p&gt;I initially started contributing to Git-Town by updating the documentation while trying to install it. 😅&lt;/p&gt;

&lt;p&gt;Just after I noticed other issues that intrigued me and moved on to more complex tasks, specifically addressing breaking changes. This phase of my contribution was a highlight; I discussed with the project creator and one other maintainer on a way to implement these changes carefully, ensuring they were integrated in a way that minimized disruption to users. This allowed us to rapidly deploy the new release.&lt;/p&gt;

&lt;p&gt;After theses changes, I was thrilled when the creator added me to the Git-Town organization on GitHub. This recognition gave me a real sense of achievement and encouraged me to continue contributing to this project.&lt;/p&gt;

&lt;p&gt;You can find the project &lt;a href="https://github.com/git-town/git-town" rel="noopener noreferrer"&gt;here&lt;/a&gt; 💚 &lt;/p&gt;

&lt;h3&gt;
  
  
  Open Food Facts
&lt;/h3&gt;

&lt;p&gt;I came across Open Food Facts while reading a blog post on project to contribute to during Hacktoberfest, and its public benefit and mission immediately resonated with me. It is a public database of food products from around the world, providing information on ingredients, nutrition, and environmental impact to help users make informed choices.&lt;/p&gt;

&lt;p&gt;I chose to focus on updating the Node.js SDK by adding wrappers for the latest API endpoints, writing unit tests, improving CI/CD, and working towards automatic releases of new versions. Through this, I hope to support the project’s growth and stability, ensuring it’s reliable for anyone who wishes to use it to create projects that rely on Open Food Facts. There are often very good project ideas in the opensource world 🙂&lt;/p&gt;

&lt;p&gt;You can find the project &lt;a href="https://github.com/openfoodfacts" rel="noopener noreferrer"&gt;here&lt;/a&gt; 💚  &lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and Learning Moments 🤗
&lt;/h2&gt;

&lt;p&gt;The most challenging part of Hacktoberfest was getting started with each project. Understanding how the project works and integrating my contributions with the existing architecture required time and patience. It is important to minimize breaking changes wherever possible, which is often easier said than done.&lt;/p&gt;

&lt;p&gt;Contributing to open source also reminds how to work asynchronously. Each contributor has their own schedule, and learning to adapt to different timelines and communicate effectively has been a valuable experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Forward 🙌
&lt;/h2&gt;

&lt;p&gt;My journey into open source was also made possible by my company, &lt;a href="https://www.zenika.com/en-US" rel="noopener noreferrer"&gt;Zenika&lt;/a&gt;, which encourages us to engage with this ecosystem. Zenika has a dedicated website, &lt;a href="https://oss.zenika.com/" rel="noopener noreferrer"&gt;oss.zenika.com&lt;/a&gt;, to support open-source involvement, and every October, we host events like live streams, meetups, and more to promote participation.&lt;/p&gt;

&lt;p&gt;We also have a dedicated Github Organisation that can be useful if you're interested in joining this ecosystem like this repository on how to promote &lt;a href="https://github.com/zenika-open-source/promote-open-source-project" rel="noopener noreferrer"&gt;Open Source Projects&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hacktoberfest has left me with a sense of accomplishment and a desire to continue contributing to open-source. If you’re new to open source, I encourage you to explore the many resources available, from GitHub to community spaces like &lt;a href="https://discord.com/invite/hacktoberfest" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;, where you can connect with other contributors and learn more about active projects.&lt;/p&gt;

&lt;p&gt;Open-source work is often done in people’s personal time, so it’s important to be proactive and patient. Maintainers and contributors may not always be immediately available. 🙌&lt;/p&gt;

&lt;p&gt;Thank you for taking an interest in open source. Remember, there are likely more tools you use than you think that rely on open-source contributions 😄&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hacktoberfest</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Démarrez votre projet Web3 : panorama tech du développement de smart contracts en 2024</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Tue, 08 Oct 2024 09:00:00 +0000</pubDate>
      <link>https://forem.com/zenika/demarrez-votre-projet-web3-panorama-tech-du-developpement-de-smart-contracts-en-2024-589b</link>
      <guid>https://forem.com/zenika/demarrez-votre-projet-web3-panorama-tech-du-developpement-de-smart-contracts-en-2024-589b</guid>
      <description>&lt;p&gt;L'idée des smart contracts n'est pas nouvelle. Le concept a été théorisé pour la première fois par &lt;em&gt;Nick Szabo&lt;/em&gt;, un informaticien et cryptographe, en 1994. Il a imaginé un système de "contrats numériques" qui pourraient s'exécuter automatiquement sans l'intervention d'un tiers de confiance.&lt;/p&gt;

&lt;p&gt;Cependant, il a fallu attendre l'avènement de la technologie blockchain pour que les smart contracts deviennent une réalité. La blockchain est un registre distribué et sécurisé qui permet de stocker et de vérifier des transactions de manière transparente. Cette technologie offre un environnement idéal pour l'exécution de smart contracts, car elle garantit la sécurité et l'immuabilité des données.&lt;/p&gt;

&lt;p&gt;Ethereum a été la première plateforme à implémenter des smart contracts. Lancée en 2015, elle a permis aux développeurs de créer et de déployer des contrats sur sa blockchain. Cette innovation a déclenché une vague d'intérêt et a conduit à la création de nombreuses autres plateformes et applications décentralisées.&lt;/p&gt;

&lt;p&gt;Plusieurs facteurs contribuent à la tendance actuelle :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;L'essor des registres distribués&lt;/strong&gt; : les registres distribués, dont la blockchain est un sous-type, offrent une infrastructure sécurisée et transparente pour l'exécution de smart contracts. Pour simplifier, nous utiliserons le terme "blockchain" par la suite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La demande croissante de solutions automatisées&lt;/strong&gt; : Les entreprises et les particuliers recherchent des solutions automatisées pour simplifier les processus et réduire les coûts. Pouvons nous imaginer une solution automatisée de gestion de l’immobilier ?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Les avantages potentiels des smart contracts&lt;/strong&gt; : Ils peuvent offrir de nombreux avantages, tels que la sécurité, l'efficacité et la réduction des risques.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La tendance est encore à ses débuts, mais elle a le potentiel de révolutionner de nombreux secteurs d'activité.&lt;br&gt;
Dans cet article, nous explorerons l’état de l’art du développement des smart contracts, les langages et outils pour le développement puis les défis et solutions ainsi que les futures tendances en 2024.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TL;DR&lt;/p&gt;

&lt;p&gt;En 2024, le développement des smart contracts continue d'évoluer rapidement, notamment grâce à des plateformes comme Ethereum, Binance Smart Chain, Solana, et Polkadot, chacune offrant des caractéristiques uniques en termes de scalabilité (vitesse), de sécurité et de décentralisation (plus d’informations sur ces 3 piliers en regardant le trilemme de la blockchain). Les langages comme Solidity ou Rust dominent le développement, tandis que de nouveaux outils et frameworks simplifient le processus de création et de déploiement. Malgré les défis persistants de sécurité et de scalabilité, les innovations telles que les oracles, l'inter-opérabilité, et les organisations autonomes décentralisées, ou Decentralized Autonomous Organization (DAOs), ouvrent la voie à des applications plus avancées. Le paysage juridique et éthique reste complexe, mais des efforts sont en cours pour créer un cadre réglementaire plus clair, favorisant une adoption responsable et bénéfique des smart contracts.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Choisir la bonne plateforme : une décision stratégique pour la viabilité de votre projet.
&lt;/h2&gt;

&lt;p&gt;Les plateformes permettant l’exécution de smart contracts sont nombreuses et variées, chacune offrant des caractéristiques uniques qui peuvent influencer la manière dont vos applications sont développées et exécutées.&lt;/p&gt;

&lt;p&gt;Les blockchains peuvent être envisagées comme des réseaux décentralisés qui hébergent et exécutent des applications de manière sécurisée et transparente. Elles assurent la vérification et la validation des transactions par un consensus distribué, éliminant ainsi le besoin de tiers de confiance. Ces réseaux peuvent être classés principalement en deux types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Les blockchains publiques&lt;/strong&gt; sont des réseaux ouverts à tous où chaque utilisateur peut participer en tant que nœud, valider des transactions, et interagir avec le réseau sans restrictions. Elles sont plus décentralisées et transparentes, au prix de coûts de transaction plus élevés et de difficultés de scalabilité&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Les blockchains privées&lt;/strong&gt; sont des réseaux restreints où l'accès est limité à des utilisateurs ou des organisations spécifiques. Ces blockchains sont souvent utilisées dans un cadre d'entreprise ou par des consortiums où la confidentialité des données et le contrôle sur le réseau sont des priorités mais perdent en sécurité et en interopérabilité.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choisir la bonne blockchain pour développer et déployer des applications décentralisées (dApps) ou des smart contracts est une décision stratégique qui peut avoir un impact significatif sur le succès de votre projet. Pour vous guider dans votre choix, voici une liste (non exhaustive) de points à considérer :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance et Scalabilité&lt;/strong&gt; : Cela comprend la vitesse de traitement des transactions, le débit du réseau, et la capacité à gérer une augmentation de l'utilisation sans compromettre les performances. Par exemple, Solana est réputée pour sa capacité à traiter plusieurs milliers de transactions par seconde, tandis qu'Ethereum est plus lente mais dispose d'une infrastructure bien établie.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mécanisme de consensus&lt;/strong&gt; : Tenez compte du mécanisme de consensus d'une blockchain spécifique en relation avec la sécurité, la vitesse et le coût. Par exemple, la preuve de travail (PoW) est gourmande en énergie pour garantir une sécurité maximale, tandis que la preuve d'enjeu (PoS) est plus économe en énergie tout en offrant une meilleure scalabilité. Il convient d'étudier les mécanismes sous tous les angles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Les langages de programmation&lt;/strong&gt; : Ils peuvent influencer le choix en fonction des exigences techniques du projet et de la plateforme choisie. Ethereum utilise bytecode qui sera interprété par l’EVM. Solidity est un langage orienté pour les smart contracts qui permet d’être compilé en bytecode. C'est le choix dominant pour la plupart des développeurs de dApps. Tandis que Polkadot : Permet l'utilisation de Rust pour développer des blockchains personnalisées.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La sécurité&lt;/strong&gt; : c'est un aspect fondamental qui doit être examiné sous différents angles. Il ne s'agit pas seulement du degré de décentralisation, mais aussi de l'historique de sécurité de la blockchain. Une blockchain plus décentralisée est généralement plus résistante aux attaques et plus transparente. Par exemple, Bitcoin et Ethereum sont souvent considérés comme hautement décentralisés. Vérifiez si la plateforme effectue des audits réguliers de sécurité et si elle a une communauté active qui signale et corrige rapidement les vulnérabilités.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L'écosystème et la communauté de développeurs&lt;/strong&gt; : un écosystème robuste peut accélérer le développement de votre projet. Il peut être important de savoir s'il y a déjà tout un écosystème d'applis et de protocoles sur lesquels s'appuyer pour construire de nouveaux produits. La capacité d'interagir avec d'autres blockchains et applications est cruciale pour certaines applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La gouvernance&lt;/strong&gt; : elle définit comment les décisions concernant la blockchain sont prises. Comprendre le modèle de gouvernance est essentiel pour évaluer comment les mises à jour, les changements de protocole, et les conflits sont gérés.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Le niveau d'adoption&lt;/strong&gt; : l’adoption par les utilisateurs et les entreprises est un indicateur clé de la maturité et de la viabilité de la blockchain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;De nombreuses plateformes supportent les smart contracts. Ici, nous comparerons les 10 plus populaires, ce qui donnera déjà une bonne idée des structures disponibles.&lt;/p&gt;

&lt;p&gt;Pour donner une idée globale de la comparaison suivante, voici un tableau récapitulatif :&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%2F9vr3mhus3q645jgg5bz8.jpg" 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%2F9vr3mhus3q645jgg5bz8.jpg" alt="Tableau comparatif des caractéristiques des blockchains" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Ethereum
&lt;/h3&gt;

&lt;p&gt;Ethereum est une blockchain publique et open-source. Lancée en 2015 par &lt;em&gt;Vitalik Buterin&lt;/em&gt;, Ethereum est devenue la plateforme de développement de smart contracts la plus populaire et la plus mature.&lt;/p&gt;

&lt;p&gt;Le principal langage de programmation utilisé dans Ethereum est "turing-complet", c'est-à-dire la capacité à gérer tout calcul réalisable par une machine universelle. Son potentiel est donc illimité. Cela permet aux programmeurs de créer des smart contracts sophistiqués, ouvrant ainsi une multitude de possibilités d'application.&lt;/p&gt;

&lt;p&gt;Pour pallier certains de ses inconvénients, Ethereum s'appuie de plus en plus sur des solutions appelées “Layer 2”. Ces couches supplémentaires sont conçues pour améliorer la scalabilité et réduire les frais de transaction en traitant une partie des calculs en dehors de la chaîne principale.&lt;/p&gt;

&lt;p&gt;Avantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les smart contracts ne sont pas limités à de simples transactions&lt;/li&gt;
&lt;li&gt;Sécurité éprouvée&lt;/li&gt;
&lt;li&gt;Décentralisation&lt;/li&gt;
&lt;li&gt;Large communauté de développeurs et d'utilisateurs&lt;/li&gt;
&lt;li&gt;Large éventail d'outils et de ressources disponibles&lt;/li&gt;
&lt;li&gt;Grande variété de dApps déjà déployées&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inconvénients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frais de transaction élevés, surtout pour les transactions complexes&lt;/li&gt;
&lt;li&gt;Scalabilité limitée&lt;/li&gt;
&lt;li&gt;Volume d'utilisation élevé, peut entraîner une congestion et ralentir la vitesse des transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mécanisme de consensus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proof-of-Stake (PoS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Langage de développement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les principaux langages de programmation utilisés sont Solidity et Vyper. Les smart-contracts doivent d'abord être compilés en Bytecode. C'est ce Bytecode qui permet à la Machine Virtuelle Ethereum (EVM) d'exécuter le contrat sur la blockchain.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Ethereum + Layer 2
&lt;/h3&gt;

&lt;p&gt;Ethereum reste la blockchain de référence pour le développement de smart contracts, mais ses limitations en termes de scalabilité et de frais de transaction ont conduit au développement de solutions Layer 2. Les Layer 2 sont des protocoles construits sur le dessus d'une blockchain principale (Layer 1) pour réduire la congestion et améliorer l'efficacité des transactions. En déplaçant une partie du processus de transaction hors de la chaîne principale, les Layers 2 permettent de traiter un volume plus élevé de transactions à moindre coût. On peut donc les voir comme des "extensions" du réseau Ethereum.&lt;/p&gt;

&lt;p&gt;Avantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Réduction des frais de transaction en déchargeant une partie des transactions&lt;/li&gt;
&lt;li&gt;Amélioration de la scalabilité&lt;/li&gt;
&lt;li&gt;Sécurité inhérente à Ethereum&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inconvénients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adoption progressive&lt;/li&gt;
&lt;li&gt;Fragmentation: Plusieurs solutions Layer 2 existent (comme Optimistic Rollups et ZK-Rollups), ce qui peut fragmenter l'écosystème et créer des silos.&lt;/li&gt;
&lt;li&gt;Complexité supplémentaire: L'intégration de solutions Layer 2 ajoute une couche de complexité pour les développeurs et les utilisateurs, notamment en termes de transfert de fonds entre les layers.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Binance Smart Chain (BSC)
&lt;/h3&gt;

&lt;p&gt;Binance Smart Chain (BSC) est une blockchain privée compatible avec la EVM (Ethereum Virtual Machine) d'Ethereum. Lancée en 2020 par Binance, BSC offre une alternative à Ethereum avec des frais de transaction plus bas et une vitesse de transaction plus élevée.&lt;/p&gt;

&lt;p&gt;Avantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faible coût de transaction&lt;/li&gt;
&lt;li&gt;Vitesse de transaction élevée&lt;/li&gt;
&lt;li&gt;Large adoption par les utilisateurs de Binance&lt;/li&gt;
&lt;li&gt;Compatibilité avec la EVM d'Ethereum&lt;/li&gt;
&lt;li&gt;Intégration avec tout l’écosystème Binance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inconvénients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralisation&lt;/li&gt;
&lt;li&gt;Réseau dépendant de Binance&lt;/li&gt;
&lt;li&gt;Écosystème moins développé qu'Ethereum&lt;/li&gt;
&lt;li&gt;Moins de dApps disponibles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mécanisme de consensus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PoSA : un hybride entre la Proof-of-Stake (PoS) et la Proof-of-Authority (PoA). Le Proof-of-Staked Authority (PoSA) est un mécanisme de consensus hybride qui combine la Proof-of-Stake (PoS) et la Proof-of-Authority (PoA), où un ensemble de validateurs est sélectionné en fonction de la quantité de tokens qu'ils stakent (PoS) et de leur réputation ou autorité (PoA).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Langage de développement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solidity&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Solana
&lt;/h3&gt;

&lt;p&gt;Solana est une blockchain publique et open-source qui se concentre sur la vitesse de transaction et la scalabilité. Lancée en 2020 par &lt;em&gt;Anatoly Yakovenko&lt;/em&gt;, Solana utilise une architecture innovante, une combinaison entre le Proof-of-History et le Proof-of-Stake.&lt;/p&gt;

&lt;p&gt;Le Proof of History (PoH) fournit des horodatages vérifiables pour ordonner les transactions, et lorsqu'il est utilisé avec le Proof-of-Stake, il permet d'atteindre des vitesses de transaction très élevées, plusieurs milliers par seconde.&lt;/p&gt;

&lt;p&gt;Avantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architecture innovante pour la scalabilité et économe en énergie&lt;/li&gt;
&lt;li&gt;Vitesse de transaction très élevée&lt;/li&gt;
&lt;li&gt;Faible coût de transaction&lt;/li&gt;
&lt;li&gt;Les smart contracts sont écrit en Rust, ce qui garantit une sécurité élevée.&lt;/li&gt;
&lt;li&gt;Les smart contracts peuvent être traités de manière parallèle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inconvénients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moins décentralisée que d'autres blockchains car les nœuds validateurs demandent beaucoup de matériel&lt;/li&gt;
&lt;li&gt;Langage de programmation “bas niveau” ce qui est plus difficile à appréhender&lt;/li&gt;
&lt;li&gt;Plateforme relativement nouvelle&lt;/li&gt;
&lt;li&gt;Moins de ressources et d'outils disponibles&lt;/li&gt;
&lt;li&gt;Le réseau principal (mainnet) est toujours déclaré en bêta&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mécanisme de consensus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combinaison entre le Proof-of-History et le Proof-of-Stake&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Langage de développement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Avalanche
&lt;/h3&gt;

&lt;p&gt;Avalanche est une blockchain publique et open-source. Lancée en 2020 par &lt;em&gt;Emin Gün Sirer&lt;/em&gt;, Avalanche utilise un mécanisme de consensus unique conçu pour répondre à des normes de sécurité élevées et résister aux attaques.&lt;/p&gt;

&lt;p&gt;Le réseau permet la création de sous-réseaux et de blockchains personnalisées.&lt;/p&gt;

&lt;p&gt;Avantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Temps de transaction inférieur à la seconde&lt;/li&gt;
&lt;li&gt;Architecture unique pour la scalabilité et la sécurité, possibilité de brancher son réseau privé tout en conservant la sécurité des chaînes supérieures.&lt;/li&gt;
&lt;li&gt;Possibilité d’avoir des sous-réseaux, avec des règles et des fonctionnalités spécifiques adaptées aux besoins.&lt;/li&gt;
&lt;li&gt;Interopérabilité entre différentes blockchains&lt;/li&gt;
&lt;li&gt;Compatible avec la Machine Virtuelle Ethereum (EVM)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inconvénients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moins de ressources et d'outils disponibles&lt;/li&gt;
&lt;li&gt;Réseau relativement complexe avec une architecture unique, utilisant plusieurs blockchains (X-Chain, C-Chain et P-Chain)&lt;/li&gt;
&lt;li&gt;Le jeton natif d'Avalanche, AVAX, offre une liquidité limitée&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mécanisme de consensus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avalanche&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Langage de développement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solidity&lt;/li&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;D’autres plateformes pour développer des smart-contracts. Celles-ci sont moins courantes mais méritent d’y jeter un œil : Cardano, Polkadot, Near ou encore Tezos.&lt;/p&gt;


&lt;h2&gt;
  
  
  Le langage de développement, essentiel pour la stabilité et la longévité du projet
&lt;/h2&gt;

&lt;p&gt;Après avoir examiné les différentes plateformes de développement de smart contracts, il est important de s'intéresser aux langages de programmation qui leur sont associés.&lt;/p&gt;

&lt;p&gt;Le choix du langage de programmation est tout aussi important car il impacte la facilité de développement, la maintenabilité du code et la sécurité du contrat et des applications.&lt;/p&gt;

&lt;p&gt;Il existe une multitude de langages de programmation pour smart contracts, chacun avec ses propres avantages et inconvénients. Certains langages sont plus populaires que d'autres, comme Solidity pour Ethereum ou Rust pour Solana. Il est important de choisir un langage qui correspond à vos besoins spécifiques.&lt;/p&gt;

&lt;p&gt;Voici quelques points à prendre en compte lors du choix d'un langage de programmation pour smart contracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les fonctionnalités disponibles: Le langage choisi doit pouvoir répondre aux besoins de votre application.&lt;/li&gt;
&lt;li&gt;La syntaxe: Le langage doit être facile à apprendre et à utiliser.&lt;/li&gt;
&lt;li&gt;La sécurité: Le langage doit être sécurisé et permettre de développer des contrats robustes.&lt;/li&gt;
&lt;li&gt;La communauté de développeurs: Une communauté active de développeurs peut aider à trouver des réponses à vos questions et à résoudre les problèmes rencontrés&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous allons maintenant discuter des principaux langages de programmation dans ce domaine.&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%2Fbpkkz05ertot925t8d10.jpg" 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%2Fbpkkz05ertot925t8d10.jpg" alt="Tableau comparatif des caractéristiques des langages de programmation de smart-contracts" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Solidity
&lt;/h3&gt;

&lt;p&gt;Langage de programmation de haut niveau orienté objet pour les smart contracts sur la blockchain Ethereum et compatible avec la plupart des plateformes EVM (Ethereum Virtual Machine). C’est le langage de programmation le plus répandu pour développer des smart-contracts.&lt;/p&gt;

&lt;p&gt;Blockchains: Ethereum, Binance Smart Chain, Polygon, Avalanche, Fantom, et d’autres&lt;/p&gt;

&lt;p&gt;Avantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large communauté de développeurs et d'utilisateurs (plus de 200 000 développeurs actifs).&lt;/li&gt;
&lt;li&gt;Large éventail d'outils et de ressources disponibles (IDE, frameworks, bibliothèques, tutoriels).&lt;/li&gt;
&lt;li&gt;Bien documenté et facile à apprendre (syntaxe proche du C++ et du JavaScript).&lt;/li&gt;
&lt;li&gt;Large adoption par les plateformes et les projets DeFi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inconvénients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pas conçu pour la sécurité formelle (risques de bugs et de vulnérabilités).&lt;/li&gt;
&lt;li&gt;Manque de fonctionnalités avancées (gestion de la mémoire, typage générique).&lt;/li&gt;
&lt;li&gt;Sujet aux vulnérabilités de sécurité (attaques par reentrancy, overflow, etc.).
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pragma&lt;/span&gt; &lt;span class="nx"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="nx"&gt;SimpleContract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;storedData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="nc"&gt;ValueSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;storedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;emit&lt;/span&gt; &lt;span class="nc"&gt;ValueSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="nf"&gt;returns &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;storedData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rust
&lt;/h3&gt;

&lt;p&gt;Rust est un langage de programmation moderne. Il est apprécié pour sa sécurité de la mémoire, ses performances et sa concurrence. Des blockchains comme Solana l’ont adopté pour l’écriture de smart-contract.&lt;/p&gt;

&lt;p&gt;Blockchains: Solana, Near, Polkadot, etc.&lt;/p&gt;

&lt;p&gt;Avantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vitesse et performance élevées.&lt;/li&gt;
&lt;li&gt;Conçu pour éviter les erreurs de programmation telles que les accès mémoire invalides&lt;/li&gt;
&lt;li&gt;Convient aux applications complexes&lt;/li&gt;
&lt;li&gt;Langage stable et mature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inconvénients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Courbe d'apprentissage plus forte que Solidity.&lt;/li&gt;
&lt;li&gt;Moins de ressources et d'outils disponibles.&lt;/li&gt;
&lt;li&gt;Communauté de développeurs plus petite.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vous pouvez trouver différents projets blockchain utilisant Rust sur ce repo : &lt;a href="https://github.com/rust-in-blockchain/awesome-blockchain-rust" rel="noopener noreferrer"&gt;https://github.com/rust-in-blockchain/awesome-blockchain-rust&lt;/a&gt;&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="nd"&gt;#![no_std]&lt;/span&gt;
&lt;span class="nd"&gt;#![feature(alloc_error_handler)]&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;ink_lang&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[ink::contract]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;simple_contract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;string&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;#[ink(storage)]&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;SimpleContract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;SimpleContract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;#[ink(constructor)]&lt;/span&gt;
        &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;initial_value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;#[ink(message)]&lt;/span&gt;
        &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;#[ink(message)]&lt;/span&gt;
        &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  C++
&lt;/h3&gt;

&lt;p&gt;Développé par &lt;em&gt;Bjarne Stroustrup&lt;/em&gt; au début des années 1980, le C++ est un langage de programmation de haut niveau. C'est le sixième langage de programmation le plus populaire.&lt;/p&gt;

&lt;p&gt;Blockchain: EOS, Ripple, WAX&lt;/p&gt;

&lt;p&gt;Avantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Langage performant et flexible&lt;/li&gt;
&lt;li&gt;Convient aux applications complexes&lt;/li&gt;
&lt;li&gt;Sa syntaxe est bien connue des développeurs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inconvénients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supporté par quelques blockchains seulement&lt;/li&gt;
&lt;li&gt;Le code écrit en C++ n'est pas aussi concis que Solidity
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleContract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
      &lt;span class="c1"&gt;// Constructor to initialize the value (optional)&lt;/span&gt;
      &lt;span class="k"&gt;explicit&lt;/span&gt; &lt;span class="n"&gt;SimpleContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;initValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

      &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Access storage and update the value (implementation depends on the platform)&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Access storage and retrieve the value (implementation depends on the platform)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selon les plateformes de développement, d’autres langages de programmation existent mais avec des fonctionnalités moins avancées ou des communautés plus petites (Vyper, Michelson, Yul, …)&lt;/p&gt;




&lt;h3&gt;
  
  
  Les environnements de développement (frameworks, IDEs, …)
&lt;/h3&gt;

&lt;p&gt;Le développement de smart-contracts implique l'utilisation d'une variété d'outils pour simplifier le processus de création, de déploiement et de gestion des contrats.&lt;/p&gt;

&lt;p&gt;Ces outils peuvent être classés en différentes catégories :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Les frameworks&lt;/strong&gt; offrent des structures et des bibliothèques préexistantes pour faciliter le développement de smart contracts. Ils incluent des fonctionnalités pour le déploiement, la gestion des comptes, l'interaction avec la blockchain, la gestion des erreurs et la sécurité.&lt;/p&gt;

&lt;p&gt;Ils peuvent être accompagnés de CLIs, fournis par les plateformes telles que NEAR, Solana ou Polkadot, et apportent une manière native de déployer les smart contracts sur leur plateforme.&lt;/p&gt;

&lt;p&gt;Frameworks populaires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hardhat: Un framework modulaire pour le développement de smart contracts Ethereum. Il offre une flexibilité et une personnalisation pour s'adapter aux besoins spécifiques des projets.&lt;/li&gt;
&lt;li&gt;Anchor: Similaire à Truffle ou Hardhat mais pour Solana. Anchor permet de construire des programmes rapidement parce qu'il apporte de nombreuses fonctions prêtes à l’emploi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hardhat et Anchor sont les deux frameworks largement populaires sur le marché des smart-contracts, bien que d’autres initiatives existent comme Brownie qui essaie de tirer parti de la simplicité et de la puissance de Python. Auparavant, d’autres frameworks tels que Truffle ou Ganache existaient mais ils sont maintenant en “deprecated” au profit de Hardhat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Les IDEs&lt;/strong&gt; jouent un rôle essentiel dans la conception et permettent de réduire les erreurs, d'accélérer le développement, et d'améliorer la qualité du code.&lt;/p&gt;

&lt;p&gt;Remix IDE est probablement l'outil le plus connu pour démarrer dans l'écosystème Ethereum et EVM-compatible. Cet IDE en ligne permet d’écrire, compiler et déployer des smart contracts en Solidity, tout en offrant des outils d’analyse, de débogage, et même de simulation de transactions sur la blockchain.&lt;/p&gt;

&lt;p&gt;Sinon, un IDE classique comme Visual Studio Code, bien qu'universel et utilisé pour un large éventail de langages, est souvent favorisé par les développeurs blockchain grâce à ses nombreuses extensions qui transforment cet éditeur en un environnement pour le développement d'applications Web3, tout en permettant une intégration avec des outils de déploiement et de tests automatisés.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Les outils d'analyse pour explorer la blockchain&lt;/strong&gt; qui permettent de visualiser et d'analyser les transactions et les données des smart contracts sur la blockchain. Ils peuvent fournir des informations sur l'état des contrats, les interactions des utilisateurs, etc.&lt;/p&gt;

&lt;p&gt;Exemples populaires, bien qu’en général chaque plateforme (Blockchain et Layer 2) a son propre lot d’outils d’analyse :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Etherscan (&lt;a href="https://etherscan.io" rel="noopener noreferrer"&gt;https://etherscan.io&lt;/a&gt;) : Un explorateur de blocs populaire pour la blockchain Ethereum. Il permet de visualiser les transactions, les contrats, les adresses de portefeuille.&lt;/li&gt;
&lt;li&gt;Blockchair (&lt;a href="https://blockchair.com/fr):" rel="noopener noreferrer"&gt;https://blockchair.com/fr):&lt;/a&gt; Un explorateur de blocs multi-chaînes qui prend en charge la recherche et l'analyse des transactions et des contrats sur différentes blockchains.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Les tendances en 2024
&lt;/h2&gt;

&lt;p&gt;Le domaine du développement de smart contracts évolue rapidement avec l'émergence de nouvelles tendances et applications prometteuses, et notamment :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oracles: Les oracles sont des ponts entre le monde réel et les blockchains, fournissant aux smart contracts des flux de données externes afin d'accéder et d'interagir avec des données et des événements du monde réel. Cela ouvre de nouveaux cas d'utilisation dans des domaines tels que la finance décentralisée (DeFi), la gestion de la chaîne d'approvisionnement, etc&lt;/li&gt;
&lt;li&gt;Interopérabilité : L'interopérabilité permettrait à différentes blockchains de communiquer et d’effectuer des transactions les unes avec les autres de manière transparente, ce qui ouvre de nouvelles possibilités de collaboration. Les projets et les protocoles axés sur l'interopérabilité, tels que Polkadot ouvrent la voie à un écosystème de blockchain plus interconnecté et interopérable.&lt;/li&gt;
&lt;li&gt;Organisation autonome décentralisée (DAO): Les DAO sont des organisations gérées par des smart contracts, permettant une prise de décision et une gouvernance décentralisées, facilitant la gestion d'entreprises, de communautés et de projets collaboratifs.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Le développement de smart contracts est un domaine avec une communauté de développeurs très active, de nouveaux outils et leurs améliorations apparaissent régulièrement.&lt;/p&gt;

&lt;p&gt;En combinant l'immuabilité et la transparence de la blockchain avec l'automatisation et la programmabilité des contrats, les smart contracts ont le potentiel de transformer des industries entières et de créer de nouveaux paradigmes pour la collaboration et la gouvernance.&lt;/p&gt;

&lt;p&gt;Malgré les défis auxquels ils sont confrontés, tels que la sécurité, la scalabilité et l'interopérabilité, des solutions prometteuses et des initiatives émergent continuellement pour offrir des moyens de surmonter ces obstacles et de garantir un avenir stable et sécurisé pour les smart contracts.&lt;/p&gt;

&lt;p&gt;En parallèle, il est important de considérer les implications juridiques et éthiques de cette technologie. Des cadres juridiques clairs, une sensibilisation accrue et un dialogue constructif entre les développeurs, les utilisateurs et les décideurs politiques seront essentiels pour garantir une adoption responsable et bénéfique des smart contracts. Il est crucial de se rappeler que cette technologie est un outil puissant qui peut être utilisé pour le bien ou pour le mal. Il est de notre responsabilité collective de veiller à ce qu'ils soient développés et utilisés de manière responsable, éthique et inclusive, afin qu'ils puissent contribuer à un monde plus juste, transparent et efficient.&lt;/p&gt;

&lt;p&gt;Rendez-vous en 2025 pour faire un nouveau bilan.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>Interacting with Solana in Go: A Beginner's Guide</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Wed, 27 Mar 2024 08:50:14 +0000</pubDate>
      <link>https://forem.com/zenika/interacting-with-solana-in-go-a-beginners-guide-5958</link>
      <guid>https://forem.com/zenika/interacting-with-solana-in-go-a-beginners-guide-5958</guid>
      <description>&lt;p&gt;Solana is a high-performance blockchain platform gaining traction for its scalability and developer experience. This blog post dives into interacting with Solana using Go. We'll explore the basic functionalities like creating a wallet, importing existing one, fetching account balance, and transferring SOL tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  History
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Solana&lt;/strong&gt;, founded in 2020 by &lt;em&gt;Anatoly Yakovenko&lt;/em&gt;, is a high-performance blockchain that has rapidly gained popularity within the blockchain community. Its architecture, &lt;strong&gt;designed to deliver exceptional speed provides scalability and low transaction costs&lt;/strong&gt;. The core innovation lies in the unique &lt;strong&gt;combination of Proof of History and Proof of Stake&lt;/strong&gt;, allowing the network to achieve consensus quickly and efficiently. The ability to handle thousands of transactions per second, coupled with its developer-friendly environment, makes it an attractive choice for those looking to build decentralized applications at scale.&lt;/p&gt;

&lt;p&gt;On the other hand, the selection of a programming language for &lt;strong&gt;DApp development&lt;/strong&gt; necessitates careful consideration of factors such as platform compatibility, developer community engagement, security features, performance, and interoperability. Various languages, including JavaScript, Rust, and Go, can be considered in this context.&lt;/p&gt;

&lt;p&gt;Golang stands out as an optimal programming language for building decentralized applications (DApps) on the Solana blockchain. Go's strong support for concurrency aligns perfectly with Solana's design principles, allowing developers to take full advantage of the Solana’s fast transaction processing and scalability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic understanding of blockchain&lt;/li&gt;
&lt;li&gt;Basic understanding of Golang and a Go development environment&lt;/li&gt;
&lt;li&gt;Familiarity with Solana concepts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Choosing a Golang library for Solana:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As of now there is no official library to support interaction with Solana in Go, but there is popular community librairies such as :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gagliardetto/solana-go&lt;/code&gt; (&lt;a href="https://github.com/gagliardetto/solana-go" rel="noopener noreferrer"&gt;https://github.com/gagliardetto/solana-go&lt;/a&gt;) This library offers a user-friendly API for interacting with Solana's JSON RPC and WebSocket interfaces.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;blocto/solana-go-sdk&lt;/code&gt; (&lt;a href="https://github.com/blocto/solana-go-sdk" rel="noopener noreferrer"&gt;https://github.com/blocto/solana-go-sdk&lt;/a&gt;) This is a comprehensive SDK for Solana development in Golang. It offers a wide range of functionalities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we’ll use the most popular package : &lt;code&gt;gagliardetto/solana-go&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating a wallet
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a new Solana wallet. We'll use the &lt;code&gt;solana.NewRandomPrivateKey&lt;/code&gt; function to generate a new keypair:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gagliardetto/solana-go"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Generate a new random keypair&lt;/span&gt;
    &lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRandomPrivateKey&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Get the public key from the private key&lt;/span&gt;
    &lt;span class="n"&gt;publicKey&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Print the public and private keys (**keep private key secure!**)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Public Key:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Private Key:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Running this code gives the following:&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%2F51p7wifrtqmckyowq6tk.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%2F51p7wifrtqmckyowq6tk.png" alt="Output when running the previous code" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Importing an existing wallet
&lt;/h2&gt;

&lt;p&gt;You might have to create a new wallet, but most of the time you will most likely import an existing one. To use an existing wallet, you'll need its private key in base58 format. &lt;br&gt;
Here's an example using &lt;code&gt;solana.PrivateKeyFromBase58&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gagliardetto/solana-go"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Replace with your actual private key in base58 format&lt;/span&gt;
    &lt;span class="n"&gt;privateKeyString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;".........."&lt;/span&gt;

    &lt;span class="c"&gt;// Parse the private key from base58&lt;/span&gt;
    &lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivateKeyFromBase58&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;privateKeyString&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Get the public key from the private key&lt;/span&gt;
    &lt;span class="n"&gt;publicKey&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Print the public and private keys&lt;/span&gt;
    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Public Key:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;publicKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this code gives the following output:&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%2Fl2hljxpajttss0ergjqj.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%2Fl2hljxpajttss0ergjqj.png" alt="Output when running the previous code" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Request airdrop and fetching wallet balance
&lt;/h2&gt;

&lt;p&gt;For development and testing purposes, you might need test accounts with some SOL tokens to interact with the network. You could use an airdrop to get Solana token on the Devnet and Testnet. This can help you test your application's functionality.&lt;/p&gt;

&lt;p&gt;It can be subject to rate limits when there is a high number of airdrops.&lt;/p&gt;

&lt;p&gt;We can use the &lt;code&gt;GetBalance&lt;/code&gt; method to fetch the balance of an account (wallet):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"math/big"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gagliardetto/solana-go"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gagliardetto/solana-go/rpc"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c"&gt;// Create a new account&lt;/span&gt;
    &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewWallet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"account private key:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivateKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"account public key:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c"&gt;// Create a new RPC client on the DevNet&lt;/span&gt;
    &lt;span class="n"&gt;rpcClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DevNet_RPC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Airdrop 1 SOL to the new account:&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rpcClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestAirdrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="c"&gt;// 1 sol = 1000000000 lamports&lt;/span&gt;
        &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LAMPORTS_PER_SOL&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommitmentFinalized&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"airdrop transaction signature:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Get the balance of the account&lt;/span&gt;
    &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rpcClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommitmentFinalized&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lamportsOnAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetUint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;solBalance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lamportsOnAccount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetUint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LAMPORTS_PER_SOL&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Wallet Balance:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;solBalance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SOL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this code gives the following output:&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%2Fk63czk5yjbsc1t39llun.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%2Fk63czk5yjbsc1t39llun.png" alt="Output when running the previous code" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Transfer Solana to another wallet
&lt;/h2&gt;

&lt;p&gt;Transfers involve creating and sending a transaction. Here's a simple example with the wallet we requested airdrop on just before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gagliardetto/solana-go"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gagliardetto/solana-go/programs/system"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gagliardetto/solana-go/rpc"&lt;/span&gt;
    &lt;span class="n"&gt;confirm&lt;/span&gt; &lt;span class="s"&gt;"github.com/gagliardetto/solana-go/rpc/sendAndConfirmTransaction"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gagliardetto/solana-go/rpc/ws"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gagliardetto/solana-go/text"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create a new RPC client on the DevNet&lt;/span&gt;
    &lt;span class="n"&gt;rpcClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DevNet_RPC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Create a new WS client (used for confirming transactions)&lt;/span&gt;
    &lt;span class="n"&gt;wsClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DevNet_WS&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Load the account that you will send funds FROM&lt;/span&gt;
    &lt;span class="n"&gt;accountFrom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivateKeyFromBase58&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"accountFrom public key:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountFrom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c"&gt;// The public key of the account that you will send sol TO:&lt;/span&gt;
    &lt;span class="n"&gt;accountTo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewWallet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"accountTo public key:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountTo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Get the recent blockhash:&lt;/span&gt;
    &lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rpcClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRecentBlockhash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommitmentFinalized&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Instruction&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewTransferInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="c"&gt;// 1 sol = 1000000000 lamports&lt;/span&gt;
                &lt;span class="m"&gt;1e6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// 0.001 SOL,&lt;/span&gt;
                &lt;span class="n"&gt;accountFrom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;accountTo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&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;Build&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Blockhash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TransactionPayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountFrom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;solana&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivateKey&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;accountFrom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;accountFrom&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unable to sign transaction: %w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Pretty print the transaction:&lt;/span&gt;
    &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewTreeEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Transfer SOL"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c"&gt;// Send transaction, and wait for confirmation:&lt;/span&gt;
    &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;confirm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SendAndConfirmTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;rpcClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;wsClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tx&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Transaction confirmed:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this code gives the following output:&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%2F8dflbyg2mcrnbfiniyxf.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%2F8dflbyg2mcrnbfiniyxf.png" alt="Output when running the previous code" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;In this blog post, we've explored the basics of interacting with Solana using Golang. &lt;/p&gt;

&lt;p&gt;This is just the first step on Solana development with Golang. The chosen library offers a wider range of functionalities beyond what we covered here. Remember, the Solana ecosystem is constantly evolving. Stay updated with the best practices to ensure your dApps remain robust and efficient.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>solana</category>
      <category>go</category>
      <category>web3</category>
    </item>
    <item>
      <title>Developing a NodeJS Wrapper for Snowflake SDK (Pagination included)</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Mon, 05 Jun 2023 14:14:58 +0000</pubDate>
      <link>https://forem.com/zenika/developing-a-nodejs-wrapper-for-snowflake-sdk-pagination-included-mk2</link>
      <guid>https://forem.com/zenika/developing-a-nodejs-wrapper-for-snowflake-sdk-pagination-included-mk2</guid>
      <description>&lt;p&gt;In recent years, Snowflake has gained popularity as a cloud-based data warehousing solution due to its ability to handle large amounts of data. Unlike traditional databases, Snowflake separates storage and compute, allowing users to scale each independently. &lt;/p&gt;

&lt;p&gt;⬇️ In this article, I'll propose a simple wrapper to interact with the Snowflake SDK using NodeJS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before using Snowflake, there are a few prerequisites that you need.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuring Access to the Snowflake API&lt;/strong&gt;: To access Snowflake from NodeJS, you will need to configure access to the Snowflake API. This involves creating an account, generating API keys, and configuring network policies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Installing Dependencies&lt;/strong&gt;: You will need to install the Snowflake NodeJS SDK and any other required dependencies..&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⌨️ &lt;code&gt;npm i snowflake-sdk &amp;amp;&amp;amp; npm i -D @types/snowflake-sdk&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Interact with Snowflake
&lt;/h2&gt;

&lt;p&gt;The Snowflake SDK provides a set of APIs for interacting with Snowflake, including APIs for connecting to Snowflake, executing queries, and performing other database operations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;snowflake-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create a connection to Snowflake&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;your_account_name&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;your_username&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;your_password&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;your_region&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error connecting to Snowflake:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Execute a query&lt;/span&gt;
  &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;sqlText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT * FROM my_table&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error executing query:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Query results:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Destroy connection&lt;/span&gt;
      &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Connection closed.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, we create a connection to Snowflake using the &lt;code&gt;createConnection&lt;/code&gt; method and execute a simple SQL query using the execute method. The results of the query are logged to the console, and the connection is closed using the destroy method.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a wrapper with pagination
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;👉 First, we define an abstract class called SnowflakeServiceAbstract. This class has two main properties: snowflakeEnvironment and snowflakeConfig both contain information about the Snowflake account, such as the account name, username, password, role, warehouse, database, and schema. This information is necessary to establish a connection to the Snowflake account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SnowflakeServiceAbstract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;abstract&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;snowflakeEnvironment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ConnectionOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;snowflakeConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ConfigureOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;insecureConnect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_INSECURECONNECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;ocspFailOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_OCSP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_LOGLEVEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeEnvironment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;authenticator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_ACCOUNT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_ROLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;warehouse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_WAREHOUSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_DATABASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Managing Snowflake connection
&lt;/h3&gt;

&lt;p&gt;👉 Then, we'll add 3 methods to manage our Snowflake connection.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;first method&lt;/strong&gt;, &lt;code&gt;connectSnowflake&lt;/code&gt;, establishes a connection to the Snowflake account using the configuration options and environment variables that were set in the constructor. This method returns a promise that resolves to the connection object if successful, or rejects with an error if unsuccessful.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;second method&lt;/strong&gt;, &lt;code&gt;disconnectSnowflake&lt;/code&gt;, disconnects from Snowflake. It provides a way to cleanly disconnect from a Snowflake database connection that was established.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;third method&lt;/strong&gt;, &lt;code&gt;cancelStatementSnowflake&lt;/code&gt;, cancels a Snowflake statement. It is useful when you want to cancel a query or operation taking too long to execute or because it is blocking other queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SnowflakeServiceAbstract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;abstract&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;snowflakeEnvironment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ConnectionOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;snowflakeConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ConfigureOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;insecureConnect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_INSECURECONNECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;ocspFailOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_OCSP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_LOGLEVEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeEnvironment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;authenticator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_ACCOUNT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_ROLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;warehouse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_WAREHOUSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_DATABASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;connectSnowflake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeEnvironment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SnowflakeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Connected Snowflake Id: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                                &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                            &lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;disconnectSnowflake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SnowflakeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;_conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unable to disconnect Snowflake: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Disconnected Snowflake Id: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;cancelStatementSnowflake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Statement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SnowflakeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;_stmt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Statement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error while cancel statement &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Successfully aborted statement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Executing queries
&lt;/h3&gt;

&lt;p&gt;👉 Finally, we add a &lt;strong&gt;final method&lt;/strong&gt; which will be called when we want to execute a query and get the result. It takes in a SnowflakeQueryInterface object as an argument which contains the query to execute, any query parameters (binds), and pagination information.&lt;/p&gt;

&lt;p&gt;The SnowflakeResultInterface type defines the structure of the result returned by the query.&lt;/p&gt;

&lt;p&gt;The method first connects to the Snowflake database using the &lt;code&gt;connectSnowflake&lt;/code&gt; method then executes the query passing in the SQL text, bind parameters, and other options like streaming results. The complete callback function is invoked when the query execution is complete.&lt;/p&gt;

&lt;p&gt;It performs pagination on the result set, based on the startIndex and count properties. If startIndex is not provided, it defaults to 0. If count is not provided, it returns the first 1000 rows.&lt;/p&gt;

&lt;p&gt;The error event is triggered if there is any error while consuming the rows. In that case, the method logs an error message, cancels the statement, disconnects and rejects with the error.&lt;/p&gt;

&lt;p&gt;The end event is triggered when all the rows have been consumed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final class and interfaces
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SnowflakeQueryInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;binds&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Binds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SnowflakeResultInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;snowflake-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SnowflakeServiceAbstract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;abstract&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;snowflakeEnvironment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ConnectionOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;snowflakeConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ConfigureOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kr"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;insecureConnect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_INSECURECONNECT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;ocspFailOpen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_OCSP&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_LOGLEVEL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeEnvironment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;authenticator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_ACCOUNT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_ROLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;warehouse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_WAREHOUSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_DATABASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SNOWFLAKE_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;connectSnowflake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snowflakeEnvironment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SnowflakeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Connected Snowflake Id: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;disconnectSnowflake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SnowflakeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;_conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unable to disconnect Snowflake: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s2"&gt;`Disconnected Snowflake Id: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;cancelStatementSnowflake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Statement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SnowflakeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;_stmt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Statement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error while cancel statement &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Successfully aborted statement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;executeQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SnowflakeQueryInterface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SnowflakeResultInterface&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connectSnowflake&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="cm"&gt;/* PAGINATION */&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startIndex&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startIndex&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;endIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;startIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;startIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;sqlText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;binds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;binds&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;binds&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
          &lt;span class="na"&gt;streamResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="na"&gt;completeErr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SnowflakeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Statement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;_rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&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="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;completeErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;completeErr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;completeErr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;rowsArr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Query id: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStatementId&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;streamRows&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
              &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;endIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

            &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;streamErr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unable to consume all rows&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

              &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancelStatementSnowflake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnectSnowflake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

              &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;streamErr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

            &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;row&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;rowsArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

            &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;All rows consumed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
              &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getNumRows&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="na"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rowsArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;endIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getNumRows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rowsArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="p"&gt;});&lt;/span&gt;

              &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnectSnowflake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope this article has been helpful to you. If you have any questions or suggestions, please feel free to contact me. Thank you for reading!👋&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Configuring HTTP Basic Auth on an AWS Elastic Beanstalk application</title>
      <dc:creator>Benjamin Bourgeois</dc:creator>
      <pubDate>Thu, 07 Apr 2022 17:53:05 +0000</pubDate>
      <link>https://forem.com/bengeois/configuring-http-basic-auth-on-an-aws-elastic-beanstalk-application-4m89</link>
      <guid>https://forem.com/bengeois/configuring-http-basic-auth-on-an-aws-elastic-beanstalk-application-4m89</guid>
      <description>&lt;p&gt;Elastic Beanstalk is a platform within Amazon Web Service that is used for deploying and scaling web applications. It lets developers uploading their application to the AWS cloud, via AWS CodePipeline to named one, and then you can forget about the deployment. &lt;/p&gt;

&lt;p&gt;And it seems like AWS has changed some stuff in newer versions of Elastic Beanstalk that uses Amazon Linux 2. And so most of the configuration you can find on internet are no longer working.&lt;/p&gt;

&lt;p&gt;The following steps describe the newer approach to deploy an app with HTTP Basic Auth.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Create the .htpasswd
&lt;/h2&gt;

&lt;p&gt;.htpasswd is used to store usernames and password for basic authentication of HTTP users. Elastic Beanstalk defines a large number of configuration options that you can use to configure your environment's behavior and the resources that it contains. We will use one of theses :)&lt;/p&gt;

&lt;p&gt;Create, at the root of your application bundle, a folder named &lt;code&gt;.ebextensions&lt;/code&gt; and add a file named &lt;code&gt;00-http_basic_auth.config&lt;/code&gt; with the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;files:
  /etc/nginx/.htpasswd:
    mode: "000755"
    owner: root
    group: root
    content: |
      user:password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🚨 Replace user and password with your combination. You can easily find on internet how to generate a password for this file :)&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Overriding the default location
&lt;/h2&gt;

&lt;p&gt;Next, we need to overwrite the default nginx location conf provided by Beanstalk.&lt;/p&gt;

&lt;p&gt;To do so, create a file in the bundle of your application at the location .platform/nginx/conf.d/elasticbeanstalk/00_application.conf. &lt;/p&gt;

&lt;p&gt;Then, add this code. This is the default nginx location conf to which I added the last two lines.&lt;/p&gt;

&lt;p&gt;ℹ️ &lt;em&gt;Don't forget to change the port number depends on your application&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;location / {
    proxy_pass          http://127.0.0.1:8080;
    proxy_http_version  1.1;

    proxy_set_header    Connection          $connection_upgrade;
    proxy_set_header    Upgrade             $http_upgrade;
    proxy_set_header    Host                $host;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;

    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Make HTTP basic auth works with health check
&lt;/h2&gt;

&lt;p&gt;The configuration is ready so far and if you try to deploy your app, the HTTP Basic Auth will work but Beanstalk will indicate that your app is unhealthy because the health check now need to authenticate itself. To avoid this, we can make one path publicly available.&lt;/p&gt;

&lt;p&gt;Add to your previously created file &lt;code&gt;.platform/nginx/conf.d/elasticbeanstalk/00_application.conf&lt;/code&gt; the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;location /elb-status {
    proxy_pass          http://127.0.0.1:8080/status;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ℹ️ Make also this path works on your app but without any sensitive information, just a health check.&lt;/p&gt;

&lt;p&gt;Finally, we just need to change the default health check path of the Beanstalk instance.&lt;br&gt;
Go on your Beanstalk instance in your AWS Console and then click on "Configuration" and "Edit" in the Load Balancer section.&lt;br&gt;
Modify the default process with this health check path : &lt;code&gt;/elb-status&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%2Fk7rzi88v29nc5kf4ceyd.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%2Fk7rzi88v29nc5kf4ceyd.png" alt="Beanstalk health check configuration" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save and apply changes&lt;/p&gt;




&lt;p&gt;I hope it helped you and enjoy your HTTP Basic Auth :)) &lt;/p&gt;

</description>
      <category>aws</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
