{"id":26848949,"url":"https://github.com/joaop21/exth","last_synced_at":"2025-05-02T19:19:00.137Z","repository":{"id":284416571,"uuid":"931843330","full_name":"joaop21/exth","owner":"joaop21","description":"Elixir JSON-RPC client fo EVM-compatible blockchains 📡","archived":false,"fork":false,"pushed_at":"2025-04-17T17:08:25.000Z","size":197,"stargazers_count":5,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-01T17:52:32.284Z","etag":null,"topics":["elixir","evm-chains","json-rpc"],"latest_commit_sha":null,"homepage":"https://hexdocs.pm/exth","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joaop21.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-13T00:11:45.000Z","updated_at":"2025-04-17T17:08:27.000Z","dependencies_parsed_at":"2025-03-25T19:43:17.343Z","dependency_job_id":"7fe2adff-78fc-412b-a200-4a6a53a07ec2","html_url":"https://github.com/joaop21/exth","commit_stats":null,"previous_names":["joaop21/exth"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaop21%2Fexth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaop21%2Fexth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaop21%2Fexth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joaop21%2Fexth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joaop21","download_url":"https://codeload.github.com/joaop21/exth/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252092369,"owners_count":21693355,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","evm-chains","json-rpc"],"created_at":"2025-03-30T21:23:49.290Z","updated_at":"2025-05-02T19:19:00.120Z","avatar_url":"https://github.com/joaop21.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Exth\n\nExth is an Elixir client for interacting with EVM-compatible blockchain nodes\nvia JSON-RPC. It provides a robust, type-safe interface for making Ethereum RPC\ncalls.\n\n## Features\n\n- 🔒 **Type Safety**: Comprehensive type specs and validation\n- 🔄 **Transport Agnostic**: Pluggable transport system (HTTP, WebSocket, IPC)\n- 🎯 **Smart Defaults**: Sensible defaults with full configurability\n- 🛡️ **Error Handling**: Detailed error reporting and recovery\n- 📦 **Batch Support**: Efficient batch request processing\n- 🔌 **Protocol Compliance**: Full JSON-RPC 2.0 specification support\n- ⚙️ **Dynamic Configuration**: Flexible configuration through both inline options and application config\n\n## Installation\n\nAdd `exth` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:exth, \"~\u003e 0.1.0\"},\n    # Optional dependencies:\n    # Mint for Tesla adapter\n    {:mint, \"~\u003e 1.7\"}\n  ]\nend\n```\n\n## Usage\n\nExth offers two ways to interact with EVM nodes:\n\n1. **Provider** (High-Level): Define a provider module with convenient function\n   names and no need to pass client references.\n2. **RPC Client** (Low-Level): Direct client usage with more control, requiring\n   explicit client handling.\n\n\u003c!-- tabs-open --\u003e\n\n### Provider (Recommended)\n\n```elixir\n# Basic usage with inline configuration\ndefmodule MyProvider do\n  use Exth.Provider,\n    otp_app: :your_otp_app,\n    transport_type: :http,\n    rpc_url: \"https://YOUR-RPC-URL\"\nend\n\n# Dynamic configuration through application config\n# In your config/config.exs or similar:\nconfig :your_otp_app, MyProvider,\n  rpc_url: \"https://YOUR-RPC-URL\",\n  timeout: 30_000,\n  max_retries: 3\n\n# Then in your provider module:\ndefmodule MyProvider do\n  use Exth.Provider,\n    otp_app: :your_otp_app,\n    transport_type: :http\nend\n\n# Configuration is merged with inline options taking precedence\ndefmodule MyProvider do\n  use Exth.Provider,\n    otp_app: :your_otp_app,\n    transport_type: :http,\n    rpc_url: \"https://OVERRIDE-RPC-URL\" # This will override the config value\nend\n\n# Use the provider\n{:ok, block_number} = MyProvider.block_number()\n\n{:ok, balance} = MyProvider.get_balance(\n  \"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\n  \"latest\"\n)\n\n{:ok, block} = MyProvider.get_block_by_number(\"0x1\", true)\n\n{:ok, tx_hash} = MyProvider.send_raw_transaction(\"0x...\")\n```\n\nThe Provider approach is recommended for most use cases as it provides:\n\n- ✨ Clean, intuitive function names\n- 🔒 Type-safe parameters\n- 📝 Better documentation and IDE support\n- 🎯 No need to manage client references\n- ⚙️ Flexible configuration through both inline options and application config\n\n#### Configuration Options\n\nProviders can be configured through both inline options and application config.\nInline options take precedence over application config. Here are the available options:\n\n```elixir\n# Required options\ntransport_type: :http | :custom  # Transport type to use\nrpc_url: \"https://...\"          # RPC endpoint URL\n\n# Required inline option\notp_app: :your_otp_app          # Application name for config lookup\n\n# Custom transport options\nmodule: MyCustomTransport       # Required when transport_type is :custom\n\n# Optional http options\ntimeout: 30_000                 # Request timeout in milliseconds\nheaders: [{\"header\", \"value\"}]  # Custom headers for HTTP transport\n```\n\n### RPC Client\n\n```elixir\nalias Exth.Rpc\n\n# 1. Define a client\n{:ok, client} = Rpc.new_client(\n  transport_type: :http,\n  rpc_url: \"https://YOUR-RPC-URL\"\n)\n\n# 2.1. Make RPC calls with explicit client\nrequest1 = Rpc.request(client, \"eth_blockNumber\", [])\n{:ok, block_number} = Rpc.send(client, request1)\n\n# 2.2. Or make RPC calls without a client\nrequest2 = Rpc.request(\n  \"eth_getBalance\",\n  [\"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\", \"latest\"]\n)\n{:ok, balance} = Rpc.send(client, request2)\n\n# 3. You can also send multiple requests in one call\nrequests = [request1, request2]\n{:ok, responses} = Rpc.send(client, requests)\n\n# 4. You can invert the order of the arguments and pipe\nRpc.request(\"eth_blockNumber\", [])\n|\u003e Rpc.send(client)\n\n# OR\n[request1, request2]\n|\u003e Rpc.send(client)\n```\n\nUse the RPC Client approach when you need:\n\n- 🔧 Direct control over RPC calls\n- 🔄 Dynamic method names\n- 🛠️ Custom parameter handling\n- 🎛️ Flexible client management (multiple clients, runtime configuration)\n\n\u003c!-- tabs-close --\u003e\n\n## Transport Options\n\nExth uses a pluggable transport system that supports different communication\nprotocols. Each transport type can be configured with specific options:\n\n\u003c!-- tabs-open --\u003e\n\n### HTTP Transport\n\nThe default HTTP transport is built on Tesla, providing a robust HTTP client\nwith middleware support:\n\n```elixir\n# Provider configuration\ndefmodule MyProvider do\n  use Exth.Provider,\n    transport_type: :http,\n    rpc_url: \"https://eth-mainnet.example.com\",\n    # Optional HTTP-specific configuration\n    adapter: Tesla.Adapter.Mint, # Default HTTP adapter\n    headers: [{\"authorization\", \"Bearer token\"}],\n    timeout: 30_000, # Request timeout in ms\nend\n\n# Direct client configuration\n{:ok, client} = Exth.Rpc.new(\n  transport_type: :http,\n  rpc_url: \"https://eth-mainnet.example.com\",\n  adapter: Tesla.Adapter.Mint,\n  headers: [{\"authorization\", \"Bearer token\"}],\n  timeout: 30_000\n)\n```\n\n- ✨ **HTTP** (`:http`)\n\n  - Built on Tesla HTTP client\n  - Configurable adapters (Mint, Hackney, etc.)\n  - Configurable headers and timeouts\n\n### Custom Transport\n\nImplement your own transport by creating a module and implementing the\n`Exth.Transport.Transportable` protocol:\n\n```elixir\ndefmodule MyCustomTransport do\n  # Transport struct should be whatever you need\n  defstruct [:config]\nend\n\ndefimpl Exth.Transport.Transportable, for: MyCustomTransport do\n  def new(transport, opts) do\n    # Initialize your transport configuration\n    %MyCustomTransport{config: opts}\n  end\n\n  def call(transport, request) do\n    # Handle the JSON-RPC request\n    # Return {:ok, response} or {:error, reason}\n  end\nend\n\n# Use your custom transport\ndefmodule MyProvider do\n  use Exth.Provider,\n    transport_type: :custom,\n    module: MyCustomTransport,\n    rpc_url: \"custom://endpoint\",\n    # Additional custom options\n    custom_option: \"value\"\nend\n\n# Direct client configuration\n{:ok, client} = Exth.Rpc.new_request(\n  transport_type: :custom,\n  rpc_url: \"https://eth-mainnet.example.com\",\n  module: MyCustomTransport,\n  custom_option: \"value\"\n)\n```\n\n- 🔧 **Custom** (`:custom`)\n  - Full control over transport implementation\n  - Custom state management\n\n\u003c!-- tabs-close --\u003e\n\n## Examples\n\nCheck out our [examples](https://github.com/joaop21/exth/tree/main/examples)\ndirectory for practical usage examples\n\n## Requirements\n\n- Elixir ~\u003e 1.18\n- Erlang/OTP 26 or later\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b feature/my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin feature/my-new-feature`)\n5. Create new Pull Request\n\n## License\n\nThis project is licensed under the MIT License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoaop21%2Fexth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoaop21%2Fexth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoaop21%2Fexth/lists"}