<?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: Igor</title>
    <description>The latest articles on DEV Community by Igor (@tigusigalpa).</description>
    <link>https://dev.to/tigusigalpa</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%2F1475742%2Fbaa73c6e-cca1-4aef-bf6a-e4c1f0ed9d5d.png</url>
      <title>DEV Community: Igor</title>
      <link>https://dev.to/tigusigalpa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tigusigalpa"/>
    <language>en</language>
    <item>
      <title>Building Reliable Crypto Alerting Systems in Go: A Deep Dive into the whale-alert-go SDK</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Sat, 25 Jul 2026 07:39:30 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/building-reliable-crypto-alerting-systems-in-go-a-deep-dive-into-the-whale-alert-go-sdk-454</link>
      <guid>https://dev.to/tigusigalpa/building-reliable-crypto-alerting-systems-in-go-a-deep-dive-into-the-whale-alert-go-sdk-454</guid>
      <description>&lt;p&gt;Tracking large cryptocurrency transactions—commonly known as "whales"—has become a crucial tool for traders, analysts, and blockchain researchers. The Whale Alert Enterprise API is one of the leading data providers in this space, offering both historical data and real-time alerts. However, integrating third-party APIs into Go applications often requires writing a significant amount of boilerplate code. Developers must manually implement robust HTTP clients, manage the lifecycle of WebSocket connections, carefully handle pagination, and resolve floating-point precision issues when dealing with financial data.&lt;/p&gt;

&lt;p&gt;To address these challenges, the &lt;code&gt;whale-alert-go&lt;/code&gt; SDK was created &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;. This unofficial Go library is designed specifically for interacting with the Whale Alert Enterprise API. It abstracts away the routine networking tasks, allowing engineers to focus entirely on the business logic of their applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Philosophy: Idiomatic Go
&lt;/h2&gt;

&lt;p&gt;When designing &lt;code&gt;whale-alert-go&lt;/code&gt;, the primary focus was on adhering to the standards and best practices of the Go programming language. Every method that performs a network request accepts a &lt;code&gt;context.Context&lt;/code&gt; &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;. This ensures proper timeout management and the ability to cancel long-running operations, which is critical for high-load microservices. Furthermore, the client is designed to be entirely concurrency-safe, meaning it can be shared across multiple goroutines without the need for additional mutexes &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the most common pitfalls when working with cryptocurrency APIs is using the &lt;code&gt;float64&lt;/code&gt; type to represent monetary amounts. Due to the nature of floating-point arithmetic, this inevitably leads to a loss of precision when dealing with very small values (such as satoshi fees) or extremely large numbers. In &lt;code&gt;whale-alert-go&lt;/code&gt;, this problem is solved radically: all monetary values and fees are preserved as strings &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;. Developers can pass these strings directly into specialized decimal arithmetic packages, such as &lt;code&gt;shopspring/decimal&lt;/code&gt;, completely eliminating the risk of data distortion.&lt;/p&gt;

&lt;h2&gt;
  
  
  REST API: Clean and Resilient
&lt;/h2&gt;

&lt;p&gt;Working with REST APIs often involves network failures, rate limits, and temporary server errors. The SDK provides a powerful retry mechanism that can be configured during client initialization using functional options.&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="c"&gt;// Create a client with retries enabled: up to 3 attempts, starting at&lt;/span&gt;
&lt;span class="c"&gt;// 500ms and capped at 10s. Retries only apply to idempotent GET requests.&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;whalealert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;whalealert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="o"&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;Millisecond&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&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="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 retry policy is implemented with safety as the top priority. Only idempotent GET requests are retried, eliminating the risk of duplicating transactions or unintentionally altering state &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;. The client automatically responds to HTTP status 429 (Too Many Requests) and 5xx series errors. It uses an exponential backoff strategy with added jitter (random deviation) to prevent the "thundering herd" effect, and it also respects the &lt;code&gt;Retry-After&lt;/code&gt; header if provided by the server &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebSocket Alerts: Built to Survive
&lt;/h2&gt;

&lt;p&gt;For real-time data delivery, Whale Alert provides a WebSocket API. Maintaining long-lived connections is a complex task because networks are inherently unstable and servers may forcefully drop sessions. The &lt;code&gt;websocket&lt;/code&gt; package included in the SDK offers an elegant solution with automatic reconnection capabilities &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&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="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wsURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Reconnect&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReconnectConfig&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MaxAttempts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;InitialDelay&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&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="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;MaxDelay&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="o"&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="p"&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnMessage&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;msg&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&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;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EventType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EventTypeAlert&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alert&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="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[ALERT] %s: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Blockchain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A developer simply needs to define the reconnection parameters and register handlers for messages and errors. The client independently manages the read loop, decodes incoming events into strongly typed structs, and handles ping/pong control messages to keep the connection alive &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safe Pagination and Error Handling
&lt;/h2&gt;

&lt;p&gt;Endpoints that return lists, such as transaction histories, require pagination. &lt;code&gt;whale-alert-go&lt;/code&gt; offers two approaches. The first is a lazy &lt;code&gt;TransactionIterator&lt;/code&gt; that hides the logic of fetching subsequent pages under the hood &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;. The second approach allows developers to manually manage navigation using the &lt;code&gt;Next URL&lt;/code&gt; links.&lt;/p&gt;

&lt;p&gt;A notable security feature of the SDK is its validation of URLs for subsequent pages. The library verifies that the &lt;code&gt;Next URL&lt;/code&gt; shares the same origin as the client's base URL, preventing potential redirection attacks to malicious servers &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Error handling is also executed in the best traditions of Go 1.13+. The API returns a typed &lt;code&gt;APIError&lt;/code&gt; containing the HTTP status and the message from the server. In addition, sentinel errors such as &lt;code&gt;ErrUnauthorized&lt;/code&gt; or &lt;code&gt;ErrRateLimited&lt;/code&gt; are provided, which can be easily checked using &lt;code&gt;errors.Is&lt;/code&gt; and &lt;code&gt;errors.As&lt;/code&gt; &lt;a href="https://github.com/tigusigalpa/whale-alert-go" rel="noopener noreferrer"&gt;1&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Integrating with financial and cryptocurrency APIs demands a high degree of reliability. The &lt;code&gt;whale-alert-go&lt;/code&gt; library provides developers with a ready-to-use, carefully designed toolkit that resolves issues related to network instability, data precision loss, and connection management. Thanks to strongly typed models and an idiomatic approach, writing code becomes faster and safer.&lt;/p&gt;

&lt;p&gt;You can install the library using the standard Go command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/tigusigalpa/whale-alert-go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note that this is an unofficial SDK, and you will need a valid Whale Alert Enterprise API key to access authenticated endpoints. Check out the source code, examples, and full documentation in the project's GitHub repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

</description>
      <category>go</category>
      <category>whalealert</category>
      <category>cryptocurrency</category>
      <category>bitcoin</category>
    </item>
    <item>
      <title>Track Blockchain Whale Activity in PHP with whale-alert-php</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Thu, 23 Jul 2026 06:10:20 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/track-blockchain-whale-activity-in-php-with-whale-alert-php-3501</link>
      <guid>https://dev.to/tigusigalpa/track-blockchain-whale-activity-in-php-with-whale-alert-php-3501</guid>
      <description>&lt;p&gt;Large on-chain transfers are valuable events for monitoring, analytics, and alerting workflows. A product may need to retrieve a historical transaction, inspect the synchronization status of a blockchain, or notify a team the moment a high-value transfer appears. In PHP, those needs can quickly turn into repetitive work: composing requests, parsing responses, treating money safely, retrying temporary failures, and maintaining a live WebSocket connection.&lt;/p&gt;

&lt;p&gt;That is the problem &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;&lt;strong&gt;whale-alert-php&lt;/strong&gt;&lt;/a&gt; is designed to solve. It is an unofficial, MIT-licensed PHP client for the Whale Alert Enterprise API, with coverage for documented REST endpoints and real-time WebSocket alerts. Rather than exposing a loose collection of arrays and request helpers, the library presents a typed, immutable, and framework-friendly interface for PHP applications. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; &lt;code&gt;whale-alert-php&lt;/code&gt; is an independent, unofficial SDK. It is not affiliated with, endorsed by, or sponsored by Whale Alert. A valid API key is required for authenticated API operations. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why a dedicated PHP SDK matters
&lt;/h2&gt;

&lt;p&gt;Integrating an external blockchain-data API is not difficult in the narrowest sense: an HTTP request can return JSON in a few lines. The engineering work begins after that request. Production code must decide how to represent token quantities, distinguish a missing API key from a rate-limit response, follow a paginated result safely, and recover from a short-lived network or provider failure.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;whale-alert-php&lt;/code&gt; packages those concerns into a focused client. Monetary values and fees are deliberately returned as strings rather than PHP floats, protecting applications from silent precision loss. API responses are mapped to immutable DTOs, while failures are exposed through typed exceptions. The client can use any PSR-18 compatible HTTP implementation, and Laravel applications can opt into a service provider, configuration publishing, a facade, and dependency injection. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;What the SDK provides&lt;/th&gt;
&lt;th&gt;Practical benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;REST API access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Methods for supported blockchains, blockchain status, transactions, blocks, and address transactions. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Build historical views and data-enrichment workflows without hand-writing endpoint wrappers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Real-time WebSocket events&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Alert and social-event streaming, subscriptions, decoded messages, ping/pong keep-alives, and optional reconnection. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;React to relevant on-chain activity as it arrives.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typed, immutable DTOs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Structured response objects instead of ad hoc response arrays. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Improve autocomplete, readability, and confidence when integrating the API.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Precision-aware amounts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fees and monetary fields remain strings. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Avoid float-rounding surprises in financial or analytical code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resilience controls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Configurable exponential-backoff retries for idempotent GET requests on HTTP 429 and 5xx responses. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Make short-lived API or network failures less disruptive.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Laravel integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optional service provider, facade, configuration publishing, and singleton client binding. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Add the SDK naturally to Laravel projects without sacrificing dependency injection.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Install it with Composer
&lt;/h2&gt;

&lt;p&gt;The fastest path is a standard Composer install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require tigusigalpa/whale-alert-php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The package uses Guzzle by default, but its PSR-18 design lets an application substitute another compatible HTTP client when needed. That is useful for teams with an existing HTTP stack or a deliberate preference for a different client implementation. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the REST API
&lt;/h2&gt;

&lt;p&gt;The following example creates a client, lists the blockchains supported by the public status endpoint, fetches Ethereum synchronization status, and retrieves a page of transactions. The code follows the library's documented API surface. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\Config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\WhaleAlertClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WHALE_ALERT_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;maxRetries&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WhaleAlertClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Public endpoint: an API key is not required here.&lt;/span&gt;
&lt;span class="nv"&gt;$chains&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSupportedBlockchains&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$chains&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$chain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$chain&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;': '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;', '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$chain&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSymbols&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&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="c1"&gt;// Authenticated endpoint: supply a valid API key.&lt;/span&gt;
&lt;span class="nv"&gt;$status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getBlockchainStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ethereum'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ethereum: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getStartHeight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getEndHeight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;listTransactions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ethereum'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'start_height'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getStartHeight&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="s1"&gt;'limit'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTransactions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$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;echo&lt;/span&gt; &lt;span class="s2"&gt;"Transaction &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$tx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Fee: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$tx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getFee&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$tx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getFeeSymbol&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key detail is not merely that the calls are concise. The return values are DTOs, so readers of the code can see that a transaction hash and fee are part of an explicit API contract. Since fee values are strings, the application can display them as received or use a decimal-math library for precise calculations rather than implicitly converting them to floats. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Make pagination a safe default
&lt;/h2&gt;

&lt;p&gt;Pagination is often treated as a trivial concern until it becomes a security or reliability issue. List calls return a &lt;code&gt;TransactionPage&lt;/code&gt; that contains the current transactions and an optional next URL. When the next page exists, the client can follow it with &lt;code&gt;listTransactionsNext()&lt;/code&gt;. The SDK validates next URLs against the configured base origin, which avoids accidentally following an arbitrary URL returned in a response. Equivalent helpers are available for address-transaction pagination. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$nextPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;listTransactionsNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getNext&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$nextPage&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTransactions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$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;echo&lt;/span&gt; &lt;span class="nv"&gt;$tx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For applications that process large transaction sets, this small design choice keeps the calling code readable while retaining an important validation boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stream real-time alerts with WebSockets
&lt;/h2&gt;

&lt;p&gt;Polling has its place, but a real-time alerting product should not have to wait for the next scheduled request. &lt;code&gt;whale-alert-php&lt;/code&gt; includes a WebSocket client that lets an application connect, subscribe to alerts, register handlers, and enter a read loop. Automatic reconnection is opt-in: configure &lt;code&gt;maxReconnects&lt;/code&gt; with a value greater than zero when that behavior is appropriate for the application. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a compact example that listens for Ethereum alerts with a minimum USD value of 500,000:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\WebSocket\AlertSubscription&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\WebSocket\Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\WebSocket\EventType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WHALE_ALERT_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$wsUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'wss://leviathan.whale-alert.io/ws?api_key=%s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$wsUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxReconnects&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&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="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nc"&gt;Alert&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;alert&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Blockchain: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'blockchain'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Alert: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&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="p"&gt;});&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\Throwable&lt;/span&gt; &lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Connection issue: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&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="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;subscribeAlerts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AlertSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'eth-whale-watch'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;blockchains&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ethereum'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;minValueUsd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a useful foundation for an internal operations feed, a Discord or Telegram notification bridge, a data-ingestion worker, or a real-time dashboard. The SDK takes responsibility for the WebSocket protocol mechanics—connection, subscription management, message decoding, keep-alives, and optional reconnection—so the application can focus on what should happen after an alert is received. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Handle failures intentionally
&lt;/h2&gt;

&lt;p&gt;A reliable integration should make it easy to tell a configuration mistake from a temporary upstream problem. The SDK maps API failures to named exception types, including &lt;code&gt;UnauthorizedException&lt;/code&gt; for an invalid or missing credential, &lt;code&gt;RateLimitException&lt;/code&gt; for HTTP 429 responses, &lt;code&gt;NotFoundException&lt;/code&gt;, validation errors, and server-side errors. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\Exceptions\ApiException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\Exceptions\RateLimitException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\Exceptions\UnauthorizedException&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="nv"&gt;$status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getBlockchainStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ethereum'&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="nc"&gt;UnauthorizedException&lt;/span&gt; &lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check WHALE_ALERT_API_KEY.&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="nc"&gt;RateLimitException&lt;/span&gt; &lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Use the provider's suggested retry timing when present.&lt;/span&gt;
    &lt;span class="nv"&gt;$retryAfter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRetryAfter&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="nc"&gt;ApiException&lt;/span&gt; &lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Log or handle other API-specific failures.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The retry strategy is intentionally conservative. It is disabled by default, applies only to idempotent GET requests, retries rate-limit and 5xx responses, uses exponential backoff with jitter, and can honor a &lt;code&gt;Retry-After&lt;/code&gt; header. The library also redacts &lt;code&gt;api_key&lt;/code&gt; values from error excerpts and does not log the key itself. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration option&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apiKey&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Empty string&lt;/td&gt;
&lt;td&gt;Sets the credential used for authenticated endpoints. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;30&lt;/code&gt; seconds&lt;/td&gt;
&lt;td&gt;Defines the HTTP timeout. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxRetries&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enables retry attempts for eligible GET requests when set above zero. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;retryDelayMs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;500&lt;/code&gt; ms&lt;/td&gt;
&lt;td&gt;Sets the initial delay used by exponential backoff. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;retryMaxDelayMs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;10000&lt;/code&gt; ms&lt;/td&gt;
&lt;td&gt;Caps the retry delay. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  A natural fit for Laravel
&lt;/h2&gt;

&lt;p&gt;For Laravel projects, the optional &lt;code&gt;WhaleAlertServiceProvider&lt;/code&gt; can publish a &lt;code&gt;config/whale-alert.php&lt;/code&gt; file and register &lt;code&gt;WhaleAlertClient&lt;/code&gt; as a singleton. Developers can then either use the &lt;code&gt;WhaleAlert&lt;/code&gt; facade or request &lt;code&gt;WhaleAlertClient&lt;/code&gt; through dependency injection. That offers a clean path from a simple prototype to maintainable application code. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\WhaleAlert\WhaleAlertClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;WhaleAlertClient&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$chains&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSupportedBlockchains&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'chains.index'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'chains'&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 project also contains runnable REST and WebSocket examples plus PHPUnit tests covering the REST client, WebSocket client, DTOs, and error handling. Those resources make it easier to evaluate the package before embedding it in a broader workflow. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the blockchain feature, not the plumbing
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;whale-alert-php&lt;/code&gt; is for PHP teams that want to work with Whale Alert Enterprise API data without rebuilding the client layer from scratch. Its value is in the details that application code should not need to rediscover: PSR-18 flexibility, immutable typed responses, string-safe monetary fields, explicit error types, controlled retries, guarded pagination, and real-time WebSocket support. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are building a PHP or Laravel tool that monitors, enriches, visualizes, or routes blockchain-transfer events, install the SDK, review the examples, and tailor the subscriptions and request flow to your use case. Visit the &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; for the complete README, source code, and release information. &lt;a href="https://github.com/tigusigalpa/whale-alert-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>blockchain</category>
      <category>bitcoin</category>
    </item>
    <item>
      <title>Supercharge Your Algorithmic Trading with CoinQuant PHP: The Ultimate SDK for Laravel and PHP 8.1+</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Tue, 21 Jul 2026 18:35:38 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/supercharge-your-algorithmic-trading-with-coinquant-php-the-ultimate-sdk-for-laravel-and-php-81-535j</link>
      <guid>https://dev.to/tigusigalpa/supercharge-your-algorithmic-trading-with-coinquant-php-the-ultimate-sdk-for-laravel-and-php-81-535j</guid>
      <description>&lt;p&gt;Are you tired of wrestling with raw cURL requests, parsing Server-Sent Events (SSE) by hand, and building complex polling loops just to interact with trading APIs? If you are a PHP developer or a Laravel enthusiast looking to dive into algorithmic trading, your life is about to get a whole lot easier. Meet &lt;a href="https://github.com/tigusigalpa/coinquant-php" rel="noopener noreferrer"&gt;&lt;strong&gt;coinquant-php&lt;/strong&gt;&lt;/a&gt;, the official PHP and Laravel SDK for the CoinQuant Public API.&lt;/p&gt;

&lt;p&gt;CoinQuant is revolutionizing the way we approach algorithmic trading. It takes a trading idea described in plain English and turns it into a backtestable strategy using advanced AI. However, integrating such powerful tools into your own applications can often be a daunting task. That is where &lt;code&gt;coinquant-php&lt;/code&gt; steps in. This robust SDK wraps the public API, providing a seamless, developer-friendly experience that lets you focus on what really matters: building profitable trading strategies.&lt;/p&gt;

&lt;p&gt;In this comprehensive guide, we will explore why &lt;code&gt;coinquant-php&lt;/code&gt; is a game-changer for PHP developers, delve into its standout features, and show you how to get started in minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Choose CoinQuant PHP?
&lt;/h2&gt;

&lt;p&gt;The landscape of algorithmic trading is often dominated by Python, but PHP remains a powerhouse for web development, especially with frameworks like Laravel. &lt;code&gt;coinquant-php&lt;/code&gt; bridges the gap, allowing PHP developers to leverage the cutting-edge AI capabilities of CoinQuant without leaving their preferred ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Built for Modern PHP
&lt;/h3&gt;

&lt;p&gt;The library is designed for the modern era of PHP. It requires PHP 8.1+ and embraces strict typing, ensuring your code is robust and free from legacy baggage. Whether you are building a standalone script or a complex enterprise application, the SDK provides a solid foundation.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. First-Class Laravel Integration
&lt;/h3&gt;

&lt;p&gt;If you are using Laravel 10, 11, 12, or 13, you are in for a treat. The package auto-registers its &lt;code&gt;ServiceProvider&lt;/code&gt; and &lt;code&gt;Facade&lt;/code&gt;, meaning there is absolutely zero manual wiring required. You can simply install the package and start using the &lt;code&gt;CoinQuant&lt;/code&gt; facade anywhere in your controllers, jobs, or commands. It also binds the client as a singleton for elegant dependency injection.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Comprehensive API Coverage
&lt;/h3&gt;

&lt;p&gt;The SDK doesn't just cover the basics; it provides access to all 37 public endpoints of the CoinQuant API. This includes health checks, chat interactions, strategy generation, versioning, backtesting, reports, templates, credit management, and even community features like leaderboards. Everything you need is right at your fingertips.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Effortless Streaming via Generators
&lt;/h3&gt;

&lt;p&gt;One of the most powerful features of CoinQuant is its AI engine, which responds over Server-Sent Events (SSE). Handling SSE in PHP can be tricky, but the SDK abstracts this away completely. It reads the stream and classifies events into categories like &lt;code&gt;chat&lt;/code&gt;, &lt;code&gt;strategy&lt;/code&gt;, &lt;code&gt;report&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, or &lt;code&gt;unknown&lt;/code&gt;. You can even iterate over the generator directly to stream tokens to a browser in real-time, creating a highly responsive user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Simplified Backtesting
&lt;/h3&gt;

&lt;p&gt;Backtesting is the core of algorithmic trading, and &lt;code&gt;coinquant-php&lt;/code&gt; makes it incredibly simple. The &lt;code&gt;createBacktestAndWait()&lt;/code&gt; method is a one-call solution that submits the run, polls until completion, and returns the final results along with CSV exports for deep analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Actionable Exceptions
&lt;/h3&gt;

&lt;p&gt;Debugging API integrations can be frustrating, but not with this SDK. Any non-2xx response throws a &lt;code&gt;CoinQuantException&lt;/code&gt; that carries the HTTP status, a unique &lt;code&gt;request_id&lt;/code&gt;, a machine-readable &lt;code&gt;code&lt;/code&gt;, and a descriptive message. This makes error handling and troubleshooting a breeze.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started: From Zero to Backtest
&lt;/h2&gt;

&lt;p&gt;Let's walk through how easy it is to get started with &lt;code&gt;coinquant-php&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;First, pull the package in via Composer. Guzzle, the underlying HTTP client, is installed automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require tigusigalpa/coinquant-php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;CoinQuant uses a JWT bearer token for authentication. You can generate one from the Settings menu in the CoinQuant web app. Keep this token secure in an environment variable (&lt;code&gt;COINQUANT_TOKEN&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For standalone PHP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;CoinQuant\CoinQuantClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CoinQuantClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'COINQUANT_TOKEN'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nv"&gt;$credits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getCredits&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Available credits: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$credits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'available_credits_total'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Laravel, simply add the token to your &lt;code&gt;.env&lt;/code&gt; file:&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="nv"&gt;COINQUANT_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_token_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you are ready to use the facade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;CoinQuant\Laravel\Facades\CoinQuant&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$credits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CoinQuant&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getCredits&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Workflow: Idea to Metrics
&lt;/h3&gt;

&lt;p&gt;The true power of the SDK shines when you use it to turn an idea into a fully backtested strategy. Here is a complete workflow in just a few lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Describe the idea and let the AI draft a strategy.&lt;/span&gt;
&lt;span class="nv"&gt;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Long BTCUSDT when price crosses above the 200 EMA on 1h, exit on cross below.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Materialize it if it came back schema-only.&lt;/span&gt;
&lt;span class="nv"&gt;$versionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$res&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;strategyVersionId&lt;/span&gt;
    &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;finalizeChat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$res&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;chatId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'EMA 200 Crossover'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s1"&gt;'latest_version'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Backtest and wait for the verdict.&lt;/span&gt;
&lt;span class="nv"&gt;$outcome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createBacktestAndWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$versionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Analyze the results&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$outcome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'results'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'metrics'&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 simply ask the AI to create a strategy based on the 200 EMA crossover. The SDK handles the streaming response, materializes the strategy blueprint into a backtestable version, runs the backtest, and polls for the results. It is algorithmic trading made remarkably accessible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Advanced Usage: Streaming and Customization
&lt;/h2&gt;

&lt;p&gt;For developers who need more control, &lt;code&gt;coinquant-php&lt;/code&gt; delivers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-Time Streaming
&lt;/h3&gt;

&lt;p&gt;If you are building a user interface and want to show the AI's thought process in real-time, you can iterate the generator directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;CoinQuant\Streaming\StreamEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;streamPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Explain the RSI indicator.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$event&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="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nc"&gt;StreamEvent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TYPE_CHAT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Flush to the client in real time&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;
  
  
  Custom HTTP Clients
&lt;/h3&gt;

&lt;p&gt;Under the hood, the SDK uses Guzzle. If you need to configure retries, route traffic through a proxy, or add custom headers for tracing, you can pass your own configured Guzzle client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;GuzzleHttp\Client&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;GuzzleClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GuzzleClient&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'timeout'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'headers'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Authorization'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Bearer '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'COINQUANT_TOKEN'&lt;/span&gt; &lt;span class="p"&gt;)],&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CoinQuantClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'COINQUANT_TOKEN'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$http&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;The &lt;code&gt;coinquant-php&lt;/code&gt; SDK is a masterclass in developer experience. By abstracting away the complexities of the CoinQuant API, SSE parsing, and asynchronous polling, it empowers PHP developers to build sophisticated trading applications with unprecedented speed and ease.&lt;/p&gt;

&lt;p&gt;Whether you are a solo developer exploring algorithmic trading or a team building a comprehensive financial platform on Laravel, this SDK provides the tools you need to succeed. The strict typing, elegant Laravel integration, and comprehensive endpoint coverage make it a joy to use.&lt;/p&gt;

&lt;p&gt;Ready to turn your trading ideas into reality? Head over to the &lt;a href="https://github.com/tigusigalpa/coinquant-php" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;, give it a star, and start building today!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Happy Coding and Happy Trading!&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repository Author:&lt;/strong&gt; Igor Sazonov (&lt;a href="https://github.com/tigusigalpa" rel="noopener noreferrer"&gt;@tigusigalpa&lt;/a&gt;)&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>coinquant</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>Build AI-Powered Trading Strategies in Go with CoinQuant-Go</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Tue, 21 Jul 2026 07:23:32 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/build-ai-powered-trading-strategies-in-go-with-coinquant-go-444m</link>
      <guid>https://dev.to/tigusigalpa/build-ai-powered-trading-strategies-in-go-with-coinquant-go-444m</guid>
      <description>&lt;p&gt;Algorithmic trading has traditionally been a domain characterized by high barriers to entry. Quants and developers spend countless hours writing boilerplate code to handle HTTP requests, parse complex JSON responses, and manage Server-Sent Events (SSE) streams. However, the landscape is rapidly evolving with the integration of Artificial Intelligence into trading workflows. CoinQuant is at the forefront of this revolution, offering a platform where you can describe a trading idea in plain English and let AI turn it into a backtestable strategy.&lt;/p&gt;

&lt;p&gt;But what if you want to integrate this powerful AI engine directly into your Go applications? Enter &lt;code&gt;coinquant-go&lt;/code&gt;, a comprehensive, community-driven Go client for the CoinQuant Public API. In this article, we will explore why &lt;code&gt;coinquant-go&lt;/code&gt; is the ultimate tool for Go developers looking to build, backtest, and deploy algorithmic trading strategies with AI in the loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with API Boilerplate
&lt;/h2&gt;

&lt;p&gt;When integrating third-party APIs into Go applications, developers often face a repetitive and error-prone process. Writing HTTP clients, managing context timeouts, handling retries, and parsing nested JSON responses can quickly bloat your codebase. This is especially true for platforms like CoinQuant, which rely heavily on streaming responses via Server-Sent Events (SSE) to deliver real-time AI-generated content.&lt;/p&gt;

&lt;p&gt;Without a dedicated SDK, developers are forced to write custom parsers for raw event frames, handle connection drops, and manually map JSON structures to Go structs. This not only slows down development but also increases the likelihood of runtime errors. &lt;code&gt;coinquant-go&lt;/code&gt; solves this problem by providing an intentionally thin, idiomatic Go wrapper around the CoinQuant API, allowing you to focus on your trading logic rather than the underlying plumbing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Choose CoinQuant-Go?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;coinquant-go&lt;/code&gt; is designed with the Go developer in mind. It embraces the language's core principles of simplicity, strong typing, and concurrency. Here are the key features that make it stand out:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Idiomatic Go Design
&lt;/h3&gt;

&lt;p&gt;Every function in &lt;code&gt;coinquant-go&lt;/code&gt; takes a &lt;code&gt;context.Context&lt;/code&gt; as its first argument, adhering to Go's standard practices for cancellation and timeout management. Requests and responses are defined as concrete structs with explicit &lt;code&gt;json&lt;/code&gt; tags. This means you never have to deal with the guesswork and type assertions associated with &lt;code&gt;map[string]any&lt;/code&gt;. The strongly typed nature of the library ensures compile-time safety and excellent IDE support.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Comprehensive API Coverage
&lt;/h3&gt;

&lt;p&gt;The library provides full coverage of all 37 public endpoints offered by CoinQuant. Whether you need to check your credit balance, manage chat sessions, create strategies, run backtests, or fetch research reports, &lt;code&gt;coinquant-go&lt;/code&gt; has a dedicated, strongly typed method for it. You have complete programmatic control over your CoinQuant account.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Robust SSE Streaming
&lt;/h3&gt;

&lt;p&gt;One of the most challenging aspects of working with AI APIs is handling streaming responses. &lt;code&gt;coinquant-go&lt;/code&gt; abstracts away the complexity of parsing raw SSE frames. It provides a callback-driven streaming interface for endpoints like &lt;code&gt;POST /v1/prompts/stream&lt;/code&gt; and &lt;code&gt;POST /v1/chats/{chat_id}/messages:stream&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The library automatically reads the stream, passes each event to your callback function as it arrives, and returns a classified &lt;code&gt;StreamResult&lt;/code&gt; when the stream closes. Events are intelligently classified into &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;strategy&lt;/code&gt;, &lt;code&gt;report&lt;/code&gt;, &lt;code&gt;chat&lt;/code&gt;, or &lt;code&gt;unknown&lt;/code&gt; using CoinQuant's own precedence rules, making it incredibly easy to handle different types of AI responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Seamless Backtesting Workflows
&lt;/h3&gt;

&lt;p&gt;Running backtests is a core part of developing trading strategies. &lt;code&gt;coinquant-go&lt;/code&gt; simplifies this process with the &lt;code&gt;CreateBacktestAndWait&lt;/code&gt; function. This utility method wraps the entire backtesting lifecycle: it submits a strategy version for testing, polls the API at regular intervals until a terminal state is reached (such as &lt;code&gt;completed&lt;/code&gt;, &lt;code&gt;failed&lt;/code&gt;, or &lt;code&gt;error&lt;/code&gt;), and returns the final results along with the raw CSV exports. This eliminates the need to write custom polling loops in your application code.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Schema-Only Materialization
&lt;/h3&gt;

&lt;p&gt;Sometimes, the CoinQuant AI returns a strategy schema without a specific version ID. This acts as a blueprint rather than a runnable strategy. &lt;code&gt;coinquant-go&lt;/code&gt; provides a convenient &lt;code&gt;FinalizeChat&lt;/code&gt; method that takes this schema and materializes it into a real, versioned strategy that is ready for backtesting.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Actionable Error Handling
&lt;/h3&gt;

&lt;p&gt;Error handling is critical in financial applications. &lt;code&gt;coinquant-go&lt;/code&gt; converts every non-2xx HTTP response into a typed &lt;code&gt;*APIError&lt;/code&gt;. This struct contains the HTTP status code, a machine-readable error code, a human-readable message, and a unique &lt;code&gt;request_id&lt;/code&gt;. By using &lt;code&gt;errors.As&lt;/code&gt;, you can easily inspect the error and implement appropriate retry logic or notify the user. The &lt;code&gt;request_id&lt;/code&gt; is particularly useful when reaching out to CoinQuant support for troubleshooting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with CoinQuant-Go
&lt;/h2&gt;

&lt;p&gt;Let's dive into some code to see how easy it is to use &lt;code&gt;coinquant-go&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;First, install the package using &lt;code&gt;go get&lt;/code&gt;. Note that the library requires Go 1.22 or newer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/tigusigalpa/coinquant-go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initializing the Client
&lt;/h3&gt;

&lt;p&gt;To interact with the API, you need a JWT bearer token from your CoinQuant account. You can generate this token in the CoinQuant web app under &lt;strong&gt;Settings → Service Accounts → New key&lt;/strong&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="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;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;

    &lt;span class="n"&gt;coinquant&lt;/span&gt; &lt;span class="s"&gt;"github.com/tigusigalpa/coinquant-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;// Initialize the client with your secret token&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;coinquant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"COINQUANT_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&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="c"&gt;// Fetch your available credits&lt;/span&gt;
    &lt;span class="n"&gt;credits&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetCredits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;"Available Credits:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AvailableCreditsTotal&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 client is highly configurable. You can use functional options to override the base URL, set custom timeouts, or inject your own &lt;code&gt;*http.Client&lt;/code&gt; for tracing and proxies.&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="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;coinquant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"COINQUANT_TOKEN"&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;coinquant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="o"&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="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;coinquant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithHTTPClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myCustomClient&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;
  
  
  Streaming an AI Prompt
&lt;/h3&gt;

&lt;p&gt;Let's ask the CoinQuant AI to generate a trading strategy and stream the response to the console in real-time.&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="n"&gt;result&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coinquant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamingPromptRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Generate a BTCUSDT 1h EMA crossover strategy."&lt;/span&gt;&lt;span class="p"&gt;,&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;ev&lt;/span&gt; &lt;span class="n"&gt;coinquant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Print each chunk of text as it arrives&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;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&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="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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Response classified as:"&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;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The library automatically classifies the response. If the AI generated a strategy, &lt;code&gt;result.Type&lt;/code&gt; will be &lt;code&gt;coinquant.StreamTypeStrategy&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Complete Workflow: From Idea to Metrics
&lt;/h3&gt;

&lt;p&gt;Here is a complete, end-to-end example of generating a strategy, materializing it, running a backtest, and fetching the results.&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="c"&gt;// 1. Describe the idea and let the AI draft a strategy.&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coinquant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamingPromptRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Long BTCUSDT when price crosses above the 200 EMA on 1h, exit on cross below."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// 2. Materialize the strategy if it came back schema-only.&lt;/span&gt;
&lt;span class="n"&gt;versionID&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrategyVersionID&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="n"&gt;versionID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrategyVersionID&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChatID&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="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FinalizeChat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChatID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"EMA 200 Crossover"&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="n"&gt;versionID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LatestVersion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// 3. Run the backtest and wait for completion (900s timeout, 5s poll interval).&lt;/span&gt;
&lt;span class="n"&gt;bt&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateBacktestAndWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;versionID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Backtest failed:"&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;// 4. Print the performance metrics.&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;"Backtest Status:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Detail&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&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;bt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Results&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="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Total Return: %v%%&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Total Return"&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sharpe Ratio: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Sharpe Ratio"&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;With just a few lines of Go code, we have interacted with a sophisticated AI engine, generated a trading algorithm, tested it against historical data, and retrieved the performance metrics.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;coinquant-go&lt;/code&gt; bridges the gap between the power of the CoinQuant AI platform and the robust ecosystem of the Go programming language. By providing an idiomatic, strongly typed, and feature-complete SDK, it empowers developers to build complex algorithmic trading systems without getting bogged down by API intricacies.&lt;/p&gt;

&lt;p&gt;Whether you are building a custom trading bot, an automated research tool, or integrating AI-driven insights into an existing financial application, &lt;code&gt;coinquant-go&lt;/code&gt; provides the solid foundation you need.&lt;/p&gt;

&lt;p&gt;Head over to the &lt;a href="https://github.com/tigusigalpa/coinquant-go" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; to check out the source code, read the full API reference, and start building your AI-powered trading strategies today!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Note: *&lt;/em&gt;&lt;code&gt;coinquant-go&lt;/code&gt;** is an unofficial community package and is not maintained or endorsed by CoinQuant.*&lt;/p&gt;

</description>
      <category>go</category>
      <category>coinquant</category>
      <category>trading</category>
      <category>bitcoin</category>
    </item>
    <item>
      <title>Building High-Performance Crypto Trading Bots with Go: Meet phemex-go</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Sun, 19 Jul 2026 11:54:35 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/building-high-performance-crypto-trading-bots-with-go-meet-phemex-go-28ac</link>
      <guid>https://dev.to/tigusigalpa/building-high-performance-crypto-trading-bots-with-go-meet-phemex-go-28ac</guid>
      <description>&lt;p&gt;If you are building a cryptocurrency trading bot, market maker, or data aggregator in Go, you already know that talking to an exchange's API should be the least of your worries. Your focus needs to be on strategy, risk management, and execution speed. Unfortunately, many exchange SDKs are either auto-generated and unidiomatic, bloated with third-party dependencies, or missing crucial features like automatic request signing and resilient WebSockets.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://github.com/tigusigalpa/phemex-go" rel="noopener noreferrer"&gt;&lt;code&gt;phemex-go&lt;/code&gt;&lt;/a&gt; — a friendly, batteries-included Golang SDK for the &lt;a href="https://phemex.com/" rel="noopener noreferrer"&gt;Phemex&lt;/a&gt; crypto exchange.&lt;/p&gt;

&lt;p&gt;Whether you want to trade spot, perpetuals (USDⓈ-M and Coin-M), or margin, stream live market data, or manage your wallets, &lt;code&gt;phemex-go&lt;/code&gt; provides a clean, idiomatic, and robust foundation for your Go applications.&lt;/p&gt;

&lt;p&gt;In this article, we will explore why &lt;code&gt;phemex-go&lt;/code&gt; stands out, how its core architecture simplifies exchange interactions, and walk through practical examples of using its REST and WebSocket APIs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Choose &lt;code&gt;phemex-go&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Talking to a crypto exchange should feel boring — in the best possible way. No surprises, no leaked goroutines, no mystery around request signing. That's exactly what &lt;code&gt;phemex-go&lt;/code&gt; is built for.&lt;/p&gt;

&lt;p&gt;Here is what makes it a compelling choice for Go developers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contexts Everywhere:&lt;/strong&gt; Every REST and WebSocket call takes a &lt;code&gt;context.Context&lt;/code&gt;. This means cancellation, deadlines, and graceful shutdown work exactly as you expect them to in modern Go applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Invisible Request Signing:&lt;/strong&gt; Private requests require HMAC SHA256 signatures. &lt;code&gt;phemex-go&lt;/code&gt; handles this automatically. You never have to manually touch a timestamp or construct a signature header.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resilient WebSocket Client:&lt;/strong&gt; Networks drop. Servers hiccup. The &lt;code&gt;phemex-go&lt;/code&gt; WebSocket client is built for the real world. It reconnects on its own, keeps the connection alive with heartbeats, and delivers events over plain Go channels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain-Driven Design:&lt;/strong&gt; The API is huge, but the SDK is organized logically. Market data, spot, USDⓈ-M, Coin-M, margin, and assets each live in their own small, focused package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Featherweight Dependencies:&lt;/strong&gt; The only third-party dependency is &lt;code&gt;gorilla/websocket&lt;/code&gt;. Everything else relies on the Go standard library, keeping your module graph clean and secure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fully Tested:&lt;/strong&gt; Signature generation and the REST layer are covered by unit tests and &lt;code&gt;httptest&lt;/code&gt; mocks, ensuring reliability without hitting live endpoints during your CI/CD pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Typed Error Handling:&lt;/strong&gt; Stop parsing error strings. &lt;code&gt;phemex-go&lt;/code&gt; provides typed errors (e.g., &lt;code&gt;RateLimitError&lt;/code&gt;, &lt;code&gt;AuthenticationError&lt;/code&gt; ), allowing you to handle edge cases programmatically.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;To start using &lt;code&gt;phemex-go&lt;/code&gt;, you need Go 1.21 or newer. Install the package using &lt;code&gt;go get&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/tigusigalpa/phemex-go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, import the core package along with the specific domain packages you need:&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;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/tigusigalpa/phemex-go"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/tigusigalpa/phemex-go/market"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/tigusigalpa/phemex-go/spot"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Core Architecture
&lt;/h3&gt;

&lt;p&gt;A little mental model goes a long way. The SDK is split into two primary layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Core Client (&lt;/strong&gt;&lt;strong&gt;&lt;code&gt;phemex.NewClient&lt;/code&gt;&lt;/strong&gt;&lt;strong&gt;):&lt;/strong&gt; This layer owns the HTTP transport, credentials, signing logic, retries, and error mapping.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain Clients (&lt;/strong&gt;&lt;strong&gt;&lt;code&gt;market.NewClient&lt;/code&gt;&lt;/strong&gt;&lt;strong&gt;, **&lt;/strong&gt;&lt;code&gt;spot.NewClient&lt;/code&gt;*&lt;em&gt;**, etc.):&lt;/em&gt;* These are thin, typed wrappers around the core client, specific to an API area.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You create the core client once and share it across as many domain clients as you need. It is completely safe for concurrent use.&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="n"&gt;core&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;APIKey&lt;/span&gt;&lt;span class="o"&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PHEMEX_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;APISecret&lt;/span&gt;&lt;span class="o"&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PHEMEX_API_SECRET"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;spotClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;spot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;usdtmClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;usdtm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;assetsClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;assets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Exploring the REST API
&lt;/h2&gt;

&lt;p&gt;The library mirrors Phemex's API structure. Let's look at some common use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching Public Market Data
&lt;/h3&gt;

&lt;p&gt;Public market data endpoints work without credentials, making them great for prototyping and read-only tools.&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;"log"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/tigusigalpa/phemex-go"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/tigusigalpa/phemex-go/market"&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="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&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="c"&gt;// Initialize core and domain client&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{}))&lt;/span&gt;

    &lt;span class="c"&gt;// Fetch the order book snapshot for BTCUSD&lt;/span&gt;
    &lt;span class="n"&gt;book&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"BTCUSD"&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;"Order Book:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Fetch candlesticks (klines) with a typed request&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;klines&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KlineRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;"BTCUSDT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Resolution&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Limit&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;limit&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;"Klines:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;klines&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;
  
  
  Placing a Spot Trade
&lt;/h3&gt;

&lt;p&gt;For anything that touches your account—placing orders, reading balances, transferring funds—you must provide an API key and secret.&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;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/tigusigalpa/phemex-go"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/tigusigalpa/phemex-go/spot"&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="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&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;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;spot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;APIKey&lt;/span&gt;&lt;span class="o"&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PHEMEX_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;APISecret&lt;/span&gt;&lt;span class="o"&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PHEMEX_API_SECRET"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;

    &lt;span class="c"&gt;// Place a limit buy order&lt;/span&gt;
    &lt;span class="n"&gt;resp&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"symbol"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"BTCUSDT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"side"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;"Buy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"ordType"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"Limit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"price"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"65000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"orderQty"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"0.001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;"Order placed:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Review open orders&lt;/span&gt;
    &lt;span class="n"&gt;open&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryOpenOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"BTCUSDT"&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;"Open orders:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Streaming Real-Time Data with WebSockets
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;ws&lt;/code&gt; package provides a resilient, real-time feed. It automatically reconnects after drops, sends periodic heartbeats to keep the socket healthy, replays your subscriptions on reconnect, and delivers every message over a Go channel.&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;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/tigusigalpa/phemex-go/ws"&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="n"&gt;client&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;NewClient&lt;/span&gt;&lt;span class="p"&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;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Credentials are only needed for private channels like 'aop'&lt;/span&gt;
        &lt;span class="n"&gt;APIKey&lt;/span&gt;&lt;span class="o"&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PHEMEX_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;APISecret&lt;/span&gt;&lt;span class="o"&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;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PHEMEX_API_SECRET"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&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;WithTimeout&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="m"&gt;30&lt;/span&gt;&lt;span class="o"&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="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Connect to the WebSocket&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="n"&gt;client&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;ctx&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="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;defer&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Subscribe to the order book for a symbol&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="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"orderbook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"BTCUSDT"&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="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;// Consume events as they arrive&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ev&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Events&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%+v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ev&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;When you provide credentials, the client authenticates with a &lt;code&gt;user.auth&lt;/code&gt; message before your subscriptions go out, ensuring private channels like &lt;code&gt;aop&lt;/code&gt; (Account / Order / Position updates) are ready to use immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Smart Error Handling and Retries
&lt;/h2&gt;

&lt;p&gt;One of the standout features of &lt;code&gt;phemex-go&lt;/code&gt; is its intelligent error handling. Rate limits (HTTP 429) and server errors (HTTP 5xx) are retried automatically with exponential backoff, honoring the &lt;code&gt;Retry-After&lt;/code&gt; header when present.&lt;/p&gt;

&lt;p&gt;When an error does reach your code, it is strongly typed, allowing for precise control flow:&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="n"&gt;resp&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&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="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Slow down — retry after %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetryAfter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticationError&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Check your API key and secret"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ValidationError&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The request was rejected: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotFoundError&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Resource not found: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;phemex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIError&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Phemex error %d: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unexpected error: %v"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;Building a crypto trading system requires a solid foundation. You shouldn't have to write your own request signing logic, implement exponential backoff for rate limits, or manage WebSocket reconnection loops.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tigusigalpa/phemex-go" rel="noopener noreferrer"&gt;&lt;code&gt;phemex-go&lt;/code&gt;&lt;/a&gt; abstracts away the boilerplate of interacting with the Phemex exchange, providing a fast, idiomatic, and highly reliable Go SDK. Whether you are building a high-frequency trading bot, a portfolio tracker, or a market data aggregator, &lt;code&gt;phemex-go&lt;/code&gt; gives you the tools you need to succeed.&lt;/p&gt;

&lt;p&gt;Check out the repository on GitHub, star the project, and dive into the &lt;code&gt;examples/&lt;/code&gt; directory to see it in action!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/tigusigalpa/phemex-go" rel="noopener noreferrer"&gt;https://github.com/tigusigalpa/phemex-go&lt;/a&gt;&lt;strong&gt;Author:&lt;/strong&gt; Igor Sazonov (&lt;a class="mentioned-user" href="https://dev.to/tigusigalpa"&gt;@tigusigalpa&lt;/a&gt;)&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: Trading cryptocurrencies carries significant risk. This library is provided as-is. Test thoroughly—ideally against the Phemex testnet—before running anything with real money.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>phemex</category>
      <category>cryptocurrency</category>
      <category>bitcoin</category>
    </item>
    <item>
      <title>Stop Wrestling with cURL: The Modern PHP Client for Phemex Crypto Trading</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Sun, 19 Jul 2026 10:59:37 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/stop-wrestling-with-curl-the-modern-php-client-for-phemex-crypto-trading-38nj</link>
      <guid>https://dev.to/tigusigalpa/stop-wrestling-with-curl-the-modern-php-client-for-phemex-crypto-trading-38nj</guid>
      <description>&lt;p&gt;Trading cryptocurrency programmatically is an exciting endeavor, but it often comes with a steep learning curve. When you decide to integrate a cryptocurrency exchange API into your PHP application, you quickly realize that executing trades is only half the battle. The other half involves wrestling with raw cURL requests, managing complex HMAC SHA256 signatures, mapping JSON responses, and handling rate limits. This plumbing can drain your time and distract you from what truly matters: your trading strategy.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://github.com/tigusigalpa/phemex-php" rel="noopener noreferrer"&gt;phemex-php&lt;/a&gt;, a modern, strictly typed PHP client for the Phemex cryptocurrency exchange API created by Igor Sazonov. Designed for PHP 8.1+ and offering first-class Laravel integration, this open-source package transforms the Phemex REST API into a clean, object-oriented interface. In this article, we will explore why &lt;code&gt;phemex-php&lt;/code&gt; is the missing piece in your crypto trading stack and how it simplifies building robust trading bots and applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge of Crypto API Integration
&lt;/h2&gt;

&lt;p&gt;Integrating with a cryptocurrency exchange like Phemex &lt;a href="https://phemex.com/home-api" rel="noopener noreferrer"&gt;1&lt;/a&gt; requires developers to navigate several technical hurdles. First and foremost is authentication. Private endpoints demand proper HMAC SHA256 signing, which involves concatenating the URL path, query string, expiry time, and request body, and then hashing it with your API secret &lt;a href="https://github.com/phemex/phemex-api-docs" rel="noopener noreferrer"&gt;2&lt;/a&gt;. A single misplaced character or incorrect timestamp will result in an authentication failure.&lt;/p&gt;

&lt;p&gt;Secondly, developers must handle rate limits gracefully. Exchanges enforce strict request quotas to protect their infrastructure &lt;a href="https://github.com/phemex/phemex-api-docs" rel="noopener noreferrer"&gt;2&lt;/a&gt;. When you hit a rate limit (HTTP 429), your application needs to catch the error, read the retry-after headers, and implement exponential backoff before attempting the request again.&lt;/p&gt;

&lt;p&gt;Finally, there is the issue of type safety and response mapping. Raw JSON responses are prone to typos and lack IDE auto-completion. Without a robust data transfer object (DTO) layer, maintaining and scaling your application becomes a nightmare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Choose phemex-php?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;phemex-php&lt;/code&gt; package addresses these challenges head-on, offering a developer experience that is both powerful and intuitive. Let's delve into the core features that make this library stand out.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Strictly Typed and Future-Proof
&lt;/h3&gt;

&lt;p&gt;Built for PHP 8.1+, the library leverages modern PHP features such as typed properties, return types, and named arguments. Every API response is wrapped in a DTO. This means you get full IDE auto-completion for response fields, significantly reducing the risk of runtime errors.&lt;/p&gt;

&lt;p&gt;Moreover, the DTOs are designed to preserve the raw payload. If Phemex adds new fields to their API responses, you can still access them without waiting for the library to be updated. This future-proof design ensures your application remains stable even as the exchange evolves.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Framework-Agnostic with First-Class Laravel Support
&lt;/h3&gt;

&lt;p&gt;At its core, &lt;code&gt;phemex-php&lt;/code&gt; is framework-agnostic. It uses PSR-18 for HTTP communication, meaning it can run in any PHP environment &lt;a href="https://www.php-fig.org/psr/psr-18/" rel="noopener noreferrer"&gt;3&lt;/a&gt;. However, if you are a Laravel developer, you are in for a treat. The package ships with auto-discovered service providers, publishable configuration files, and a convenient &lt;code&gt;Phemex&lt;/code&gt; facade for Laravel 10–13.&lt;/p&gt;

&lt;p&gt;This dual approach ensures that whether you are building a lightweight standalone script or a massive Laravel application, the library integrates seamlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Automatic HMAC Signing and Rate Limit Handling
&lt;/h3&gt;

&lt;p&gt;Security and stability are built into the library by default. Private endpoints are signed automatically using the official Phemex HMAC SHA256 algorithm. You never have to worry about constructing the signature string yourself.&lt;/p&gt;

&lt;p&gt;Furthermore, the library features automatic retries for rate limits (HTTP 429) and transient server errors. It implements exponential backoff, ensuring your application respects the exchange's limits while maximizing the chances of a successful request.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Bring Your Own HTTP Client
&lt;/h3&gt;

&lt;p&gt;By default, the library uses Guzzle, the industry standard for HTTP requests in PHP. However, because it adheres to the PSR-18 standard, you can inject any compatible HTTP client. This flexibility is crucial for unit testing, as it allows you to mock HTTP responses without making actual network calls, or for adding custom middleware, logging, and metrics to your requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Comprehensive Endpoint Coverage
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;phemex-php&lt;/code&gt; library provides extensive coverage of the Phemex REST API. Endpoints are logically grouped into dedicated methods on the client, making navigation a breeze:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Group&lt;/th&gt;
&lt;th&gt;Client Method&lt;/th&gt;
&lt;th&gt;Covered Endpoints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Market Data&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$client-&amp;gt;market()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Products, orderbook, kline, trades, 24h tickers, funding rate history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spot Trading&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$client-&amp;gt;spot()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create, amend, cancel orders, wallets, order/trade history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USDⓈ-M Contracts&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$client-&amp;gt;usdm()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Orders, positions, leverage, assign balance, trade history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coin-M Contracts&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$client-&amp;gt;coinM()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Orders, positions, leverage, risk limit, assign balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Margin Trading&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$client-&amp;gt;margin()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Orders, borrow history, borrow, payback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assets &amp;amp; Transfers&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$client-&amp;gt;assets()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Transfers, deposit addresses, deposit/withdraw history&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Getting Started: A Quick Example
&lt;/h2&gt;

&lt;p&gt;Installing the package is as simple as running a Composer command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require tigusigalpa/phemex-php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using Laravel, publish the configuration file to customize your settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Tigusigalpa&lt;/span&gt;&lt;span class="se"&gt;\P&lt;/span&gt;&lt;span class="s2"&gt;hemex&lt;/span&gt;&lt;span class="se"&gt;\L&lt;/span&gt;&lt;span class="s2"&gt;aravel&lt;/span&gt;&lt;span class="se"&gt;\P&lt;/span&gt;&lt;span class="s2"&gt;hemexServiceProvider"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, set your environment variables in your &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;PHEMEX_API_KEY&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_api_key&lt;/span&gt;
&lt;span class="py"&gt;PHEMEX_API_SECRET&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_api_secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is how you can fetch the 24-hour ticker for Bitcoin in plain PHP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\Phemex\PhemexClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PhemexClient&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'PHEMEX_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'api_secret'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'PHEMEX_API_SECRET'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$ticker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;market&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ticker24h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BTCUSDT'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ticker&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the equivalent code using the Laravel Facade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\Phemex\Laravel\Facades\Phemex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$ticker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Phemex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;market&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ticker24h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BTCUSDT'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating a spot order is equally straightforward and type-safe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Phemex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'symbol'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'BTCUSDT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'side'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Buy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'ordType'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Limit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'orderQty'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'0.001'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'priceEp'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;65000000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exception Handling Done Right
&lt;/h2&gt;

&lt;p&gt;A robust API client must provide clear and actionable error messages. The &lt;code&gt;phemex-php&lt;/code&gt; library defines a clear exception hierarchy, allowing you to catch specific errors and respond accordingly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\Phemex\Exceptions\AuthenticationException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\Phemex\Exceptions\NotFoundException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\Phemex\Exceptions\RateLimitException&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="nv"&gt;$positions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;usdm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;accountPositions&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="nc"&gt;AuthenticationException&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle invalid or missing credentials&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="nc"&gt;NotFoundException&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle resource not found&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="nc"&gt;RateLimitException&lt;/span&gt; &lt;span class="nv"&gt;$e&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 $e-&amp;gt;retryAfter() and $e-&amp;gt;remaining()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-Time Data with WebSockets
&lt;/h2&gt;

&lt;p&gt;While REST APIs are great for executing trades and fetching historical data, real-time trading requires WebSockets. The &lt;code&gt;phemex-php&lt;/code&gt; library offers optional WebSocket support via the &lt;code&gt;ratchet/pawl&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Simply install the dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require ratchet/pawl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you can instantly subscribe to live orderbook updates or trade streams:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\Phemex\WebSocket\Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'wss://vstream.phemex.com/ws'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ws&lt;/span&gt;&lt;span class="o"&gt;-&amp;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;onMessage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getPayload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;onClose&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Connection closed'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&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="nv"&gt;$ws&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'orderbook.subscribe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'trade.subscribe'&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;Building a cryptocurrency trading application should be about crafting winning strategies, not battling API intricacies. The &lt;code&gt;phemex-php&lt;/code&gt; library abstracts away the complexities of the Phemex REST API, providing a modern, strictly typed, and developer-friendly interface. Whether you are building a simple market data tracker or a sophisticated algorithmic trading bot in Laravel, this package is an invaluable tool in your arsenal.&lt;/p&gt;

&lt;p&gt;Check out the repository on GitHub, star the project, and start building your next crypto application today!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tigusigalpa/phemex-php" rel="noopener noreferrer"&gt;GitHub Repository: tigusigalpa/phemex-php&lt;/a&gt;&lt;/p&gt;

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

</description>
      <category>php</category>
      <category>laravel</category>
      <category>phemex</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>Deep Dive into nansen-php: An Elegant PHP Client for the Nansen AI API</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Wed, 15 Jul 2026 15:42:50 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/deep-dive-into-nansen-php-an-elegant-php-client-for-the-nansen-ai-api-24l8</link>
      <guid>https://dev.to/tigusigalpa/deep-dive-into-nansen-php-an-elegant-php-client-for-the-nansen-ai-api-24l8</guid>
      <description>&lt;p&gt;Integrating third-party APIs can often turn into a tedious routine: copy-pasting the same cURL boilerplate, manually decoding JSON responses, and reinventing rate-limit and error-handling logic for every new project. If you are working with cryptocurrency data and leveraging the Nansen AI API, a new library by Igor Sazonov (tigusigalpa) called &lt;code&gt;nansen-php&lt;/code&gt; promises to eliminate this headache.&lt;/p&gt;

&lt;p&gt;In this article, we will take a comprehensive look at the &lt;a href="https://github.com/tigusigalpa/nansen-php" rel="noopener noreferrer"&gt;tigusigalpa/nansen-php&lt;/a&gt; repository &lt;a href="https://github.com/tigusigalpa/nansen-php" rel="noopener noreferrer"&gt;1&lt;/a&gt;. We will explore its architecture, highlight its key features, and understand why it deserves the attention of PHP developers—especially those working within the Laravel ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is nansen-php?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;nansen-php&lt;/code&gt; is a framework-agnostic PHP 8.1+ client designed specifically for the Nansen AI API. It provides developers with an elegant, fluent (chainable) interface for making requests, returns strongly typed Data Transfer Objects (DTOs), automatically handles rate limits with built-in retry logic, and offers first-class support for the Laravel framework (versions 10 through 13).&lt;/p&gt;

&lt;p&gt;The primary goal of the library is to hide all the HTTP request boilerplate behind an expressive API, making your code read almost like a natural language sentence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features and Architectural Decisions
&lt;/h2&gt;

&lt;p&gt;After reviewing the library's source code, several strong architectural choices stand out, making it an excellent tool for Nansen AI integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Expressive Fluent API
&lt;/h3&gt;

&lt;p&gt;Instead of manually constructing arrays of parameters and passing them to an HTTP client, &lt;code&gt;nansen-php&lt;/code&gt; employs the Builder pattern. The &lt;code&gt;RequestBuilder&lt;/code&gt; class allows you to construct a query step-by-step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\Nansen\NansenClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NansenClient&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'api_key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'YOUR_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$netflows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;smartMoney&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;netflows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;chains&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'ethereum'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every modifier method (&lt;code&gt;chains()&lt;/code&gt;, &lt;code&gt;filters()&lt;/code&gt;, &lt;code&gt;orderBy()&lt;/code&gt;, &lt;code&gt;limit()&lt;/code&gt;, &lt;code&gt;offset()&lt;/code&gt;, &lt;code&gt;page()&lt;/code&gt;) clones the current builder instance and returns a new one. This ensures immutability, allowing you to reuse base queries without unintended side effects.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Strict Typing and Data Transfer Objects (DTOs)
&lt;/h3&gt;

&lt;p&gt;One of the biggest pain points when working with external APIs in PHP is dealing with loosely structured, associative arrays. &lt;code&gt;nansen-php&lt;/code&gt; solves this by returning typed objects.&lt;/p&gt;

&lt;p&gt;All responses inherit from a base &lt;code&gt;Dto&lt;/code&gt; class. This means that lists are returned as real collections that you can iterate over, and property access is done via object properties rather than array keys.&lt;/p&gt;

&lt;p&gt;An interesting and highly practical architectural decision is that every DTO retains the original, untouched API response in a &lt;code&gt;-&amp;gt;raw&lt;/code&gt; property. If Nansen adds a new field to their API response tomorrow, and the library hasn't been updated yet, you can still access that data immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Accessing new, undocumented fields future-proofs your application&lt;/span&gt;
&lt;span class="nv"&gt;$brandNewField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$netflows&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'data'&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="s1"&gt;'brand_new_field'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This guarantees that you will never lose data due to a lagging library version.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Automatic Rate Limit Handling and Retry Logic
&lt;/h3&gt;

&lt;p&gt;Working with robust APIs often involves encountering &lt;code&gt;429 Too Many Requests&lt;/code&gt; errors. The &lt;code&gt;Client&lt;/code&gt; class within the &lt;code&gt;Http&lt;/code&gt; namespace takes full responsibility for handling these scenarios.&lt;/p&gt;

&lt;p&gt;When a 429 status is received, the client automatically extracts the &lt;code&gt;Retry-After&lt;/code&gt;, &lt;code&gt;X-RateLimit-Remaining&lt;/code&gt;, or &lt;code&gt;RateLimit-Remaining&lt;/code&gt; headers. It then pauses script execution for the required duration using &lt;code&gt;usleep()&lt;/code&gt; before automatically retrying the request.&lt;/p&gt;

&lt;p&gt;For server-side errors (HTTP statuses &amp;gt;= 500), the library implements an exponential backoff algorithm. The number of retry attempts and the base delay are easily configurable.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Clear Exception Hierarchy
&lt;/h3&gt;

&lt;p&gt;The library does not simply throw generic exceptions. It provides a structured hierarchy extending from a base &lt;code&gt;ApiException&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;RateLimitException&lt;/code&gt;&lt;/strong&gt;: Thrown when the rate limit is exceeded and all retry attempts have been exhausted. It provides useful &lt;code&gt;retryAfter()&lt;/code&gt; and &lt;code&gt;remaining()&lt;/code&gt; methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;UnauthorizedException&lt;/code&gt;&lt;/strong&gt;: Thrown for 401 statuses, typically indicating an invalid or expired API key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;NotFoundException&lt;/code&gt;&lt;/strong&gt;: Thrown for 404 statuses when a resource or address cannot be found.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This hierarchy allows developers to easily catch specific errors and handle them gracefully within their applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. HTTP Client Agnosticism (PSR-18)
&lt;/h3&gt;

&lt;p&gt;By default, &lt;code&gt;nansen-php&lt;/code&gt; utilizes Guzzle (&lt;code&gt;guzzlehttp/guzzle&lt;/code&gt; ). However, the library is fully compliant with the PSR-18 standard. You can inject any other PSR-18 compatible HTTP client by passing it to the constructor or binding it via the Laravel service container. This is particularly useful if you need to use a client with custom middleware, logging, or specific SSL configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. First-Class Laravel Integration
&lt;/h3&gt;

&lt;p&gt;While the library is framework-agnostic at its core, it provides a seamless developer experience for Laravel users. The package includes an auto-discovered &lt;code&gt;NansenServiceProvider&lt;/code&gt; that automatically configures the &lt;code&gt;NansenClient&lt;/code&gt; using settings published to &lt;code&gt;config/nansen.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It also provides a &lt;code&gt;Nansen&lt;/code&gt; facade, enabling you to write highly concise code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\Nansen\Laravel\Facades\Nansen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$balances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Nansen&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;profiler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addressBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'0x1234...'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Supported Endpoints
&lt;/h2&gt;

&lt;p&gt;As of version 1.0.0, the library covers the core and most highly requested Nansen AI endpoints:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Available Endpoints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Smart Money&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;netflows()&lt;/code&gt;, &lt;code&gt;holdings()&lt;/code&gt;, &lt;code&gt;dexTrades()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Token God Mode&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;tokenScreener()&lt;/code&gt;, &lt;code&gt;flowIntelligence()&lt;/code&gt;, &lt;code&gt;whoBoughtSold()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Profiler&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;addressBalance()&lt;/code&gt;, &lt;code&gt;addressDexTrades()&lt;/code&gt;, &lt;code&gt;addressLabels()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Portfolio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;defiHoldings()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;general()&lt;/code&gt;, &lt;code&gt;entity()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Historical Data&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Access to v1beta1 backtesting endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because every endpoint shares the same set of modifiers, once you learn how to query one endpoint, you immediately know how to query them all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Quality and Testing
&lt;/h2&gt;

&lt;p&gt;An analysis of the repository reveals a high standard of engineering culture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PHP 8.1+ Features&lt;/strong&gt;: The codebase actively utilizes modern PHP features such as &lt;code&gt;readonly&lt;/code&gt; properties, &lt;code&gt;match&lt;/code&gt; expressions, and strict typing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;: The presence of a &lt;code&gt;tests&lt;/code&gt; directory and a &lt;code&gt;phpunit.xml&lt;/code&gt; configuration file indicates that the code is covered by tests. According to the README, the test suite runs against a mocked HTTP client, meaning no real API key or network access is required to run them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standards&lt;/strong&gt;: The use of &lt;code&gt;declare(strict_types=1);&lt;/code&gt; is consistent across all files.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The &lt;code&gt;tigusigalpa/nansen-php&lt;/code&gt; repository is an exemplary model of what a modern PHP API SDK should look like. The author didn't just wrap cURL requests in classes; they created a thoughtful architecture that solves real developer pain points: response typing, rate limit handling, and code readability.&lt;/p&gt;

&lt;p&gt;Whether you are building a complex crypto analytics platform on Laravel or a small, standalone PHP script to monitor wallets, this library will save you hours of boilerplate coding and make your codebase cleaner and more reliable.&lt;/p&gt;

&lt;p&gt;The repository is MIT licensed and open for contributions. If you are working with the Nansen API, it is definitely worth requiring &lt;code&gt;tigusigalpa/nansen-php&lt;/code&gt; in your &lt;code&gt;composer.json&lt;/code&gt;.&lt;/p&gt;

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

</description>
      <category>php</category>
      <category>laravel</category>
      <category>cryptocurrency</category>
      <category>nansen</category>
    </item>
    <item>
      <title>Building Crypto Intelligence with Go: A Deep Dive into the nansen-go Library</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Tue, 14 Jul 2026 19:07:16 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/building-crypto-intelligence-with-go-a-deep-dive-into-the-nansen-go-library-2ppg</link>
      <guid>https://dev.to/tigusigalpa/building-crypto-intelligence-with-go-a-deep-dive-into-the-nansen-go-library-2ppg</guid>
      <description>&lt;p&gt;The world of blockchain analytics is vast, complex, and often overwhelming. Developers building crypto applications, trading bots, or analytical dashboards constantly face the challenge of extracting meaningful intelligence from raw onchain data. Enter Nansen AI, a platform renowned for its proprietary data labeling, Smart Money analytics, and comprehensive multi-chain coverage &lt;a href="https://docs.nansen.ai/" rel="noopener noreferrer"&gt;1&lt;/a&gt;. While Nansen provides a powerful API, integrating it cleanly into a Go backend requires a well-designed client. This is where &lt;code&gt;nansen-go&lt;/code&gt; shines.&lt;/p&gt;

&lt;p&gt;In this review, we will explore &lt;code&gt;nansen-go&lt;/code&gt; (available at &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;github.com/tigusigalpa/nansen-go&lt;/a&gt;), an elegant, dependency-free Go client for the Nansen AI API. We will examine its design philosophy, key features, and how it simplifies the process of building crypto intelligence applications in Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Philosophy of &lt;code&gt;nansen-go&lt;/code&gt;: Idiomatic and Unobtrusive
&lt;/h2&gt;

&lt;p&gt;When evaluating a third-party API client, developers often look for a balance between abstraction and control. A good client should handle the boilerplate of HTTP requests, authentication, and error handling without hiding the underlying API or forcing the developer into unnatural patterns. The creator of &lt;code&gt;nansen-go&lt;/code&gt;, Igor Sazonov, has clearly embraced this philosophy.&lt;/p&gt;

&lt;p&gt;The repository's README states that the library "tries to stay out of your way" &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;. This is not just a marketing tagline; it is reflected in the core design choices of the package.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero Dependencies
&lt;/h3&gt;

&lt;p&gt;One of the most striking features of &lt;code&gt;nansen-go&lt;/code&gt; is its complete lack of third-party dependencies. The entire library is built exclusively on the Go standard library &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Nothing to vendor. The whole thing is built on the standard library. &lt;code&gt;go get&lt;/code&gt; it and you're done — no dependency tree to audit." &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In an era where a simple API client can pull in dozens of transitive dependencies, this is a breath of fresh air. For enterprise applications or security-conscious projects, minimizing the dependency footprint is crucial. It reduces the attack surface, simplifies auditing, and ensures that the client won't conflict with other packages in your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contexts Everywhere
&lt;/h3&gt;

&lt;p&gt;Idiomatic Go code relies heavily on &lt;code&gt;context.Context&lt;/code&gt; for managing timeouts, cancellation, and request-scoped values. &lt;code&gt;nansen-go&lt;/code&gt; adheres strictly to this convention. Every API call in the library takes a &lt;code&gt;context.Context&lt;/code&gt; as its first argument &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;. This ensures that developers have fine-grained control over the lifecycle of their requests, making it easy to integrate the client into robust, production-ready systems where timeouts and graceful degradation are essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features and Ergonomics
&lt;/h2&gt;

&lt;p&gt;Beyond its architectural philosophy, &lt;code&gt;nansen-go&lt;/code&gt; offers a range of features designed to make interacting with the Nansen API as smooth as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration via Functional Options
&lt;/h3&gt;

&lt;p&gt;Instead of relying on massive configuration structs, &lt;code&gt;nansen-go&lt;/code&gt; utilizes the functional options pattern for initialization &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;. This allows developers to pass only the configuration parameters they need, while sensible defaults handle the rest.&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="n"&gt;client&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;nansen&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NANSEN_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;nansen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="o"&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="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;nansen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="o"&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;Millisecond&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&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="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;Options like &lt;code&gt;WithBaseURL&lt;/code&gt;, &lt;code&gt;WithHTTPClient&lt;/code&gt;, &lt;code&gt;WithTimeout&lt;/code&gt;, and &lt;code&gt;WithRetry&lt;/code&gt; provide the flexibility needed to adapt the client to various environments, from local testing to high-throughput production deployments &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrency and Safety
&lt;/h3&gt;

&lt;p&gt;Go's concurrency model is one of its strongest selling points, and &lt;code&gt;nansen-go&lt;/code&gt; is built to leverage it. The client is designed to be safe for concurrent use across multiple goroutines &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Safe to share. Create one client and hand it to as many goroutines as you like. No locks, no fuss." &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means you can instantiate a single &lt;code&gt;nansen.Client&lt;/code&gt; at application startup and inject it into your HTTP handlers, background workers, or data pipelines without worrying about race conditions or managing connection pools manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type Safety and Pointer Semantics
&lt;/h3&gt;

&lt;p&gt;The Nansen API expects specific JSON payloads, and &lt;code&gt;nansen-go&lt;/code&gt; ensures that your requests are strictly typed. Chains, sort fields, trader types, and labels are defined as real constants in the library &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Furthermore, optional request fields are implemented as pointers &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;. This is a critical detail in Go, where the zero value of a type (like &lt;code&gt;false&lt;/code&gt; for a boolean or &lt;code&gt;0&lt;/code&gt; for an integer) can sometimes be indistinguishable from an omitted field when marshaling to JSON. By using pointers, &lt;code&gt;nansen-go&lt;/code&gt; guarantees that optional fields are only sent when explicitly provided. To alleviate the verbosity of creating pointers to primitive types, the library includes handy helper functions like &lt;code&gt;nansen.StringPtr()&lt;/code&gt;, &lt;code&gt;nansen.IntPtr()&lt;/code&gt;, and &lt;code&gt;nansen.Float64Ptr()&lt;/code&gt; &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Error Handling and Retries
&lt;/h2&gt;

&lt;p&gt;Interacting with any remote API involves handling failures gracefully. Nansen API rate limits and transient network errors are inevitable, and &lt;code&gt;nansen-go&lt;/code&gt; provides robust mechanisms to deal with them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspectable Errors
&lt;/h3&gt;

&lt;p&gt;When an API call fails, &lt;code&gt;nansen-go&lt;/code&gt; returns an &lt;code&gt;*nansen.APIError&lt;/code&gt;. This custom error type provides deep visibility into the failure, exposing the HTTP status code, the error message, the raw response body, and crucial rate-limit headers &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because the library integrates seamlessly with Go's &lt;code&gt;errors.Is&lt;/code&gt; and &lt;code&gt;errors.As&lt;/code&gt; functions, developers can easily branch their logic based on the specific type of error encountered. The library provides built-in sentinels like &lt;code&gt;nansen.ErrRateLimited&lt;/code&gt;, &lt;code&gt;nansen.ErrUnauthorized&lt;/code&gt;, and &lt;code&gt;nansen.ErrNotFound&lt;/code&gt; for quick checks &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built-in Exponential Backoff
&lt;/h3&gt;

&lt;p&gt;Perhaps the most valuable feature for production use is the built-in retry mechanism. By opting in with &lt;code&gt;nansen.WithRetry()&lt;/code&gt;, developers enable automatic retries with exponential backoff &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;. The client intelligently handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;429 Too Many Requests:&lt;/strong&gt; It pauses execution based on the &lt;code&gt;Retry-After&lt;/code&gt; or &lt;code&gt;RateLimit-Reset&lt;/code&gt; headers returned by the Nansen API &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transient 5xx Errors:&lt;/strong&gt; It retries server-side errors that are likely to resolve themselves quickly &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Flakiness:&lt;/strong&gt; It attempts to recover from temporary connection drops, provided the request context hasn't expired &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crucially, the retry logic respects the overall timeout budget set by the developer, ensuring that retries never block indefinitely &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mapping the Nansen Ecosystem
&lt;/h2&gt;

&lt;p&gt;The Nansen API is expansive, offering data on Smart Money movements, token flows, portfolio holdings, and historical trends. &lt;code&gt;nansen-go&lt;/code&gt; organizes this vast surface area into logical services attached to the main client object &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service Namespace&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example Endpoints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;client.SmartMoney&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Access netflows, holdings, and DEX trades of highly profitable entities.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/v1/smart-money/netflow&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;client.TokenGodMode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Utilize the token screener, flow intelligence, and buyer/seller analysis.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/v1/token-screener&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;client.Profiler&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieve current balances and DEX trade history for specific addresses.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/v1/profiler/address/current-balance&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;client.Portfolio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Analyze DeFi holdings and overall portfolio composition.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/v1/portfolio/defi-holdings&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;client.Historical&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Access backtesting endpoints for historical token flows and balances.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/v1beta1/tgm/historical-token-flow-summary&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This modular approach makes the client highly discoverable. Developers can rely on their IDE's autocomplete to explore the available endpoints within a specific domain, rather than sifting through a monolithic list of functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started and Examples
&lt;/h2&gt;

&lt;p&gt;To help developers hit the ground running, the repository includes a dedicated &lt;code&gt;examples&lt;/code&gt; directory containing complete, runnable programs &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;. These examples cover common use cases such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using the token screener with complex filters and sorting mechanisms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profiling specific addresses to retrieve balances and trade history.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analyzing Smart Money netflows and DEX trades.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running these examples is as simple as setting the &lt;code&gt;NANSEN_API_KEY&lt;/code&gt; environment variable and executing &lt;code&gt;go run&lt;/code&gt; &lt;a href="https://github.com/tigusigalpa/nansen-go" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;nansen-go&lt;/code&gt; library is a masterclass in designing a Go API client. By adhering strictly to idiomatic Go principles—such as zero dependencies, context propagation, functional options, and strong typing—it provides a robust and developer-friendly interface to the Nansen AI platform.&lt;/p&gt;

&lt;p&gt;For developers looking to integrate high-quality onchain analytics into their Go applications, &lt;code&gt;nansen-go&lt;/code&gt; abstracts away the complexity of HTTP communication, error handling, and rate limiting, allowing them to focus on what truly matters: building powerful, data-driven crypto products. It is a tool that truly "stays out of your way" while delivering immense value.&lt;/p&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

</description>
      <category>go</category>
      <category>nansen</category>
      <category>cryptocurrency</category>
      <category>smartmoney</category>
    </item>
    <item>
      <title>Exploring coinglass-php: The Ultimate SDK for Coinglass API v4 in PHP and Laravel</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Sun, 12 Jul 2026 22:33:58 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/exploring-coinglass-php-the-ultimate-sdk-for-coinglass-api-v4-in-php-and-laravel-2j9i</link>
      <guid>https://dev.to/tigusigalpa/exploring-coinglass-php-the-ultimate-sdk-for-coinglass-api-v4-in-php-and-laravel-2j9i</guid>
      <description>&lt;p&gt;Building cryptocurrency analytics dashboards, liquidation trackers, or monitoring funding rate arbitrage often requires reliable access to high-quality market intelligence data. The Coinglass platform provides one of the most comprehensive APIs for derivatives, ETFs, and on-chain analytics. However, integrating REST APIs and WebSocket streams from scratch can be a real headache for developers: writing endless boilerplate, managing HTTP clients, handling errors, and dealing with rate limits.&lt;/p&gt;

&lt;p&gt;Fortunately, a robust solution has emerged for PHP developers. In this article, we will take a deep dive into the &lt;code&gt;coinglass-php&lt;/code&gt; package—a modern, framework-agnostic PHP SDK for the Coinglass API v4 that features first-class Laravel integration [1].&lt;/p&gt;

&lt;h2&gt;
  
  
  What is &lt;code&gt;coinglass-php&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/tigusigalpa/coinglass-php" rel="noopener noreferrer"&gt;&lt;code&gt;coinglass-php&lt;/code&gt;&lt;/a&gt; package (developed by Igor Sazonov) serves as a comprehensive wrapper for all six endpoint groups of the Coinglass API v4: Futures, Spot, Options, ETF, On-Chain, and Indicators [1]. Furthermore, it includes a built-in WebSocket client for handling real-time data streams natively.&lt;/p&gt;

&lt;p&gt;The package was born out of a developer's frustration with hand-rolling Guzzle calls and juggling raw arrays while building a liquidation dashboard. The result is a strictly typed, PSR-18 compliant client that easily drops into any PHP 8.1+ project, or directly into Laravel (versions 10 through 13) [1].&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features of the Package
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Complete API Coverage
&lt;/h3&gt;

&lt;p&gt;The package supports absolutely every endpoint offered by Coinglass v4. You won't have to manually implement missing methods. Out of the box, you can retrieve open interest history, liquidation data, order books, Bitcoin ETF flows, the Fear &amp;amp; Greed index, and much more [1].&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Built-in WebSocket Client (No Extra Dependencies)
&lt;/h3&gt;

&lt;p&gt;To work with the Coinglass WebSocket API (which streams liquidations, spot/futures trades, and tickers), you do not need to install heavy third-party libraries like Ratchet or ReactPHP. The client is built natively on top of standard PHP streams (&lt;code&gt;stream_socket_client&lt;/code&gt;) and the &lt;code&gt;ext-openssl&lt;/code&gt; extension [1]. Subscribing to channels and maintaining the connection—including sending the required "ping" heartbeat every 20 seconds—is handled completely automatically [1].&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Framework-Agnostic and PSR-18 Swappable
&lt;/h3&gt;

&lt;p&gt;While the package boasts excellent Laravel support, it remains entirely independent of it. It uses Guzzle (&lt;code&gt;^7.4&lt;/code&gt;) by default, but thanks to the PSR-18 standard, you can swap it out and inject any HTTP client of your preference [1].&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Automatic Retry Mechanism
&lt;/h3&gt;

&lt;p&gt;The Coinglass API enforces strict rate limits (HTTP 429 Too Many Requests). &lt;code&gt;coinglass-php&lt;/code&gt; handles this elegantly: it automatically retries rate-limited requests using exponential backoff, respectfully honoring the &lt;code&gt;Retry-After&lt;/code&gt; header when the server provides one [1].&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Strict Type Hydration (DTOs)
&lt;/h3&gt;

&lt;p&gt;Say goodbye to unpredictable associative arrays. Every API response is hydrated into a &lt;code&gt;CoinGlassDto&lt;/code&gt; object (for a single record) or a &lt;code&gt;CoinGlassCollection&lt;/code&gt; (for lists) [1]. You can access fields using whatever syntax feels most natural: property syntax (&lt;code&gt;$dto-&amp;gt;openInterestUsd&lt;/code&gt;), array syntax (&lt;code&gt;$dto['openInterestUsd']&lt;/code&gt;), or getter methods (&lt;code&gt;$dto-&amp;gt;get('openInterestUsd')&lt;/code&gt;). If you ever need the untouched raw payload, it is always available via &lt;code&gt;$dto-&amp;gt;raw&lt;/code&gt; or &lt;code&gt;$dto-&amp;gt;toArray()&lt;/code&gt; [1].&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Clear Exception Hierarchy
&lt;/h3&gt;

&lt;p&gt;Instead of throwing a single catch-all &lt;code&gt;Exception&lt;/code&gt;, the package provides a clear and purposeful exception hierarchy: &lt;code&gt;UnauthorizedException&lt;/code&gt;, &lt;code&gt;NotFoundException&lt;/code&gt;, &lt;code&gt;RateLimitException&lt;/code&gt;, and a generic &lt;code&gt;ApiException&lt;/code&gt; for all other API-related errors [1]. This makes writing fault-tolerant code much simpler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Laravel Integration: Ready Out of the Box
&lt;/h2&gt;

&lt;p&gt;For users of Laravel (versions 10, 11, 12, and 13), the package provides maximum convenience. After installing via Composer (&lt;code&gt;composer require tigusigalpa/coinglass-php&lt;/code&gt;), you can publish the configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;coinglass-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configuration is then easily managed through your &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;COINGLASS_API_KEY=your-api-key
COINGLASS_BASE_URL=https://open-api-v4.coinglass.com
COINGLASS_TIMEOUT=15
COINGLASS_RETRY_ATTEMPTS=3
COINGLASS_RETRY_DELAY=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can leverage Dependency Injection to receive the &lt;code&gt;CoinGlassClient&lt;/code&gt; in your controllers, or utilize the elegant &lt;code&gt;CoinGlass&lt;/code&gt; facade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\CoinGlass\Laravel\Facades\CoinGlass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Fetching BTC open interest history for the last 30 days&lt;/span&gt;
&lt;span class="nv"&gt;$oi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CoinGlass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;openInterestOhlcHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BTC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'1d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Practical Usage Examples
&lt;/h2&gt;

&lt;p&gt;The client's API is logically divided into endpoint groups. Here are a few examples demonstrating how effortless it is to retrieve the data you need:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Working with Futures:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CoinGlassClient&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'YOUR_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Funding rate exchange list&lt;/span&gt;
&lt;span class="nv"&gt;$funding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fundingRateExchangeList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BTC'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Liquidation history&lt;/span&gt;
&lt;span class="nv"&gt;$liq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;liquidationHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BTC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'BTCUSDT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'1h'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fetching ETF Data:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bitcoin ETF flows over the last 24 weeks&lt;/span&gt;
&lt;span class="nv"&gt;$flows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;etf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;bitcoinFlowHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'1w'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-time WebSocket Streaming:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\CoinGlass\WebSocket\Channels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Tigusigalpa\CoinGlass\WebSocket\Message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;websocket&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$stream&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Channels&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;liquidationOrders&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nc"&gt;Channels&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;futuresTicker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Binance'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'BTCUSDT'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$stream&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Message&lt;/span&gt; &lt;span class="nv"&gt;$message&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="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nc"&gt;Channels&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;liquidationOrders&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; liquidated &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;volume_usd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&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="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;listen()&lt;/code&gt; method blocks execution forever, making it a perfect fit for long-running CLI workers or queued Laravel jobs [1].&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;coinglass-php&lt;/code&gt; package is a prime example of what a modern PHP API client should look like. It abstracts away all the tedious boilerplate related to HTTP requests, rate limiting, and WebSocket connections, providing developers with a clean, typed, and predictable interface.&lt;/p&gt;

&lt;p&gt;Whether you are building a complex algorithmic trading system in vanilla PHP or developing a crypto analytics portal in Laravel 11, this package will save you hours—if not days—of development time. &lt;/p&gt;

&lt;p&gt;The code quality is backed by solid test coverage (using PHPUnit and Orchestra Testbench for Laravel) and leverages the modern features of PHP 8.1+ [2]. If your project involves crypto market intelligence, &lt;code&gt;coinglass-php&lt;/code&gt; absolutely deserves a spot in your &lt;code&gt;composer.json&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;[1] &lt;a href="https://github.com/tigusigalpa/coinglass-php" rel="noopener noreferrer"&gt;tigusigalpa/coinglass-php GitHub Repository&lt;/a&gt;&lt;br&gt;&lt;br&gt;
[2] &lt;a href="https://packagist.org/packages/tigusigalpa/coinglass-php" rel="noopener noreferrer"&gt;tigusigalpa/coinglass-php Packagist Page&lt;/a&gt;  &lt;/p&gt;

</description>
      <category>coinglass</category>
      <category>php</category>
      <category>laravel</category>
      <category>trading</category>
    </item>
    <item>
      <title>Building a Zero-Dependency Go Client for the Coinglass Crypto Data API</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Sun, 12 Jul 2026 18:00:51 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/building-a-zero-dependency-go-client-for-the-coinglass-crypto-data-api-3k8m</link>
      <guid>https://dev.to/tigusigalpa/building-a-zero-dependency-go-client-for-the-coinglass-crypto-data-api-3k8m</guid>
      <description>&lt;p&gt;If you are building cryptocurrency trading algorithms, liquidation dashboards, or funding rate arbitrage bots, you already know that data is everything. In the crypto derivatives space, &lt;a href="https://coinglass.com" rel="noopener noreferrer"&gt;Coinglass&lt;/a&gt; has established itself as the premier platform for market data. With the release of their unified &lt;a href="https://docs.coinglass.com/reference/getting-started-with-your-api" rel="noopener noreferrer"&gt;API v4&lt;/a&gt;, they opened up institutional-grade access to open interest, funding rates, liquidations, and order book heatmaps across all major exchanges.&lt;/p&gt;

&lt;p&gt;However, when I started building my own tooling in Go to consume this data, I noticed a gap. I wanted a strongly typed, concurrent-safe client that didn't drag a massive tree of third-party dependencies into my &lt;code&gt;go.mod&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;To solve this, I built &lt;a href="https://github.com/tigusigalpa/coinglass-go" rel="noopener noreferrer"&gt;&lt;code&gt;coinglass-go&lt;/code&gt;&lt;/a&gt; — a small, idiomatic, and dependency-free Go SDK for the Coinglass API v4. In this article, I want to share the design decisions behind the library, how it handles rate limiting gracefully, and how you can use it to power your own crypto analytics tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build Another API Client?
&lt;/h2&gt;

&lt;p&gt;When integrating with REST APIs in Go, developers generally have two choices: use an auto-generated client (like OpenAPI/Swagger) or write a custom wrapper. Auto-generated clients are great for API coverage, but they often result in unidiomatic Go code, weird pointer types, and bloated dependencies.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;coinglass-go&lt;/code&gt;, the goals were strict:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero Dependencies:&lt;/strong&gt; The library leans entirely on the Go standard library (&lt;code&gt;net/http&lt;/code&gt;, &lt;code&gt;encoding/json&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt;, &lt;code&gt;time&lt;/code&gt; ). Adding it to your project costs nothing in terms of binary bloat.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Idiomatic Design:&lt;/strong&gt; It uses the functional options pattern for configuration, requires &lt;code&gt;context.Context&lt;/code&gt; for every network call, and organizes endpoints into logical sub-services (Futures, Spot, Options, ETF, Indicators).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resilience:&lt;/strong&gt; Crypto APIs are notorious for strict rate limits. The client needed built-in exponential backoff that automatically honors &lt;code&gt;Retry-After&lt;/code&gt; headers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Designing the Client Architecture
&lt;/h2&gt;

&lt;p&gt;The entry point to the SDK is the &lt;code&gt;Client&lt;/code&gt; struct, which holds the HTTP configuration and exposes the API resource groups as fields. This pattern is heavily inspired by Google's &lt;code&gt;go-github&lt;/code&gt; library.&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;type&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Internal configuration&lt;/span&gt;
    &lt;span class="n"&gt;apiKey&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;baseURL&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;httpClient&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;
    &lt;span class="n"&gt;maxAttempts&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;baseDelay&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;Duration&lt;/span&gt;

    &lt;span class="c"&gt;// Exposed Services&lt;/span&gt;
    &lt;span class="n"&gt;Futures&lt;/span&gt;    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;FuturesService&lt;/span&gt;
    &lt;span class="n"&gt;Spot&lt;/span&gt;       &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SpotService&lt;/span&gt;
    &lt;span class="n"&gt;Options&lt;/span&gt;    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;OptionsService&lt;/span&gt;
    &lt;span class="n"&gt;ETF&lt;/span&gt;        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ETFService&lt;/span&gt;
    &lt;span class="n"&gt;Indicators&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;IndicatorsService&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configuration is handled via the functional options pattern. This makes the &lt;code&gt;NewClient&lt;/code&gt; constructor clean while allowing advanced users to inject custom &lt;code&gt;http.Transport&lt;/code&gt; layers, adjust timeouts, or enable retries.&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;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
    &lt;span class="n"&gt;coinglass&lt;/span&gt; &lt;span class="s"&gt;"github.com/tigusigalpa/coinglass-go"&lt;/span&gt;
 &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="o"&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="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&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="p"&gt;),&lt;/span&gt; &lt;span class="c"&gt;// 3 attempts, 1s initial backoff&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling Rate Limits with Grace
&lt;/h2&gt;

&lt;p&gt;The Coinglass API enforces rate limits based on your subscription tier (e.g., 30 requests/min for Hobbyist, up to 1200 for Professional). Handling &lt;code&gt;HTTP 429 Too Many Requests&lt;/code&gt; is mandatory for any serious application.&lt;/p&gt;

&lt;p&gt;Instead of forcing the user to implement their own retry loops, &lt;code&gt;coinglass-go&lt;/code&gt; handles this internally. When &lt;code&gt;WithRetry()&lt;/code&gt; is enabled, the client intercepts 429 responses. It first checks if the API provided a &lt;code&gt;Retry-After&lt;/code&gt; header. If so, it sleeps for that duration. If not, it falls back to an exponential backoff strategy (1s, 2s, 4s...).&lt;/p&gt;

&lt;p&gt;Crucially, because every method takes a &lt;code&gt;context.Context&lt;/code&gt;, the retry sleep loop is fully cancellable. If your application is shutting down, or a parent timeout is reached, the &lt;code&gt;select&lt;/code&gt; block immediately unblocks and returns &lt;code&gt;ctx.Err()&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="n"&gt;timer&lt;/span&gt; &lt;span class="o"&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;NewTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Abort retry if context is cancelled&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="c"&gt;// Proceed with next attempt&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exploring the Data: Open Interest and Funding Rates
&lt;/h2&gt;

&lt;p&gt;Let's look at how easy it is to pull actionable market data. Suppose you are building a dashboard that tracks the Open Interest (OI) and Funding Rates for Bitcoin across all exchanges.&lt;/p&gt;

&lt;p&gt;Because the SDK uses strong typing, optional query parameters are passed as pointers. To make this ergonomic, the library includes helpers like &lt;code&gt;coinglass.IntPtr()&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="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&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="c"&gt;// Fetch BTC open interest history (last 30 days, daily)&lt;/span&gt;
&lt;span class="n"&gt;oi&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Futures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenInterestHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OIHistoryParams&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;"BTC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Interval&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Limit&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;oi&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OI: %.2f USD at timestamp %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenInterestUsd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timestamp&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;If you want to hunt for arbitrage opportunities, you can pull the funding rate disparities across exchanges in a single call:&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="n"&gt;arb&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Futures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FundingRateArbitrage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FundingRateArbitrageParams&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringPtr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BTC"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;arb&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exchange: %s, Spread: %.4f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Spread&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Built for Concurrency
&lt;/h2&gt;

&lt;p&gt;Go shines in concurrent workloads, and fetching data for dozens of trading pairs sequentially is a waste of time. The &lt;code&gt;coinglass.Client&lt;/code&gt; is completely thread-safe. You can safely share a single instance across hundreds of goroutines.&lt;/p&gt;

&lt;p&gt;Here is an example of fetching open interest for multiple symbols concurrently using a &lt;code&gt;sync.WaitGroup&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="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"BTC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ETH"&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="s"&gt;"DOGE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"XRP"&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;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&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;sym&lt;/span&gt; &lt;span class="kt"&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;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c"&gt;// Safe concurrent access&lt;/span&gt;
        &lt;span class="n"&gt;data&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Futures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenInterestHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OIHistoryParams&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Interval&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Limit&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;24&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to fetch %s: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sym&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="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fetched %d hours of OI for %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;

&lt;p&gt;When dealing with financial APIs, generic errors aren't enough. You need to know exactly why a request failed. The SDK wraps all non-2xx responses in a custom &lt;code&gt;*coinglass.APIError&lt;/code&gt; struct, which contains the HTTP status code, the Coinglass-specific error code, and the raw JSON body.&lt;/p&gt;

&lt;p&gt;It also provides sentinel errors that work seamlessly with Go 1.13+ &lt;code&gt;errors.Is&lt;/code&gt; and &lt;code&gt;errors.As&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;import&lt;/span&gt; &lt;span class="s"&gt;"errors"&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Futures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SupportedCoins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&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="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrUnauthorized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid API key! Please check your COINGLASS_API_KEY."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&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="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrRateLimited&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Rate limit exceeded and retries exhausted."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;apiErr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIError&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;As&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;apiErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API rejected request: Code %s, Message: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;apiErr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;apiErr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&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;h2&gt;
  
  
  Beyond Futures: Spot, Options, and ETFs
&lt;/h2&gt;

&lt;p&gt;While Coinglass is famous for derivatives data, API v4 unified their offering. The &lt;code&gt;coinglass-go&lt;/code&gt; SDK provides full coverage for these endpoints as well.&lt;/p&gt;

&lt;p&gt;You can track Bitcoin ETF inflows:&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="n"&gt;flows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ETF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BitcoinFlowHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ETFFlowParams&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Interval&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"1w"&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;Or pull the current Crypto Fear &amp;amp; Greed Index:&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="n"&gt;fg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Indicators&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FearGreedHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FearGreedParams&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Limit&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;coinglass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntPtr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Market Sentiment: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&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;Classification&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;Building &lt;code&gt;coinglass-go&lt;/code&gt; was an exercise in keeping things simple. By avoiding third-party dependencies and leaning into Go's standard library, the result is a fast, resilient, and predictable SDK.&lt;/p&gt;

&lt;p&gt;If you are building crypto data pipelines, algorithmic trading bots, or market research tools in Go, give it a try. The source code is fully open-source under the MIT license.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/tigusigalpa/coinglass-go" rel="noopener noreferrer"&gt;tigusigalpa/coinglass-go&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contributions, issues, and pull requests are always welcome. Happy coding!&lt;/p&gt;

</description>
      <category>coinglass</category>
      <category>go</category>
      <category>bitcoin</category>
      <category>trading</category>
    </item>
    <item>
      <title>Supercharge Your Crypto and Stock Analytics with lunarcrush-go</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Thu, 09 Jul 2026 06:00:24 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/supercharge-your-crypto-and-stock-analytics-with-lunarcrush-go-4nop</link>
      <guid>https://dev.to/tigusigalpa/supercharge-your-crypto-and-stock-analytics-with-lunarcrush-go-4nop</guid>
      <description>&lt;p&gt;Are you building a trading dashboard, a market sentiment tracker, or a financial data pipeline in Go? If so, you know that gathering reliable social intelligence and market data is often a complex, messy process. You have to juggle raw HTTP requests, decode deeply nested JSON payloads, and manually handle rate limits. But what if you could access a wealth of crypto and stock social intelligence idiomatically, right where your Go code lives?&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://github.com/tigusigalpa/lunarcrush-go" rel="noopener noreferrer"&gt;&lt;strong&gt;lunarcrush-go&lt;/strong&gt;&lt;/a&gt;, a powerful, zero-dependency SDK designed to seamlessly integrate the &lt;a href="https://lunarcrush.com/en/developers" rel="noopener noreferrer"&gt;LunarCrush API v4&lt;/a&gt; into your Golang applications.&lt;/p&gt;

&lt;p&gt;In this article, we will explore why &lt;code&gt;lunarcrush-go&lt;/code&gt; is the ultimate tool for developers looking to tap into social and market intelligence, how to get started in under 60 seconds, and why its zero-dependency architecture makes it a robust choice for production workloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why LunarCrush?
&lt;/h2&gt;

&lt;p&gt;Before diving into the SDK, it is worth understanding what LunarCrush brings to the table. LunarCrush goes beyond traditional price charts. It measures what the internet is actually saying about Bitcoin, Ethereum, Tesla, and thousands of other assets. By analyzing social buzz, creator impact, and overall market sentiment across various platforms, LunarCrush provides a holistic view of the market &lt;a href="https://lunarcrush.com/en/developers" rel="noopener noreferrer"&gt;1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Whether you want to know the Galaxy Score of a specific coin, track the hourly social time-series of a stock, or get AI-generated insights on a trending topic, LunarCrush has you covered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing lunarcrush-go
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;lunarcrush-go&lt;/code&gt; library was built with one primary goal: to provide clean, typed, and production-ready access to every LunarCrush endpoint without pulling in a single third-party dependency. It speaks Go natively, meaning you do not have to wrestle with raw JSON or hand-roll your own retry loops.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;p&gt;Here is what makes &lt;code&gt;lunarcrush-go&lt;/code&gt; stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complete API Coverage:&lt;/strong&gt; The SDK supports every LunarCrush endpoint, including Coins, Stocks, Topics, Categories, Creators, Posts, Searches, AI summaries, and System changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Truly Zero Dependencies:&lt;/strong&gt; It relies entirely on the Go standard library (&lt;code&gt;net/http&lt;/code&gt;, &lt;code&gt;encoding/json&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt;, &lt;code&gt;time&lt;/code&gt; ). No &lt;code&gt;go.sum&lt;/code&gt; bloat, no dependency tree drama.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Functional Options:&lt;/strong&gt; Configure the client the idiomatic Go way, mixing and matching only what you need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context-Aware &amp;amp; Concurrent:&lt;/strong&gt; Every method accepts &lt;code&gt;context.Context&lt;/code&gt;, and the client is completely safe for use across multiple goroutines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Built-In Resilience:&lt;/strong&gt; Automatic retry with exponential backoff on HTTP 429 errors, strictly respecting the &lt;code&gt;Retry-After&lt;/code&gt; header when LunarCrush tells you to wait.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Friendly Error Handling:&lt;/strong&gt; Sentinel errors for common HTTP statuses (&lt;code&gt;401&lt;/code&gt;, &lt;code&gt;404&lt;/code&gt;, and &lt;code&gt;429&lt;/code&gt;), plus detailed &lt;code&gt;APIError&lt;/code&gt; values for everything else.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started in 60 Seconds
&lt;/h2&gt;

&lt;p&gt;Getting up and running with &lt;code&gt;lunarcrush-go&lt;/code&gt; is incredibly fast. First, drop it into your project with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/tigusigalpa/lunarcrush-go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Requires Go 1.21 or newer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, here is a tiny, complete program you can run right away to fetch the 24-hour social summary for Bitcoin and the top 10 coins by Galaxy Score:&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;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="n"&gt;lunarcrush&lt;/span&gt; &lt;span class="s"&gt;"github.com/tigusigalpa/lunarcrush-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="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&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="c"&gt;// Initialize the client with your API key and custom options&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lunarcrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;lunarcrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="o"&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="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;lunarcrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&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="p"&gt;),&lt;/span&gt; &lt;span class="c"&gt;// 3 attempts, 1s initial backoff&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// 1. Fetch 24-hour social summary for Bitcoin&lt;/span&gt;
    &lt;span class="n"&gt;topic&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Topics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bitcoin"&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bitcoin interactions (24h): %.0f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interactions24h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// 2. Fetch Top 10 coins by Galaxy Score&lt;/span&gt;
    &lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"galaxy_score"&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="n"&gt;coins&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Coins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lunarcrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CoinsListParams&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Sort&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Limit&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Desc&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Top 10 Coins by Galaxy Score:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coin&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;coins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s — Galaxy Score: %.1f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GalaxyScore&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;func&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;T&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;v&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compile and run it, and you are instantly talking to LunarCrush from Go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for Production
&lt;/h2&gt;

&lt;p&gt;When building production systems, you need reliability. &lt;code&gt;lunarcrush-go&lt;/code&gt; is designed with robust error handling and concurrency in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contexts and Concurrency
&lt;/h3&gt;

&lt;p&gt;All methods are context-first. Whether you pass &lt;code&gt;context.Background()&lt;/code&gt;, &lt;code&gt;context.WithTimeout()&lt;/code&gt;, or &lt;code&gt;context.WithCancel()&lt;/code&gt;, the SDK adapts to your flow. Furthermore, the client is safe to share across goroutines. You can fetch data for multiple coins in parallel without the overhead of creating new clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate Limits and Retry Behavior
&lt;/h3&gt;

&lt;p&gt;LunarCrush rate limits depend on your specific plan &lt;a href="https://lunarcrush.com/en/developers" rel="noopener noreferrer"&gt;1&lt;/a&gt;. Hitting a &lt;code&gt;429 Too Many Requests&lt;/code&gt; is not a panic moment with &lt;code&gt;lunarcrush-go&lt;/code&gt;. By enabling retries during client configuration, the SDK will automatically back off, doubling the wait time on each attempt, and honoring the &lt;code&gt;Retry-After&lt;/code&gt; header.&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="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lunarcrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;lunarcrush&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&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="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;
  
  
  Error Handling Done Right
&lt;/h3&gt;

&lt;p&gt;Every non-2xx response is returned as a detailed &lt;code&gt;*lunarcrush.APIError&lt;/code&gt;. For common statuses, you can easily use &lt;code&gt;errors.Is&lt;/code&gt; with sentinel errors like &lt;code&gt;lunarcrush.ErrUnauthorized&lt;/code&gt;, &lt;code&gt;lunarcrush.ErrNotFound&lt;/code&gt;, or &lt;code&gt;lunarcrush.ErrRateLimited&lt;/code&gt;. The raw response body is also preserved, making debugging weird API responses much easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Are you a PHP Developer? We have you covered!
&lt;/h2&gt;

&lt;p&gt;If your tech stack leans towards PHP, you do not have to miss out on this streamlined experience. We have also built &lt;a href="https://github.com/tigusigalpa/lunarcrush-php" rel="noopener noreferrer"&gt;&lt;strong&gt;lunarcrush-php&lt;/strong&gt;&lt;/a&gt;, a modern, framework-agnostic SDK for PHP 8.1+ &lt;a href="https://github.com/tigusigalpa/lunarcrush-php" rel="noopener noreferrer"&gt;2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just like its Go counterpart, &lt;code&gt;lunarcrush-php&lt;/code&gt; wraps every public endpoint behind a fluent, strongly-typed interface. It features readonly DTOs, typed collections, automatic rate-limit retries, and even first-class Laravel 10/11 integration out of the box.&lt;/p&gt;

&lt;p&gt;Whether you are writing Go or PHP, integrating LunarCrush has never been more elegant.&lt;/p&gt;

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

&lt;p&gt;Building robust financial and social intelligence applications requires tools that are reliable, fast, and easy to use. &lt;code&gt;lunarcrush-go&lt;/code&gt; delivers on all fronts by providing a zero-dependency, context-aware, and highly resilient SDK for the LunarCrush API.&lt;/p&gt;

&lt;p&gt;Ready to supercharge your analytics? Check out the &lt;a href="https://github.com/tigusigalpa/lunarcrush-go" rel="noopener noreferrer"&gt;lunarcrush-go repository on GitHub&lt;/a&gt;, drop a star, and start building! If you find a bug or have an idea for a better example, pull requests are always welcome.&lt;/p&gt;

&lt;p&gt;Happy building! 🚀&lt;/p&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

</description>
      <category>go</category>
      <category>lunarcrush</category>
      <category>trading</category>
      <category>bitcoin</category>
    </item>
    <item>
      <title>telegram-wallet-go: The Lightweight Go SDK for Accepting Crypto Payments in Telegram</title>
      <dc:creator>Igor</dc:creator>
      <pubDate>Thu, 16 Apr 2026 09:28:24 +0000</pubDate>
      <link>https://dev.to/tigusigalpa/telegram-wallet-go-the-lightweight-go-sdk-for-accepting-crypto-payments-in-telegram-15k6</link>
      <guid>https://dev.to/tigusigalpa/telegram-wallet-go-the-lightweight-go-sdk-for-accepting-crypto-payments-in-telegram-15k6</guid>
      <description>&lt;p&gt;Telegram has evolved far beyond a simple messaging application. With its massive user base and deep integration with the TON blockchain ecosystem, it has become a powerful platform for commerce, gaming, and decentralized applications. For developers building Telegram bots and Mini Apps, the ability to monetize by accepting cryptocurrency payments directly within the chat interface is a game-changer.&lt;/p&gt;

&lt;p&gt;The official &lt;strong&gt;Telegram Wallet Pay API&lt;/strong&gt; enables merchants to accept TON, USDT, BTC, and NOT from users seamlessly, without redirecting them outside of Telegram [1]. However, integrating a raw REST API involves handling authentication, constructing request payloads, verifying cryptographic webhook signatures, and mapping HTTP status codes to meaningful errors. Doing this from scratch in Go can be tedious and error-prone.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;&lt;a href="https://github.com/tigusigalpa/telegram-wallet-go" rel="noopener noreferrer"&gt;telegram-wallet-go&lt;/a&gt;&lt;/strong&gt;. Created by Igor Sazonov, this open-source Go SDK wraps the Wallet Pay API in a clean, idiomatic, and lightweight interface. It provides everything you need to start accepting crypto payments in your Go applications, with zero external dependencies for the core client and built-in middleware for popular web frameworks. In this article, we will explore the features, architecture, and usage of this excellent library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Choose telegram-wallet-go?
&lt;/h2&gt;

&lt;p&gt;When building backend services in Go, developers value simplicity, performance, and strong typing. The &lt;code&gt;telegram-wallet-go&lt;/code&gt; library aligns perfectly with these principles. Its key design goals include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Zero Core Dependencies:&lt;/strong&gt; The core client relies entirely on the Go standard library (&lt;code&gt;net/http&lt;/code&gt;, &lt;code&gt;crypto/hmac&lt;/code&gt;, &lt;code&gt;encoding/json&lt;/code&gt;, etc.), keeping your &lt;code&gt;go.mod&lt;/code&gt; clean and reducing the risk of supply chain vulnerabilities.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Idiomatic Go Design:&lt;/strong&gt; It uses the functional options pattern for configuration, context-aware requests (&lt;code&gt;context.Context&lt;/code&gt;), and strong typing for all API requests and responses.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Framework Integrations:&lt;/strong&gt; While the core is dependency-free, it provides optional middleware for &lt;code&gt;net/http&lt;/code&gt;, Gin, and Echo to handle webhook signature verification effortlessly.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Security by Default:&lt;/strong&gt; Webhook signature verification using HMAC-SHA256 is built-in, ensuring that you only process legitimate payment events from Wallet Pay.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Comprehensive Error Handling:&lt;/strong&gt; It maps HTTP status codes to specific error types (e.g., &lt;code&gt;AuthError&lt;/code&gt;, &lt;code&gt;RateLimitError&lt;/code&gt;), making it easy to handle different failure scenarios programmatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Installation is as simple as running a &lt;code&gt;go get&lt;/code&gt; command. The library requires Go 1.21 or higher.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/tigusigalpa/telegram-wallet-go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initializing the Client
&lt;/h3&gt;

&lt;p&gt;The library uses the functional options pattern, allowing you to configure the client cleanly. You only need your Store API Key, which you can obtain from the &lt;a href="https://t.me/WalletPay_Support_Bot" rel="noopener noreferrer"&gt;@WalletPay_Support_Bot&lt;/a&gt; on Telegram.&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;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/tigusigalpa/telegram-wallet-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;// Basic initialization&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YOUR_STORE_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Advanced initialization with custom options&lt;/span&gt;
    &lt;span class="n"&gt;customClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"YOUR_STORE_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithBaseURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://pay.wallet.tg"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt; &lt;span class="o"&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="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithHTTPClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90&lt;/span&gt; &lt;span class="o"&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="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Transport&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;MaxIdleConns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;MaxIdleConnsPerHost&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&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;h2&gt;
  
  
  Creating a Payment Order
&lt;/h2&gt;

&lt;p&gt;Creating an order is straightforward thanks to the strongly typed &lt;code&gt;CreateOrderRequest&lt;/code&gt; struct. This ensures you provide all required fields correctly.&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;"log"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/tigusigalpa/telegram-wallet-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="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YOUR_STORE_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;order&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateOrder&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;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateOrderRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MoneyAmount&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;CurrencyCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;"9.99"&lt;/span&gt;&lt;span class="p"&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="s"&gt;"Premium subscription for 1 month"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ExternalID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;             &lt;span class="s"&gt;"ORDER-12345"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c"&gt;// Your unique order ID for idempotency&lt;/span&gt;
        &lt;span class="n"&gt;TimeoutSeconds&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;         &lt;span class="m"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c"&gt;// 1 hour to pay&lt;/span&gt;
        &lt;span class="n"&gt;CustomerTelegramUserID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123456789&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c"&gt;// Restrict payment to this user&lt;/span&gt;
        &lt;span class="n"&gt;AutoConversionCurrency&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"USDT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c"&gt;// Automatically convert received funds to USDT&lt;/span&gt;
        &lt;span class="n"&gt;ReturnURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;              &lt;span class="s"&gt;"https://t.me/YourBot/YourApp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;CustomData&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;             &lt;span class="s"&gt;`{"user_id":42}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// Metadata returned in webhooks&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;// The DirectPayLink is what you send to the user&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;"Payment URL:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DirectPayLink&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;DirectPayLink&lt;/code&gt; can be used as an Inline Button URL in a bot message or opened via &lt;code&gt;Telegram.WebApp.openTelegramLink(url)&lt;/code&gt; in a Mini App [1].&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Webhooks Securely
&lt;/h2&gt;

&lt;p&gt;When a payment succeeds or fails, Wallet Pay sends a webhook to your server. Verifying the HMAC-SHA256 signature of these webhooks is critical to prevent spoofing. &lt;code&gt;telegram-wallet-go&lt;/code&gt; makes this incredibly easy by providing ready-to-use middleware.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Standard &lt;code&gt;net/http&lt;/code&gt;
&lt;/h3&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;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/tigusigalpa/telegram-wallet-go"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/tigusigalpa/telegram-wallet-go/middleware"&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="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YOUR_STORE_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/webhook/walletpay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WalletPayWebhookHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WebhookEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;events&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;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WebhookEventOrderPaid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Order %d paid: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExternalID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="c"&gt;// Fulfill the order (e.g., grant premium access)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c"&gt;// Always acknowledge receipt&lt;/span&gt;
            &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OK"&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="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using Gin Framework
&lt;/h3&gt;

&lt;p&gt;If you use Gin, you can leverage the specific middleware by building with the &lt;code&gt;gin&lt;/code&gt; tag (&lt;code&gt;go build -tags gin&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;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gin-gonic/gin"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/tigusigalpa/telegram-wallet-go"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/tigusigalpa/telegram-wallet-go/middleware"&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="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/webhook/walletpay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GinWebhookMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Retrieve parsed events from the context&lt;/span&gt;
        &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"walletpay_events"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WebhookEvent&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;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;walletpay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WebhookEventOrderPaid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c"&gt;// Handle successful payment&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;c&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="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&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;Similar middleware is available for the Echo framework as well.&lt;/p&gt;

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

&lt;p&gt;When implementing Wallet Pay in production, keep these best practices in mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Idempotency:&lt;/strong&gt; Wallet Pay may send the same webhook multiple times due to network retries. Always use the &lt;code&gt;EventID&lt;/code&gt; from the &lt;code&gt;WebhookEvent&lt;/code&gt; to ensure you process each event only once.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;External ID:&lt;/strong&gt; Use the &lt;code&gt;ExternalID&lt;/code&gt; field when creating an order as your idempotency key. If you attempt to create an order with an existing &lt;code&gt;ExternalID&lt;/code&gt;, the API will return the existing order instead of creating a duplicate.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Acknowledge Quickly:&lt;/strong&gt; Always return an HTTP 200 OK status as quickly as possible in your webhook handler. Perform heavy processing (like database updates or sending emails) asynchronously.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The &lt;code&gt;telegram-wallet-go&lt;/code&gt; library is a stellar example of how an SDK should be written in Go. It is lightweight, secure, idiomatic, and provides exactly what developers need without unnecessary bloat. Whether you are building a simple storefront bot or a complex Telegram Mini App, this library will save you hours of boilerplate code and debugging.&lt;/p&gt;

&lt;p&gt;You can check out the source code, contribute, or star the repository on GitHub: &lt;a href="https://github.com/tigusigalpa/telegram-wallet-go" rel="noopener noreferrer"&gt;tigusigalpa/telegram-wallet-go&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding, and enjoy building the next generation of crypto-enabled Telegram applications!&lt;/p&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;[1] &lt;a href="https://docs.wallet.tg/pay/" rel="noopener noreferrer"&gt;Wallet Pay API Documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>telegram</category>
      <category>wallet</category>
      <category>bitcoin</category>
    </item>
  </channel>
</rss>
