├── .formatter.exs ├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── config └── config.exs ├── lib ├── ipfs-api.ex └── ipfs-connection.ex ├── mix.exs ├── mix.lock └── test ├── ipfs_api_test.exs └── test_helper.exs /.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}", "priv/repo/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /_build 2 | /deps 3 | /docs 4 | /doc 5 | erl_crash.dump 6 | *.ez 7 | /.elixir_ls/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: elixir 2 | elixir: 1.0.4 3 | otp_release: 4 | - 17.1 5 | sudo: false 6 | before_script: 7 | - mix deps.get --only test 8 | script: 9 | - mix compile 10 | - mix test 11 | after_script: 12 | - cd $TRAVIS_BUILD_DIR 13 | - MIX_ENV=docs mix deps.get 14 | - MIX_ENV=docs mix inch.report -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Zohaib Rauf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/zabirauf/elixir-ipfs-api.svg)](https://travis-ci.org/zabirauf/elixir-ipfs-api) [![Inline docs](http://inch-ci.org/github/zabirauf/elixir-ipfs-api.svg)](http://inch-ci.org/github/zabirauf/elixir-ipfs-api) 2 | 3 | Current Version: [v0.1.0](https://hex.pm/packages/elixir_ipfs_api) 4 | 5 | # Elixir-Ipfs-Api 6 | 7 | The Elixir library that is used to communicate with the IPFS REST endpoint. 8 | 9 | ![elixir_ipfs_api](https://cloud.githubusercontent.com/assets/1104560/11236786/a332e2ba-8d90-11e5-9b21-e37a0931130c.png) 10 | 11 | # [Documentation](http://hexdocs.pm/elixir_ipfs_api/) 12 | 13 | The documentation is posted at [hexdocs](http://hexdocs.pm/elixir_ipfs_api/) 14 | 15 | # How to use it 16 | 17 | ## 1. Add the library to mix.exs 18 | 19 | The package is published on [Hex](https://hex.pm). Add the elixir\_ipfs\_api as follow 20 | 21 | ``` 22 | defp deps do 23 | [ 24 | ... 25 | {:elixir_ipfs_api, "~> 0.1.0"} 26 | ... 27 | ] 28 | end 29 | ``` 30 | 31 | ## 2. Start the IPFS Daemon 32 | 33 | Start the IPFS daemon by running the following in terminal 34 | 35 | ``` 36 | $ ipfs daemon 37 | ``` 38 | 39 | This will start the ipfs daemon with the API endpoint at localhost:5001. 40 | If you want to start the API endpoint at a different address then add to the config 41 | 42 | ``` 43 | $ ipfs config Addresses.API /ipfs/127.0.0.1/tcp/5007 44 | ``` 45 | 46 | ## 3. Create the IpfsConnection in your code 47 | 48 | The [IpfsConnection](http://hexdocs.pm/elixir_ipfs_api/IpfsConnection.html) entity contains the information of the IPFS API endpoint. By default it will try to connect to http://localhost:5001/api/v0 49 | 50 | ``` 51 | conn = %IpfsConnection{host: "127.0.0.1", base: "api/v0", port: 5007} 52 | ``` 53 | 54 | ## Examples 55 | 56 | ### Adding content to IPFS 57 | 58 | 59 | ``` 60 | iex> conn = %IpfsConnection{} 61 | iex> IpfsApi.add(conn, "Hello world from Elixir-Ipfs-Api") 62 | {:ok, 63 | %{"Hash" => "QmTcCZJEW1kUcYU1bKQk9SMGRsTisMMWXuxJ1AQerHwyaA", 64 | "Name" => "QmTcCZJEW1kUcYU1bKQk9SMGRsTisMMWXuxJ1AQerHwyaA"}} 65 | ``` 66 | 67 | ### Getting content from IPFS 68 | 69 | 70 | ``` 71 | iex> conn = %IpfsConnection{} 72 | iex> IpfsApi.get(conn, "QmTcCZJEW1kUcYU1bKQk9SMGRsTisMMWXuxJ1AQerHwyaA") 73 | <<81, 109, 84, 99, 67, 90, 74, 69, 87, 49, 107, 85, 99, 89, 85, 49, 98, 75, 81, 107, 57, 83, 77, 71, 82, 115, 84, 105, 115, 77, 77, 87, 88, 117, 120, 74, 49, 65, 81, 101, 114, 72, 119, 121, 97, 65, 0, 0, 0, 0, ...>> 74 | ``` 75 | 76 | # TODO 77 | - [] Add stream for adding & getting files to and from IPFS 78 | - [] Add a pool to request from multiple different IPFS nodes 79 | 80 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | use Mix.Config 4 | 5 | # This configuration is loaded before any dependency and is restricted 6 | # to this project. If another project depends on this project, this 7 | # file won't be loaded nor affect the parent project. For this reason, 8 | # if you want to provide default values for your application for third- 9 | # party users, it should be done in your mix.exs file. 10 | 11 | # Sample configuration: 12 | # 13 | # config :logger, :console, 14 | # level: :info, 15 | # format: "$date $time [$level] $metadata$message\n", 16 | # metadata: [:user_id] 17 | 18 | # It is also possible to import configuration files, relative to this 19 | # directory. For example, you can emulate configuration per environment 20 | # by uncommenting the line below and defining dev.exs, test.exs and such. 21 | # Configuration from the imported file will override the ones defined 22 | # here (which is why it is important to import them last). 23 | # 24 | # import_config "#{Mix.env}.exs" 25 | -------------------------------------------------------------------------------- /lib/ipfs-api.ex: -------------------------------------------------------------------------------- 1 | defmodule IpfsApi do 2 | @moduledoc """ 3 | The module is a client to call into IPFS REST endpoint. 4 | 5 | """ 6 | 7 | @type request_ret :: {:ok, Dict.t()} | {:error, String.t()} 8 | 9 | ######################### 10 | ##### Basic Commands###### 11 | ######################### 12 | 13 | @spec add(IpfsConnection.t(), binary) :: request_ret 14 | def add(_connection, <<>>) do 15 | {:error, "No content provided"} 16 | end 17 | 18 | @doc ~S""" 19 | Add an object to ipfs 20 | 21 | ## Examples 22 | 23 | IpfsApi.add(%IpfsConnection{}, "Hello World") 24 | """ 25 | @spec add(IpfsConnection.t(), binary) :: request_ret 26 | def add(connection, content) do 27 | connection 28 | |> create_url("/add") 29 | |> request_send_file(content) 30 | end 31 | 32 | @doc ~S""" 33 | Get an ipfs object 34 | 35 | ## Examples 36 | 37 | IpfsApi.get(%IpfsConnection{}, "QmUXTtySmd7LD4p6RG6rZW6RuUuPZXTtNMmRQ6DSQo3aMw") 38 | """ 39 | @spec get(IpfsConnection.t(), String.t()) :: {:ok, binary} | {:error, String.t()} 40 | def get(connection, multihash) do 41 | connection 42 | |> create_url("/get/#{multihash}") 43 | |> request_get_file 44 | end 45 | 46 | @doc ~S""" 47 | Show ipfs object data 48 | """ 49 | @spec cat(IpfsConnection.t(), String.t()) :: request_ret 50 | def cat(connection, multihash) do 51 | connection 52 | |> request(:get, "/cat", [multihash]) 53 | end 54 | 55 | @doc ~S""" 56 | List links from an object 57 | """ 58 | @spec ls(IpfsConnection.t(), String.t()) :: request_ret 59 | def ls(connection, multihash) do 60 | connection 61 | |> request(:get, "/ls", [multihash]) 62 | end 63 | 64 | @doc ~S""" 65 | List hashes of links from an object 66 | """ 67 | @spec refs(IpfsConnection.t(), String.t()) :: request_ret 68 | def refs(connection, multihash) do 69 | connection 70 | |> request(:get, "/refs", [multihash]) 71 | end 72 | 73 | ######################### 74 | # Data Structure Commands# 75 | ######################### 76 | 77 | @doc ~S""" 78 | Print information of a raw IPFS block 79 | """ 80 | @spec block_stat(IpfsConnection.t(), String.t()) :: request_ret 81 | def block_stat(connection, multihash) do 82 | connection 83 | |> request(:get, "/block/stat", [multihash]) 84 | end 85 | 86 | @doc ~S""" 87 | Get a raw IPFS block 88 | """ 89 | @spec block_get(IpfsConnection.t(), String.t()) :: request_ret 90 | def block_get(connection, multihash) do 91 | connection 92 | |> request(:get, "/block/get", [multihash]) 93 | end 94 | 95 | @doc ~S""" 96 | Stores input as an IPFS block 97 | """ 98 | @spec block_put(IpfsConnection.t(), binary) :: request_ret 99 | def block_put(connection, content) do 100 | connection 101 | |> create_url("/block/put") 102 | |> request_send_file(content) 103 | end 104 | 105 | @doc ~S""" 106 | The raw bytes in an IPFS object 107 | """ 108 | @spec object_data(IpfsConnection.t(), String.t()) :: request_ret 109 | def object_data(connection, multihash) do 110 | connection 111 | |> request(:get, "/object/data", [multihash]) 112 | end 113 | 114 | @doc ~S""" 115 | The links pointed to by the specified object 116 | """ 117 | @spec object_links(IpfsConnection.t(), String.t()) :: request_ret 118 | def object_links(connection, multihash) do 119 | connection 120 | |> request(:get, "/object/links", [multihash]) 121 | end 122 | 123 | @doc ~S""" 124 | Get and serialize the DAG node name by `multihash` 125 | """ 126 | @spec object_get(IpfsConnection.t(), String.t()) :: request_ret 127 | def object_get(connection, multihash) do 128 | connection 129 | |> request(:get, "/object/get", [multihash]) 130 | end 131 | 132 | @doc ~S""" 133 | Stores `content` as a DAG object 134 | """ 135 | @spec object_put(IpfsConnection.t(), binary) :: request_ret 136 | def object_put(connection, content) do 137 | connection 138 | |> create_url("/block/put") 139 | |> request_send_file(content) 140 | end 141 | 142 | @doc ~S""" 143 | Get stats for the DAG node name by `key` 144 | """ 145 | @spec object_stat(IpfsConnection.t(), String.t()) :: request_ret 146 | def object_stat(connection, key) do 147 | connection 148 | |> request(:get, "/object/stat", [key]) 149 | end 150 | 151 | @doc ~S""" 152 | Create a new merkledag object base on an existing one 153 | """ 154 | @spec object_patch(IpfsConnection.t(), String.t()) :: request_ret 155 | def object_patch(connection, key) do 156 | connection 157 | |> request(:get, "/object/patch", [key]) 158 | end 159 | 160 | @doc ~S""" 161 | List directory content for `path` 162 | """ 163 | @spec file_ls(IpfsConnection.t(), String.t()) :: request_ret 164 | def file_ls(connection, path) do 165 | connection 166 | |> request(:get, "/file/ls", [path]) 167 | end 168 | 169 | ######################### 170 | #### Advanced Commands#### 171 | ######################### 172 | 173 | @doc ~S""" 174 | Resolve the value of the `name` 175 | TODO: Add ability to resolve recursively 176 | """ 177 | @spec resolve(IpfsConnection.t(), String.t()) :: request_ret 178 | def resolve(connection, name) do 179 | connection 180 | |> request(:get, "/resolve", [name]) 181 | end 182 | 183 | @doc ~S""" 184 | Publish the `ipfs_path` to your identity name 185 | """ 186 | @spec name_publish(IpfsConnection.t(), String.t()) :: request_ret 187 | def name_publish(connection, ipfs_path) do 188 | connection 189 | |> request(:get, "/name/publish", [ipfs_path]) 190 | end 191 | 192 | @doc ~S""" 193 | Resolve the value of `name` 194 | """ 195 | @spec name_resolve(IpfsConnection.t(), String.t()) :: request_ret 196 | def name_resolve(connection, name \\ "") do 197 | connection 198 | |> request(:get, "/name/resolve", [name]) 199 | end 200 | 201 | @doc ~S""" 202 | Resolve the DNS link 203 | TODO: Add ability to resolve recursively 204 | """ 205 | @spec dns(IpfsConnection.t(), String.t()) :: request_ret 206 | def dns(connection, domain_name) do 207 | connection 208 | |> request(:get, "/dns", [domain_name]) 209 | end 210 | 211 | @doc ~S""" 212 | Pins objects to local storage 213 | """ 214 | @spec pin_add(IpfsConnection.t(), String.t()) :: request_ret 215 | def pin_add(connection, ipfs_path) do 216 | connection 217 | |> request(:get, "/pin/add", [ipfs_path]) 218 | end 219 | 220 | @doc ~S""" 221 | Remove the pinned object from local storage 222 | TODO: Add ability to resolve recursively 223 | """ 224 | @spec pin_rm(IpfsConnection.t(), String.t()) :: request_ret 225 | def pin_rm(connection, ipfs_path) do 226 | connection 227 | |> request(:get, "/pin/rm", [ipfs_path]) 228 | end 229 | 230 | @doc ~S""" 231 | List objects pinned to local storage 232 | """ 233 | @spec pin_ls(IpfsConnection.t()) :: request_ret 234 | def pin_ls(connection) do 235 | connection 236 | |> request(:get, "/pin/ls", []) 237 | end 238 | 239 | @doc ~S""" 240 | Perform a grabage collection sweep on the repo 241 | """ 242 | @spec repo_gc(IpfsConnection.t()) :: request_ret 243 | def repo_gc(connection) do 244 | connection 245 | |> request(:get, "/repo/gc", []) 246 | end 247 | 248 | ######################### 249 | #### Network Commands##### 250 | ######################### 251 | 252 | @doc ~S""" 253 | Gets the information about the specified `peer_id` 254 | """ 255 | @spec id(IpfsConnection.t(), String.t()) :: request_ret 256 | def id(connection, peer_id \\ "") do 257 | connection 258 | |> request(:get, "/id", [peer_id]) 259 | end 260 | 261 | @doc ~S""" 262 | Gets the list of bootstrap peers 263 | """ 264 | @spec bootstrap(IpfsConnection.t()) :: request_ret 265 | def bootstrap(connection) do 266 | connection 267 | |> request(:get, "/bootstrap", []) 268 | end 269 | 270 | @doc ~S""" 271 | Add peers to the bootstrap list 272 | """ 273 | @spec bootstrap_add(IpfsConnection.t(), String.t()) :: request_ret 274 | def bootstrap_add(connection, peer) do 275 | connection 276 | |> request(:get, "/bootstrap/add", [peer]) 277 | end 278 | 279 | @doc ~S""" 280 | Remoes peers from the bootstrap list 281 | """ 282 | @spec bootstrap_rm(IpfsConnection.t(), String.t()) :: request_ret 283 | def bootstrap_rm(connection, peer) do 284 | connection 285 | |> request(:get, "/bootstrap/rm", [peer]) 286 | end 287 | 288 | @doc ~S""" 289 | List peers with open connections 290 | """ 291 | @spec swarm_peers(IpfsConnection.t()) :: request_ret 292 | def swarm_peers(connection) do 293 | connection 294 | |> request(:get, "/swarm/peers", []) 295 | end 296 | 297 | @doc ~S""" 298 | List known addresses 299 | """ 300 | @spec swarm_addr(IpfsConnection.t()) :: request_ret 301 | def swarm_addr(connection) do 302 | connection 303 | |> request(:get, "/swarm/addrs", []) 304 | end 305 | 306 | @doc ~S""" 307 | Open connection to given `address` 308 | """ 309 | @spec swarm_connect(IpfsConnection.t(), String.t()) :: request_ret 310 | def swarm_connect(connection, address) do 311 | connection 312 | |> request(:get, "/swarm/connect", [address]) 313 | end 314 | 315 | @doc ~S""" 316 | Close connection to give address 317 | """ 318 | @spec swarm_disconnect(IpfsConnection.t(), String.t()) :: request_ret 319 | def swarm_disconnect(connection, address) do 320 | connection 321 | |> request(:get, "/swarm/disconnect", [address]) 322 | end 323 | 324 | @doc ~S""" 325 | Add an address filter 326 | """ 327 | @spec swarm_filters_add(IpfsConnection.t(), String.t()) :: request_ret 328 | def swarm_filters_add(connection, address) do 329 | connection 330 | |> request(:get, "/swarm/filters/add", [address]) 331 | end 332 | 333 | @doc ~S""" 334 | Remove an address filter 335 | """ 336 | @spec swarm_filters_rm(IpfsConnection.t(), String.t()) :: request_ret 337 | def swarm_filters_rm(connection, address) do 338 | connection 339 | |> request(:get, "/swarm/filters/rm", [address]) 340 | end 341 | 342 | @doc ~S""" 343 | Run a FindClosesPeers query through the DHT 344 | """ 345 | @spec dht_query(IpfsConnection.t(), String.t()) :: request_ret 346 | def dht_query(connection, peer_id) do 347 | connection 348 | |> request(:get, "/dht/query", [peer_id]) 349 | end 350 | 351 | @doc ~S""" 352 | Run a FundProviders quest through the DHT 353 | """ 354 | @spec dht_findprovs(IpfsConnection.t(), String.t()) :: request_ret 355 | def dht_findprovs(connection, key) do 356 | connection 357 | |> request(:get, "/dht/findprovs", [key]) 358 | end 359 | 360 | @doc ~S""" 361 | Run a FindPeer query through the DHT 362 | """ 363 | @spec dht_findpeer(IpfsConnection.t(), String.t()) :: request_ret 364 | def dht_findpeer(connection, peer_id) do 365 | connection 366 | |> request(:get, "/dht/findpeer", [peer_id]) 367 | end 368 | 369 | @doc ~S""" 370 | Run a GetValue query through the DHT 371 | """ 372 | @spec dht_get(IpfsConnection.t(), String.t()) :: request_ret 373 | def dht_get(connection, key) do 374 | connection 375 | |> request(:get, "/dht/get", [key]) 376 | end 377 | 378 | @doc ~S""" 379 | Run a PutValue query through the DHT 380 | """ 381 | @spec dht_put(IpfsConnection.t(), String.t(), String.t()) :: request_ret 382 | def dht_put(connection, key, value) do 383 | connection 384 | |> request(:get, "/dht/put", [key, value]) 385 | end 386 | 387 | @doc ~S""" 388 | Send echo request packets to IPFS hosts 389 | TODO: Add ability to give number of count 390 | """ 391 | @spec ping(IpfsConnection.t(), String.t()) :: request_ret 392 | def ping(connection, peer_id) do 393 | connection 394 | |> request(:get, "/ping", [peer_id]) 395 | end 396 | 397 | ######################### 398 | ###### Tool Commands###### 399 | ######################### 400 | 401 | # def config() do 402 | @doc ~S""" 403 | Gets the content of the config file 404 | """ 405 | @spec config_show(IpfsConnection.t()) :: request_ret 406 | def config_show(connection) do 407 | connection 408 | |> request(:get, "/config/show", []) 409 | end 410 | 411 | # def config_replace() do 412 | 413 | @doc ~S""" 414 | Gets the IPFS version 415 | """ 416 | @spec version(IpfsConnection.t()) :: request_ret 417 | def version(connection) do 418 | connection 419 | |> request(:get, "/version", []) 420 | end 421 | 422 | ######################### 423 | #### Helper Functions##### 424 | ######################### 425 | 426 | defp create_url(connection, path) do 427 | "#{connection.host}:#{connection.port}/#{connection.base}#{path}" 428 | end 429 | 430 | defp request_send_file(url, content) do 431 | url 432 | |> (fn url -> 433 | boundary = "a831rwxi1a3gzaorw1w2z49dlsor" 434 | 435 | HTTPoison.request(:post, url, create_add_body(content, boundary), [ 436 | {"Content-Type", "multipart/form-data; boundary=#{boundary}"} 437 | ]) 438 | end).() 439 | |> process_response 440 | end 441 | 442 | defp request_get_file(url) do 443 | url 444 | |> HTTPoison.get() 445 | |> process_response(& &1) 446 | end 447 | 448 | defp request(connection, req_type, path, args) do 449 | request_internal(connection, req_type, create_url(connection, path), args) 450 | end 451 | 452 | defp request_internal(_connection, :post, url, %{} = args) do 453 | url 454 | |> HTTPoison.post(Poison.encode(args)) 455 | |> process_response 456 | end 457 | 458 | defp request_internal(_connection, :get, url, []) do 459 | HTTPoison.get(url) 460 | |> process_response 461 | end 462 | 463 | defp request_internal(connection, :get, url, [h | t]) do 464 | request(connection, :get, "#{url}/#{h}", t) 465 | end 466 | 467 | defp process_response(response) do 468 | process_response(response, &Poison.decode/1) 469 | end 470 | 471 | defp process_response( 472 | {:ok, %HTTPoison.Response{status_code: 200, body: body}}, 473 | deserializationFunc 474 | ) do 475 | deserializationFunc.(body) 476 | end 477 | 478 | defp process_response( 479 | {:ok, %HTTPoison.Response{status_code: code, body: body}}, 480 | _deserializationFunc 481 | ) do 482 | {:error, "Error status code: #{code}, #{body}"} 483 | end 484 | 485 | defp process_response({:error, %HTTPoison.Error{reason: reason}}, _deserializationFunc) do 486 | {:error, reason} 487 | end 488 | 489 | defp create_add_body(content, boundary) do 490 | "--#{boundary}\r\nContent-Type: application/octet-stream\r\nContent-Disposition: file; \r\n\r\n#{ 491 | content 492 | } #{boundary}" 493 | end 494 | end 495 | -------------------------------------------------------------------------------- /lib/ipfs-connection.ex: -------------------------------------------------------------------------------- 1 | defmodule IpfsConnection do 2 | @moduledoc """ 3 | The IpfsConnection is used to create the struct that contains connection 4 | information of IPFS rest endpoint. By default it connects to `http://localhost:5001/api/v0` 5 | """ 6 | 7 | @type t :: %IpfsConnection{host: String.t(), base: String.t(), port: pos_integer} 8 | defstruct host: "localhost", base: "api/v0", port: 5001 9 | end 10 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule ElixirIpfsApi.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :elixir_ipfs_api, 7 | version: "0.1.1", 8 | elixir: "~> 1.6", 9 | description: "An elixir client library for the IPFS API", 10 | build_embedded: Mix.env() == :prod, 11 | start_permanent: Mix.env() == :prod, 12 | deps: deps() 13 | ] 14 | end 15 | 16 | # Configuration for the OTP application 17 | # 18 | # Type `mix help compile.app` for more information 19 | def application do 20 | [applications: [:logger, :httpoison]] 21 | end 22 | 23 | # Dependencies can be Hex packages: 24 | # 25 | # {:mydep, "~> 0.3.0"} 26 | # 27 | # Or git/path repositories: 28 | # 29 | # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} 30 | # 31 | # Type `mix help deps` for more examples and options 32 | defp deps do 33 | [ 34 | {:httpoison, "~> 1.0"}, 35 | {:poison, "~> 3.1", override: true}, 36 | {:inch_ex, "~> 0.5", only: :docs}, 37 | {:ex_doc, "~> 0.18.3", only: :dev}, 38 | {:earmark, "~> 1.2", only: :dev} 39 | ] 40 | end 41 | 42 | defp package do 43 | [ 44 | maintainers: ["Zohaib Rauf"], 45 | license: ["MIT"], 46 | links: %{ 47 | "GitHub" => "https://github.com/zabirauf/elixir-ipfs-api", 48 | "Docs" => "http://hexdocs.pm/elixir_ipfs_api" 49 | } 50 | ] 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{ 2 | "certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, 3 | "earmark": {:hex, :earmark, "1.2.5", "4d21980d5d2862a2e13ec3c49ad9ad783ffc7ca5769cf6ff891a4553fbaae761", [:mix], [], "hexpm"}, 4 | "ex_doc": {:hex, :ex_doc, "0.18.3", "f4b0e4a2ec6f333dccf761838a4b253d75e11f714b85ae271c9ae361367897b7", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, 5 | "hackney": {:hex, :hackney, "1.12.1", "8bf2d0e11e722e533903fe126e14d6e7e94d9b7983ced595b75f532e04b7fdc7", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, 6 | "hoedown": {:git, "git://github.com/hoedown/hoedown.git", "ca4609d56a77378ef9cf6dd3caff3aec006ecce9", []}, 7 | "httpoison": {:hex, :httpoison, "1.1.0", "497949fb62924432f64a45269d20e6f61ecf35084ffa270917afcdb7cd4d8061", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, 8 | "idna": {:hex, :idna, "5.1.1", "cbc3b2fa1645113267cc59c760bafa64b2ea0334635ef06dbac8801e42f7279c", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, 9 | "inch_ex": {:hex, :inch_ex, "0.5.3", "39f11e96181ab7edc9c508a836b33b5d9a8ec0859f56886852db3d5708889ae7", [:mix], [{:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: false]}]}, 10 | "markdown": {:git, "git://github.com/devinus/markdown.git", "9b3beaf69a9b9c6450526c41d591a94d2eedf1e8", []}, 11 | "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, 12 | "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, 13 | "parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"}, 14 | "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, 15 | "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, 16 | "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5", "2e73e068cd6393526f9fa6d399353d7c9477d6886ba005f323b592d389fb47be", [:make], []}, 17 | "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}, 18 | } 19 | -------------------------------------------------------------------------------- /test/ipfs_api_test.exs: -------------------------------------------------------------------------------- 1 | defmodule IpfsApi.Test do 2 | use ExUnit.Case, async: true 3 | doctest IpfsApi 4 | end 5 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | --------------------------------------------------------------------------------