<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Christopher Poulsen</title>
    <description>The latest articles on DEV Community by Christopher Poulsen (@cjpoulsen).</description>
    <link>https://dev.to/cjpoulsen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2955781%2F062ec7f4-65b5-44bc-b74e-b5b30ed79b38.jpeg</url>
      <title>DEV Community: Christopher Poulsen</title>
      <link>https://dev.to/cjpoulsen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cjpoulsen"/>
    <language>en</language>
    <item>
      <title>Earn and spend USDC on inference</title>
      <dc:creator>Christopher Poulsen</dc:creator>
      <pubDate>Wed, 21 Oct 2026 02:33:46 +0000</pubDate>
      <link>https://dev.to/cjpoulsen/earn-and-spend-usdc-on-inference-39d7</link>
      <guid>https://dev.to/cjpoulsen/earn-and-spend-usdc-on-inference-39d7</guid>
      <description>&lt;p&gt;If your app or harness talks to three model providers, you have three accounts, three API keys, three billing dashboards, and three sets of rate limits to babysit. If you want to offer a model, you need your own signup flow, key issuance and billing before anyone can pay you.&lt;/p&gt;

&lt;p&gt;We've been building Stellarium, a decentralized network where anyone can host an API and get paid for every call. This post is about the newest piece: running AI inference on it. Models become ordinary resources on the network, callers pay per token in USDC, and nobody needs to set up an account. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A model is just a resource&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On Stellarium, every API is a resource hosted by a node. A resource has a name, like &lt;code&gt;com.example.Weather&lt;/code&gt;, and a list of functions programs can call. Nodes advertise their resources to peers, and any node can route a call to whoever hosts the resource.&lt;/p&gt;

&lt;p&gt;An AI model fits the same shape. A provider wraps the model in a resource with a function that takes a prompt and returns text. For example, &lt;code&gt;sh.stellarium.inference.claude.Sonnet&lt;/code&gt; exposes Claude Sonnet through a message function.&lt;/p&gt;

&lt;p&gt;That means AI gets everything the network already does: discovery by name, routing between peers, results that carry either a value or an error, and payment with no signup or keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calling a model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Requests on Stellarium are written in RequestScript. Calling a model looks like calling a function. The only difference is &lt;code&gt;maxTokens&lt;/code&gt; is a required parameter. This allows the caller and provider to work out a fair price.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;request AskClaude {
  const sonnet: sh.stellarium.inference.claude.Sonnet

  const reply = sonnet.message(prompt: "Write a haiku about Oslo", maxTokens: 200)
  if (reply.error != null) {
    return reply.error.message
  }

  return reply.value
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The node does the rest: it finds the node hosting the model, gets a price estimate, checks it against your spending limit, and pays for the call. If the model fails, your script gets an error it can handle rather than a dead request.&lt;br&gt;
Since a model is just another resource, one request can mix a model call with anything else on the network (a weather lookup, a Regex validation) and combine the results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hard part: paying per token, fairly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most paid functions on Stellarium charge a flat fee per call. That doesn't work for inference, because cost depends on input and output tokens. There's a trust problem in both directions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The caller can't know the output length ahead of time, and doesn't want to sign a blank check.&lt;/li&gt;
&lt;li&gt;The provider doesn't want to burn GPU time (or its own API credits) on a call that won't be paid.&lt;/li&gt;
&lt;li&gt;Nobody should have to trust the provider to report whatever token count it likes.
AI-based functions need a new function type: inference functions. Inference functions are priced at a rate per million input tokens and a rate per million output tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every paid call goes through six steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Estimate. The caller's node asks the provider for an estimate. The provider counts the input tokens and returns maxAmount: the cost of those input tokens plus maxTokens of output.&lt;/li&gt;
&lt;li&gt;Check. The caller recomputes maxAmount from the advertised rates and refuses the call if it's over its configured limit.&lt;/li&gt;
&lt;li&gt;Sign. The caller signs an inference voucher carrying maxAmount, both rates and maxTokens, and sends it with the call.&lt;/li&gt;
&lt;li&gt;Verify. The provider checks that the voucher's rates and maxTokens match, re-runs its estimate, and answers 402 if the voucher doesn't cover it. Inference never runs unpaid.&lt;/li&gt;
&lt;li&gt;Report. After the call, the provider sends the voucher and actual token counts to the operator. Output is capped at maxTokens.&lt;/li&gt;
&lt;li&gt;Settle. The operator verifies the signature and charges actual usage at the signed rates, never more than maxAmount, settling on Solana through an escrow.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The caller agrees to a ceiling up front and pays only for what was used. The provider knows the call is covered before spending anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters for agents&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agents have a great use-case for Stellarium. An agent that wants a second model, a cheaper model for a subtask, or a specialized model someone else fine-tuned shouldn't need a human to sign up, paste an API key and attach a card. On Stellarium it calls the resource by name, its node enforces a hard spending ceiling per call, and the payment is settled automatically. All through USDC on Solana. &lt;/p&gt;

&lt;p&gt;Try it&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the AI overview and the inference functions guide:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stellarium.sh/ai" rel="noopener noreferrer"&gt;https://stellarium.sh/ai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stellarium.sh/ai/inference-functions" rel="noopener noreferrer"&gt;https://stellarium.sh/ai/inference-functions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Browse models and their rates on the registry: &lt;a href="https://stellariumregistry.xyz/" rel="noopener noreferrer"&gt;https://stellariumregistry.xyz/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run a node and host your own model&lt;/li&gt;
&lt;li&gt;Star or contribute on GitHub&lt;/li&gt;
&lt;li&gt;Come say hi on Discord. If you host a model, we'd love to hear about it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Payments on Stellarium go live this Thursday, October 22nd, 2026. Stellarium is open source and early. Questions, comments and pull requests are all welcome.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stellarium.sh" rel="noopener noreferrer"&gt;https://stellarium.sh&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>web3</category>
    </item>
    <item>
      <title>RequestScript &amp; Stellarium - A new way to build web APIs</title>
      <dc:creator>Christopher Poulsen</dc:creator>
      <pubDate>Mon, 05 Oct 2026 02:06:44 +0000</pubDate>
      <link>https://dev.to/cjpoulsen/requestscript-stellarium-a-new-way-to-build-web-apis-3n4l</link>
      <guid>https://dev.to/cjpoulsen/requestscript-stellarium-a-new-way-to-build-web-apis-3n4l</guid>
      <description>&lt;p&gt;Hey everyone! I'm introducing two new projects I have been developing the past few years that I think are now ready for primetime and more contributors.&lt;/p&gt;

&lt;p&gt;TLDR: &lt;strong&gt;RequestScript&lt;/strong&gt; is a new programming language that is declared in the request body to an HTTP server. &lt;strong&gt;Stellarium&lt;/strong&gt; is a decentralized API platform that runs RequestScript and handles API monetization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is RequestScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RequestScript is a programming language that is declared in the request body to a server. It is influenced by Kotlin and Typescript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// sent to http://localhost:3000/run
request MyRequest {
    const a = 2
    const b = 3
    const c = a + b

    return "Hello World!"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can define Resources in the host language and reference them in RequestScript.&lt;/p&gt;

&lt;p&gt;In Typescript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Resource&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;requestscript-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addResource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;                       &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path.to&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AddResource&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;int32&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;second&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;int32&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;returnType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;int32&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="c1"&gt;// any RequestScript type string, or 'void'&lt;/span&gt;
          &lt;span class="na"&gt;exec&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;args&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;second&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&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;first&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;second&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 RequestScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;request MyRequest {
        const math: path.to.AddResource
        return math.add(first: 2, second: 3)
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also define reusable requests called &lt;code&gt;Contracts&lt;/code&gt; that are saved to the server and can be executed on demand.&lt;/p&gt;

&lt;p&gt;In RequestScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract path.to.MyContract@1.2.3(name: string) {
        return "Hello ${name}"
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stellarium is where things get really interesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Stellarium?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stellarium is a decentralized API platform that allows anyone to execute RequestScript and call server resources and contracts across a network. You can effectively call resources and combine their output across nodes hosted in different languages. It's really simple to create Resources and share them. Hate dealing with HTTP status codes, retry logic, etc.? Craft your APIs in RequestScript Resources instead. Have a favorite library in Go you wish you could call in Java? Export it as a Resource in the Go node, and call it on the Java node in a typed way using RequestScript. The goal is for a global, decentralized API network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monetization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stellarium also makes API monetization easy, as the individual RequestScript tokens you use can be totaled up and sent to its controlling node for payment. Only pay for the exact if statement you execute, or resource function you call. &lt;/p&gt;

&lt;p&gt;If you're interested in contributing or learning more, here are the repos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/qualletio/requestscript-js" rel="noopener noreferrer"&gt;RequestScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/qualletio/stellarium-ts" rel="noopener noreferrer"&gt;Stellarium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All experience levels welcome! This could be an especially helpful project for anyone wanting practice in writing spike docs and RFCs. Everything is just getting off the ground and is very much a work in progress. More documentation coming soon!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>api</category>
      <category>showdev</category>
      <category>web3</category>
    </item>
    <item>
      <title>Guide: Running an Avisen node</title>
      <dc:creator>Christopher Poulsen</dc:creator>
      <pubDate>Wed, 19 Mar 2025 21:37:11 +0000</pubDate>
      <link>https://dev.to/cjpoulsen/running-an-avisen-node-14bn</link>
      <guid>https://dev.to/cjpoulsen/running-an-avisen-node-14bn</guid>
      <description>&lt;p&gt;The official Avisen client is deployed to &lt;a href="https://hub.docker.com/repository/docker/avisen/client-kt/general" rel="noopener noreferrer"&gt;https://hub.docker.com/repository/docker/avisen/client-kt/general&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For starting out, we recommend connecting with an official test network or starting your own. See &lt;a href="https://www.avisen.org/use#boot-nodes" rel="noopener noreferrer"&gt;boot nodes&lt;/a&gt; for official boot node addresses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the first time
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Docker Compose
&lt;/h3&gt;

&lt;p&gt;We recommend running a node using Docker Compose. This will help automate the start-up of the database and node and make it easier to set the client’s many environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose a node type
&lt;/h2&gt;

&lt;p&gt;An Avisen node can start in many different nodes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UTILITY&lt;/strong&gt;: a node that is running without a blockchain, network, or database. Useful for generating key-pairs and working with Avisen's local utilities. Most REST API endpoints are disabled in this mode, but you still get access to the crypto utilities. A database is not used in this mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REPLICA&lt;/strong&gt;: a node that is a full replica of the network and blockchain. Receives updates from publisher nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PUBLISHER&lt;/strong&gt;: a node that has the ability to publish transactions (articles), mint blocks, and broadcast new blocks to the network. Requires ECDSA signing keys and permission from the blockchain to publish.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose run behavior
&lt;/h3&gt;

&lt;p&gt;An avisen node can start up its own blockchain or join an existing network. This is handled by the optional BOOT_NODE environment variable. If it is set, the node will attempt to join the boot node’s network and download its blockchain. If it is not set, the node will start its own blockchain with a Genesis block.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prepare the database
&lt;/h3&gt;

&lt;p&gt;Running a non-utility node requires a running PostgreSQL database at version 17 or higher.&lt;/p&gt;

&lt;p&gt;The chosen database user must have permissions to create tables, insert data, and select data in the default schema. This can be done by connecting directly to the database and running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRANT ALL PRIVILEGES ON DATABASE YOUR_DATABASE TO YOUR_USERNAME;

GRANT ALL ON SCHEMA public TO YOUR_USERNAME;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fulfill environment variables
&lt;/h3&gt;

&lt;p&gt;The client requires many environment variables. It is important to take note of which ones are required for the mode you are running your node in.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DB_URL&lt;/code&gt;: the url corresponding to the backing PostgreSQL database. There should only be one database per node. Not required in &lt;code&gt;UTILITY&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DB_USER&lt;/code&gt;: the username when connecting to the database. This should not be the admin user. Not required in &lt;code&gt;UTILITY&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DB_PASS&lt;/code&gt;: the password for the database user. Not required in &lt;code&gt;UTILITY&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NODE_ADDRESS&lt;/code&gt;: the url address (host, port, etc.) for accessing the node. Broadcast to the other nodes in the network. Required. This should be a static IP address or url.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BOOT_NODE&lt;/code&gt;: the url address (host, port, etc.) for accessing another node to populate the blockchain and network pool. If not populated, the node will run in genesis mode. (See Network/Starting up for the first time) Not required in &lt;code&gt;UTILITY&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NODE_MODE&lt;/code&gt;: the mode to run the node in:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PUBLISHER&lt;/code&gt;: a node that has the ability to publish transactions (articles), mint blocks, and broadcast new blocks to the network.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;REPLICA&lt;/code&gt;: a node that is a full replica of the network and blockchain. Receives updates from publisher nodes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;UTILITY&lt;/code&gt;: a node that is running without a blockchain, network, or database. Useful for generating key-pairs and working with Avisen's local utilities. Most REST API endpoints are disabled in this mode. Database connection information is not required in this mode.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NETWORK_ID&lt;/code&gt;: a shared id that prevents cross-network activity. Not required in UTILITY mode.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PORT&lt;/code&gt;: the given port for the app to run on. Defaults to 8081 if not provided. When running in Docker, the port must be set to 8081.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PUBLISHER_SIGNING_KEY&lt;/code&gt;: A private ECDSA key used for signing blocks. Required if running a node in &lt;code&gt;PUBLISHER&lt;/code&gt; mode. Not required in &lt;code&gt;UTILITY&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PUBLISHER_PUBLIC_KEY&lt;/code&gt;: A public ECDSA key used as property of a block. Required if running a node in PUBLISHER mode. Not required in &lt;code&gt;UTILITY&lt;/code&gt; mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start the app!
&lt;/h3&gt;

&lt;p&gt;Start the node using your preferred Docker method. Check the logs for errors and success. If you are having trouble starting a node, head over to our official Discord server for help.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connect to the node
&lt;/h3&gt;

&lt;p&gt;See &lt;a href="https://www.avisen.org/instructions/connecting" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; for more information on how to connect to a node. Log issues to our &lt;a href="https://github.com/avisenorg/avisen-kt" rel="noopener noreferrer"&gt;github page&lt;/a&gt; or our &lt;a href="https://discord.gg/yrjU35cPyu" rel="noopener noreferrer"&gt;discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>docker</category>
    </item>
    <item>
      <title>Call for Contributors</title>
      <dc:creator>Christopher Poulsen</dc:creator>
      <pubDate>Wed, 19 Mar 2025 00:04:58 +0000</pubDate>
      <link>https://dev.to/cjpoulsen/call-for-contributors-3f7e</link>
      <guid>https://dev.to/cjpoulsen/call-for-contributors-3f7e</guid>
      <description>&lt;p&gt;Hey everyone! I’m looking for more contributors for my open source project: Avisen. If you’re interested in Kotlin, Go, decentralized networks, blockchain, or supporting independent journalism, check out our &lt;a href="https://avisen.org" rel="noopener noreferrer"&gt;website&lt;/a&gt; or join our &lt;a href="https://discord.gg/36tRJQv7" rel="noopener noreferrer"&gt;discord&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>blockchain</category>
      <category>opensource</category>
      <category>go</category>
    </item>
  </channel>
</rss>
