Getting Started

Introduction

Axiom is a platform for building decentralized applications. It is also a cryptocurrency. If you've used application platforms like Heroku or App Engine before, you'll find parts of this familiar. If you've developed an application using other cryptocurrencies like Ethereum before, you'll find different parts of this familiar.

Currently, Axiom primarily targets web applications built in JavaScript. If you know how to make a simple website, you'll be able to deploy a simple decentralized site. To build a more complicated application, you'll probably want to be familiar with a JavaScript framework like React or Vue.

The best way to learn about the Axiom system is to build a simple application on it. The Getting Started section of this documentation will explain how to get an account set up and how to deploy a simple static site to Axiom. The Building Applications section will explain how to build a slightly more complicated application. If you're interested in learning more, the later sections will go into more detail.

If you run into any bugs, we would really appreciate it if you report them in the GitHub issues.

Thanks for reading!

Installing the CLI

There are several different ways to interact with Axiom. Servers running the Axiom blockchain and hosting Axiom files interact with each other through the wire protocol. Application code typically interacts with Axiom through the JavaScript Axiom client. During the development process, the most convenient way to interact with Axiom is typically through the CLI.

The CLI is tested on OS X and Linux. It might also work in Windows.

You can install the CLI using npm or yarn:

npm install -g axiom-cli
yarn global add axiom-cli

Signing Up

The Axiom system stores data in two different ways. The blockchain is replicated among every machine running Axiom. Storage space there is limited, but it is very reliable. Account data, like public keys to validate users, and balances indicating how much cryptocurrency is owned by each account, is kept on the blockchain.

File storage, on the other hand, is not replicated among every machine running Axiom. Files stored on Axiom will only be replicated to a few different machines. Only hash values of file content will be stored on the blockchain.

To store any data in Axiom, you'll need to acquire some cryptocurrency, to pay for storage. To make this easier during the beta period, we have a faucet set up to give out a small amount of currency to use for development.

To sign up, first register your email here. Then run this command:

axiom signup youremail@example.com

You will have to enter a token that was emailed to you, so please use a legitimate email address.

The signup command will log in the CLI and generate a secure passphrase for you. Keep this somewhere secure.

Once you complete the signup command, you should have enough money in your account to pay for the storage used in application development. To check your account balance, run:

axiom status

Log in using the passphrase that the signup command generated. You should see output that displays a balance greater than zero. Congratulations, you now own some of the Axiom cryptocurrency!

Creating a Bucket

To understand file storage on Axiom, it is helpful to understand the concepts of buckets and hosting providers. An Axiom bucket is similar to an Amazon S3 bucket. A bucket can hold many files, and a user can own many buckets. Each bucket has a capacity for how many files it can store. One of your buckets could hold the static content for a web application you are deploying, or it could hold the data for an application you are using, or it could hold any sort of files you would like to keep in decentralized storage.

Data on the blockchain is replicated among every machine running the blockchain. Data in a bucket is only replicated among a few different hosting providers. This makes it relatively inexpensive to store data in a bucket. With the developer faucet, you should have enough to pay for about 100 megabytes of bucket storage.

Let's make a bucket. Pick a unique name like "my-cool-example". Names are unique, so if you pick this exact one it probably won't work because someone else will have gone through the example. Bucket names also have to be at least six letters long.

First, we have to create a new bucket. Let's pick a size of 1 megabyte because we're just using this as an example:

axiom create-bucket my-cool-example 1

You should see output that looks like:

created bucket: www:my-cool-example
Bucket: www:my-cool-example
  owner: 0x32bbd7e6ffc293bd586953bc2d66aa4f30269e4ab7a084d29f94d2a1fdab9858fe19
  size: 1
  magnet: magnet:?xt=urn:btih:4185e95e9f147f2f245da786f79a6e7ca3e5455b&dn=.&tr=ws%3A%2F
  4 providers

The www is the application tag for this bucket. It defaults to www which indicates that these files are intended for web access.

The create-bucket command will automatically allocate the bucket to a few hosting providers for you. Either the owner of a bucket or the hosting provider can deallocate the bucket at any time. As a developer, you might want to reallocate a bucket elsewhere if a hosting provider is providing a poor service level. As a hosting provider, you might want to deallocate a bucket if you discover that it is hosting content that you don't want to be hosting. Providers are never forced to host particular files.

Storing Files

Now that you've created a bucket, you can upload files to that bucket. The simplest way to upload files is to use the axiom upload command to upload the contents of a local directory to a bucket:

mkdir ~/my-cool-example
cd ~/my-cool-example
echo "hello decentralized world" > index.html
axiom upload . my-cool-example

When you run an upload, the files are transferred to the hosting providers via WebTorrent. The blockchain only contains a single hash value encoded in a magnet URI, so that other users can verify the contents of the bucket.

Using the WebTorrent protocol for uploads and downloads means that the costs of file hosting for providers don't scale linearly according to the number of downloads, and can be amortized into the base cost of the bucket. When you update the blockchain, you do have to pay a fee. The CLI by default attempts to use a 0-fee transaction. Since the blockchain uses the Stellar Consensus Protocol, hopefully these fees can stay very small over time even as blockchain usage increases.

Now that we've uploaded content to a bucket, let's download it to make sure it's working.

mkdir ~/testdir
cd ~/testdir
axiom download my-cool-example

You should be able to inspect the newly-created ~/testdir directory to see a copy of your uploaded file.

Decentralized Websites

Any bucket can be used to upload and download files. Since we stored this data in a bucket with the application tag www, the convention is that these files are meant to be used as a website, with the root page in index.html.

Normal websites are based on a domain name which is found through a centralized domain name registry. Since an Axiom application is based on files that are available through decentralized buckets, it can be accessed without depending on this centralized registry.

The easiest way to do so is to install the Axiom Authenticator Chrome extension. When you install this extension, domains that end with .axiom will be loaded from an Axiom bucket, rather than doing a DNS lookup and loading content over HTTP. .axiom isn't a real domain, so this shouldn't cause conflict with any normal websites.

After installing the authenticator, check out your site in your browser, with a URL like:

http://my-cool-example.axiom/

Replace my-cool-example with your bucket name, and you should see the contents of your index.html, loaded as a website.

Congratulations! You have now distributed your "hello world" application on the decentralized web. Read on to learn about building more complicated applications that interact with user data.

Building an Application

A React Example

There are two logical parts to an Axiom application. First, the application code is a bundle of JavaScript, HTML, and other files that works like a website. This code is stored in a bucket owned by the app developer. Second, there is user data, which contains things like blog posts, messages, or profile pictures. This data is stored in separate buckets, each owned by a different user. An application interacts with user data via the JavaScript Axiom API.

When building an Axiom application, you can use any framework that outputs JavaScript and HTML. This includes tools like React, Angular, and Vue. You can't use server-side frameworks like Rails, Django, or PHP.

This section of the documentation will demonstrate the basics of Axiom apps, using an example app written with React. We won't do anything too React-centric, so if you don't know React, hopefully you can follow along and figure out how this would work in your favorite framework.

The easiest way to follow along is to clone this GitHub repository with our example React app:

git clone git@github.com:axiom-org/react-example.git

There isn't much in this repo. To make it, we ran create-react-app, ran npm install axiom-api, and removed some stuff we aren't going to use. App.js is the file that contains all the code we're going to write. To start out, it contains:

import React from "react";
import Axiom from "axiom-api";

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.axiom = new Axiom();

    this.state = {
      message: null
    };
  }

  async onClick() {
    this.setState({ message: "click!" });
  }

  render() {
    if (this.state.message) {
      return <p>{this.state.message}</p>;
    }

    return <button onClick={() => this.onClick()}>Click Me</button>;
  }
}

All this app does so far is display a button that says "Click Me", and when you click it, it displays the message "click!". To serve it on localhost, run:

npm start

It's a useful shell for experimenting with the Axiom API, because we can edit the onClick function to do different things.

If you're familiar with React, this app should look pretty straightforward. The only parts that relate to Axiom are constructing the Axiom object:

import Axiom from "axiom-api";

this.axiom = new Axiom();

The Axiom object provides access to the Axiom API. You only need to create one of them at a time, and it's a good idea to only create one because it will automatically cache some things for you. We can create it in the constructor of App here because the App component only gets rendered once.

The following sections will show you different things you can do with this axiom object.

Logging In

The first thing we can get from the Axiom API is an identity. This is useful so that we can store information specific to the person who is currently using the application.

We can use the axiom.getPublicKey method to access the current user. Try replacing the onClick logic with this:

async onClick() {
  let key = await this.axiom.getPublicKey();
  this.setState({ message: `your public key is ${key}` });
}

When you run npm start, the application will reload whenever you change its code, so if you already have it running, you don't need to run it again.

Now, clicking the button will attempt to log the user in. Try it out, with the Axiom Authenticator Chrome extension installed. You should see a popup asking for permission. If you haven't configured the extension yet, you will need to enter your private key, which you can get by running axiom get-private-key:

axiom get-private-key

The extension will ask you to set a password, so you don't need to enter your private key every time you are authenticating a website. Once you accept the permission, the getPublicKey method in the application will return, and the application will display your public key.

It's important that getPublicKey is an async function. By default, the extension doesn't share any information about users with websites. The user has to grant permission each time. This might take some time, so the method can't return immediately, and has to be asynchronous. However, if the user has already granted this permission, getPublicKey will return immediately.

Permissions are not stored globally. They are only stored in the extension. That means users need to give permission to an application separately for every browser they are using to access it. This is similar to regular password-protected application access - you typically need to log in separately on each device. Because the extension stores the authentication keys, applications no longer have the ability to authenticate as a user once the user closes the web page.

One important thing to note is that since getPublicKey may open a popup to ask for information, you should call it as a direct response to a user action like clicking a button. This will ensure that browsers show the popup instead of hiding it.

Storing User Data

By default, all data stored on Axiom is unencrypted. Applications can retrieve arbitrary data stored in buckets via the API.

Buckets are specified by two strings, the application tag and the bucket name. Each of these must be at least six letters long, to discourage collisions. One useful pattern is to pick a unique name for your application, and use that as the application tag. Then, you can pick a user-specific name for the bucket name, like the user's public key, or a username they pick themselves.

Let's say we're building an application that keeps track of a counter for each user. We'll name it counter, and have each user store their data in a bucket with the counter application tag, and a bucket name of their own public key.

We can use the axiom.getBucket method to check if a bucket exists already, and we can use the axiom.createBucket method to create a bucket on behalf of the user. Try replacing the onClick logic in our application with this:

async onClick() {
  let key = await this.axiom.getPublicKey();
  let bucket = await this.axiom.getBucket("counter", key);
  if (bucket) {
    this.setState({ message: "the bucket already exists" });
  } else {
    await this.axiom.createBucket("counter", key, 1);
    this.setState({ message: "created a bucket" });
  }
}

The same pattern for permissions operates here as with login. Since data is public, getting a bucket requires no permissions. Creating a new bucket does require the user to grant permission. If this permission has not already been granted, an extension popup opens so that the user can grant permission.

Try running this application and clicking the button. The first time you run this code, it should discover that the bucket does not exist, prompt you for permission, and create the bucket for you. The next time you run this code, it should tell you that the bucket already exists.

While buckets are often created by individual applications, the user maintains control. For example, you can delete this bucket from the CLI when you are done with this sample application. To list all buckets you are using, run axiom get-buckets:

axiom get-buckets

Then you can delete any you are not using with axiom delete-bucket:

axiom delete-bucket <full-name>

This is similar to how applications are installed on a PC hard drive. A well-behaved application will offer ways to uninstall or clean itself up. But even when an application is not well-behaved, you can delete the folder that its files are installed into. The permission model here also prevents some forms of bad behavior. An application can write to the bucket or buckets that the user gives it permission for, but an application doesn't have the ability to modify all the files you own.

Modifying User Data

The Axiom API provides a number of ways to manipulate files in a bucket. For our example application, let's say we are storing a counter in a file named counter.json. It's a simple JSON object with a single key named counter. So if our counter value is 5, our file would have the contents:

{"counter":5}

Once we have a bucket, we can use bucket.getJSON and bucket.setJSON to manipulate the contents of files. Once we're done modifying the bucket, we can use bucket.upload to save the result.

Once you've created a bucket according to the previous section, try replacing the onClick logic in our application with this:

async onClick() {
  let key = await this.axiom.getPublicKey();
  let bucket = await this.axiom.getBucket("counter", key);
  let data = await bucket.getJSON("counter.json");
  if (!data) {
    data = { counter: 1 };
  } else {
    data = { counter: data.counter + 1 };
  }
  bucket.setJSON("counter.json", data);
  this.setState({ message: "setting data to " + JSON.stringify(data) });
  await bucket.upload();
  this.setState({ message: "upload complete" });
}

Try running this application and clicking the button. The first time you run this code, it should discover that there is no file storing a counter, set its value to 1, and upload the new data. If you reload the page and click the button again, it should pick up the new value of the counter and increase it again.

Developers aren't required to use JSON to store application data. The plain file data is also available via the bucket.getFile and bucket.setFile methods.

Putting It All Together

So far, we've investigated areas of the API by building an application with a single button. We can put it all together to make an application that will do all of this: get permission from the user to log in, create a bucket to store data, store a counter in that bucket, and increment the counter every time a button is clicked.

Combining this functionality together, we can get something like this:

import React from "react";
import Axiom from "axiom-api";

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.axiom = new Axiom({ verbose: true });

    this.state = {
      publicKey: null,
      loadingMessage: null,
      bucket: null,
      counter: null
    };

    this.login = this.login.bind(this);
    this.createBucket = this.createBucket.bind(this);
    this.increment = this.increment.bind(this);
  }

  async login() {
    let publicKey = await this.axiom.getPublicKey();
    this.setState({
      publicKey: publicKey
    });

    this.setState({
      loadingMessage: "loading your data..."
    });

    let bucket = await this.axiom.getBucket("counter", this.state.publicKey);
    if (bucket) {
      console.log("got bucket:", bucket);
      let data = await bucket.getJSON("counter.json");
      console.log("got data:", data);
      let counter = data ? data.counter : 0;
      this.setState({
        bucket: bucket,
        counter: counter,
        loadingMessage: null
      });
    } else {
      console.log("failed to get bucket");
      this.setState({
        loadingMessage: null
      });
    }
  }

  async createBucket() {
    this.setState({
      loadingMessage: "creating a bucket..."
    });
    console.log("creating a bucket");
    await this.axiom.createBucket("counter", this.state.publicKey, 1);
    await this.login();
  }

  async increment() {
    this.setState({
      loadingMessage: `saving counter = ${this.state.counter + 1}...`
    });
    this.state.bucket.setJSON("counter.json", {
      counter: this.state.counter + 1
    });
    console.log("uploading...");
    await this.state.bucket.upload();
    console.log("upload complete");
    this.setState({
      waiting: false,
      loadingMessage: null,
      counter: this.state.counter + 1
    });
  }

  render() {
    if (this.state.loadingMessage) {
      return <p>{this.state.loadingMessage}</p>;
    }

    if (!this.state.publicKey) {
      return <button onClick={this.login}>Log In</button>;
    }

    if (!this.state.bucket) {
      return <button onClick={this.createBucket}>Create a Counter</button>;
    }

    return (
      <div>
        <p>Counter: {this.state.counter}</p>
        <button onClick={this.increment}>count!</button>
      </div>
    );
  }
}

If you'd like to play around with this sample application, check out the code on GitHub, or you can clone it locally with:

git clone git@github.com:axiom-org/counter.git

This example has only touched on a small part of what is possible. To learn more, check out the API reference.

The Axiom system is also fully open source, with new functionality being frequently added. If there is an application you want to build, but it doesn't seem like the API currently supports some functionality you need, it might be a good candidate for future work. You can check out the API source code if you're interested in contributing, or you can submit a GitHub issue if you would like to encourage other people to develop the feature you need.

Thanks for reading this far, and good luck building applications!

API Reference

API Overview

This section provides a reference to all of the JavaScript API methods.

The Axiom API is distributed through the axiom-api npm package. You can install it using npm or yarn:

npm install axiom-api
yarn add axiom-api

We recommend that you use the async/await pattern when developing Axiom applications. Most of the sample code will be written in that style. It isn't mandatory, though. When a function is documented as being async, and you call it without using await, it will return a Promise object that you can use from code that isn't using async/await.

Currently, axiom-api only supports a browser environment. It's designed for running applications where the user is only authorizing specific operations. However, anything that can be done through the JS API can also be done through HTTP or through the CLI. If you're interested in this, you may find it useful to check out the API source code or the CLI source code

new Axiom()

import Axiom from "axiom-api";
let axiom = new Axiom();

All access to the Axiom JavaScript API happens through an Axiom object. You only need to create this once for your application. It will internally handle caching and permissions.

The constructor can take an options object, with the fields:

  • network can be set to "local" to use a development blockchain you are running locally on your own machine. The default is to use the public network.

  • verbose can be set to true to log debugging messages to the console. By default Axiom shouldn't log unless there is an error.

If you have a question about the Axiom class that isn't answered by this documentation, you can check out its source code on GitHub.

axiom.createBucket

async axiom.createBucket(app, name, size)

createBucket creates a new bucket on behalf of the user of the application. A common pattern is that users can browse content for an application without creating a bucket to store their application files, but once they want to create an account, or create content of some kind, they create a bucket to store it.

app is a string that identifies the application, and name is a string that identifies this particular bucket. If your application has usernames, it's reasonable to use usernames as bucket names, and to create the bucket at the time that the user is creating an account. Since the data is controlled by the end user who owns the bucket, different applications can share the same app string to interact with the same data.

size is the size of the bucket in megabytes.

For example, if we wrote an app named blogpost to let people make blog posts, we could let a user named BradNelson create an account with:

await axiom.createBucket("blogpost", "BradNelson", 0);

The first call to this method will cause a popup in the extension, to ask the user for authorization to create the bucket.

If you want to manipulate this bucket in the CLI later, the full name of the bucket is the app name and the bucket name joined by a colon. So in this case, it would be blogpost:BradNelson.

createBucket throws an error if bucket creation does not succeed. This usually means the bucket already exists, your connection to the internet failed, or the user rejected this request.

If you have a question about the Bucket class that isn't answered by this documentation, you can check out its source code on GitHub.

axiom.getAccount

async axiom.getAccount(publicKey)

getAccount fetches account data for a public key. The account is a plain object with the fields:

  • owner is the public key who owns the account

  • sequence is the sequence id of the last operation authorized by this account. The blockchain resolution logic uses this to prevent replay attacks.

  • balance is the current balance of this account.

  • storage is how much total bucket size, in megabytes, this account is currently storing.

No permissions are needed to fetch account data for a public key, since the information is public.

axiom.getBucket

async axiom.getBucket(app, name)

getBucket retrieves a Bucket object that contains information for a bucket from the blockchain. It does not download the actual contents of the bucket. If you want that, you should subsequently call bucket.download.

app and name are the same parameters used when the bucket was created.

No permissions are needed to get a bucket, since the data is public data.

axiom.getPublicKey

async axiom.getPublicKey()

getPublicKey gets the current user's public key from the extension.

For privacy, the extension won't just tell every application your public key. The first time this is called, a popup opens that asks the user if they would like to grant this website knowledge of their public key. In order to make sure this popup is shown, getPublicKey should be called directly in response to the user interacting with an input element, like a login button.

If the user has already granted access, however, getPublicKey will return successfully without further authorization.

bucket.download

async bucket.download()

download() downloads the entire contents of a bucket to the local browser.

You don't necessarily need to call this, because the asynchronous getter functions like getJSON will download as they need to anyway. But if you know your application is going to want this information later, you can call download() as soon as the bucket is acquired, to begin the download immediately.

bucket.getFile

async bucket.getFile(path)

getFile returns a standard File object given a path within a bucket.

If the file isn't available locally, this will download the file and then return it. If the bucket has already been entirely downloaded with bucket.download, the file will be returned from the cache.

In general, a File object is the most standard form for files in a browser, but it isn't very convenient for most common operations. If you're interacting with application data, you may find it more helpful to use bucket.getJSON or bucket.getText.

bucket.getJSON

async bucket.getJSON(path)

getJSON returns the result of JSON-parsing the file stored at path. It will throw an error if that file doesn't contain valid JSON. It will return null if that file does not exist.

This is often more useful for accessing application data than using getFile to access a file directly. But it's just a simple wrapper around getFile.

bucket.getPaths

async bucket.getPaths()

getPaths returns a list of paths for every file stored in this bucket.

Directories aren't stored recursively in a bucket. They are just stored as long pathnames that happen to have slashes in them. So if your bucket contains two directories, each with two files, you might get a response to getPaths that looks like:

[ "foo/1.txt", "foo/2.txt", "bar/1.txt", "bar/2.txt" ]

bucket.getText

async bucket.getText(path, encoding)

getText returns the text content for a file stored at path. If you don't provide an encoding, the file is assumed to be utf-8.

This is often more useful for accessing application data than using getFile to access a file directly. But it's just a simple wrapper around getFile.

bucket.magnet

bucket.magnet

This field provides access to a magnet URI for the WebTorrent protocol. You can use this to download the current contents of a bucket if you don't want to use this API.

In most cases, you should be able to use getters on the Bucket object instead of using the magnet directly.

Don't write to this field.

bucket.name

bucket.name

This field provides the full name of the bucket, which is the app name and the bucket name separated by a colon.

This field is mostly useful for debugging. You usually won't need to use it in code because all the data access for the bucket can happen via the Bucket object. But if you want to inspect a bucket using the CLI, you'll need its full name.

Don't write to this field.

bucket.owner

bucket.owner

This field provides access to the public key of the user that owns this bucket.

In particular, if axiom.getPublicKey() doesn't match, then this user won't be able to write to this bucket.

bucket.setFile

bucket.setFile(path, file)

setFile stores a file into a bucket at path.

This function only changes the content of the bucket locally. You have to call bucket.upload to upload the new contents of the bucket when you are ready to save it.

In general, a File object is the most standard form for files in a browser, but it isn't very convenient for most common operations. If you're storing application data, you may find it more helpful to use bucket.setJSON or bucket.setText.

bucket.setJSON

bucket.setJSON(path, object)

setJSON JSON-encodes a provided object, and stores the result in a file at path.

Like setFile, this function only changes the content of the bucket locally. You have to call bucket.upload to upload the new contents of the bucket when you are ready to save it.

It's a good idea to end files with .json when they are storing JSON data. It isn't required, though.

bucket.setText

bucket.setText(path, text)

setText stores the provided text in a file at path.

It only supports utf-8 encoding. If you want to use a different encoding, or if you want to store nontextual data, try using setFile instead.

You have to call bucket.upload to upload the new contents of the bucket when you are ready to save it.

It's a good idea to end files with .txt when they are storing plain text data. It isn't required, though.

bucket.size

bucket.size

This field tells you the size of the bucket, in megabytes. It is always an integer; you can't have buckets that are half a megabyte in size.

The size of a bucket is an upper limit. Usually the total size of all files in a bucket is smaller than the bucket size.

Don't write to this field.

bucket.upload

async bucket.upload()

upload uploads new content to a bucket.

The typical usage pattern is first to fetch information for a bucket using bucket.download(). Then, the user can access data in the bucket with getters like bucket.getJSON and modify it with setters like bucket.setJSON. Once some modifications to the bucket have been made, it can be uploaded with bucket.upload.

CLI Reference

CLI Overview

This section provides a reference to all of the CLI commands.

The CLI is distributed through the axiom-cli npm package. You can install the CLI using npm or yarn:

npm install -g axiom-cli
yarn global add axiom-cli

The general format of CLI commands is:

axiom command-name argument-1 argument-2 [...]

If you run a command with no arguments, you'll get a brief usage message.

Anything that can be done through the CLI can also be done through HTTP. The CLI source code is on GitHub so if some of its behavior is insufficiently documented, or it's unclear how to achieve it programmatically, you can check there.

Several of the CLI commands use bucket names. A bucket name can optionally have an application tag on it. If the application tag is omitted, the application is considered to be www. For example, in the bucket name foobar:bazqux, foobar is the application tag and bazqux is the name of the bucket itself.

axiom alloc

axiom alloc [bucketName] [providerID]

Allocates a bucket to a particular provider.

Usually you don't have to run this command because create-bucket allocates a bucket for you. This is useful if there is a specific set of providers that you would like to use.

This command is a synonym of axiom allocate for those who prefer to avoid typing.

axiom allocate

axiom allocate [bucketName] [providerID]

The long form of axiom alloc for those who prefer spelling out whole words.

axiom config

Used in one of two ways:

axiom config alpha
axiom config local

axiom config switches the CLI between using different networks. There are two Axiom networks that it can talk to. alpha is the developer network that you can deploy things to and have them be accessible to the outside world. local is a network that you are running on your own machine, for testing purposes.

By default, this talks to the alpha network. You don't have to use this command unless you are working on the Axiom software itself.

axiom create-bucket

axiom create-bucket [bucketName] [size]

Creates a new bucket, finds some providers with enough available space to host this bucket, and allocates the bucket to those providers.

If you want to allocate the bucket yourself, use axiom create-unallocated-bucket instead, which won't automatically allocate the bucket.

size is denominated in megabytes.

axiom create-provider

axiom create-provider [capacity]

This command creates a provider object on the blockchain. The blockchain will assign it a unique numerical id, and users creating a bucket can use it to specify which provider they want to store their files.

You usually wouldn't want to do this yourself. If you want to run a file hosting server, try the instructions for running hserver. When you run an hserver, it automatically creates a provider object if it doesn't have one already. This CLI command is useful if you are writing your own file hosting logic, or if you are debugging a buggy hserver.

axiom create-unallocated-bucket

axiom create-unallocated-bucket [bucketName] [size]

axiom create-unallocated-bucket creates a new bucket with no providers. This is useful if you wish to use a specific set of providers, and manually allocate them yourself later. But usually you just want to use axiom create-bucket.

size is denominated in megabytes.

axiom dealloc

axiom dealloc [bucketName] [providerID]

Deallocates a bucket from a particular provider.

You might want to run this command if you own a bucket, and a particular provider has been performing poorly. Axiom doesn't enforce an SLA through the blockchain mechanisms itself. So if a provider is not providing good service, you can deallocate your buckets from one provider and reallocate them to another.

You also might want to run this commend if you are running a hosting provider, and you discover a particular bucket contains content that you don't want to be hosting. Perhaps it's illegal in your jurisdiction, or you just don't like it for whatever reason. Deallocating the bucket means you aren't obliged to host it any more.

This command is a synonym of axiom deallocate for those who prefer not to spell out whole words.

axiom deallocate

axiom deallocate [bucketName] [providerID]

The long form of axiom dealloc for those who prefer to type more.

axiom delete-bucket

axiom delete-bucket [name]

If you created a bucket that you don't want any more, you can use this command to delete it.

axiom deploy

axiom deploy [directory] [bucketName]

This command is a synonym of axiom upload.

It's a bit more logical to have the commands named "upload" and "download" so that the names are kind of parallel to each other. But when you're building an application, the typical usage pattern is to write some code, and then when you're ready, you deploy that code to production to have the application go live. So it's kind of common to call this "deploy" in a command-line tool. Anyway, in a fit of indecisiveness we left both commands in the CLI.

axiom download

axiom download [bucketName]

Downloads the contents of a bucket to a newly-created directory with the same name as the bucket, in the current working directory.

axiom generate

axiom generate

This command generates a keypair file containing both private key and public key that correspond to a passphrase. You don't need this just to use the CLI, but you will need this keypair file in order to run your own hosting server. If you're interested in running your own hosting server, check out the instructions here.

axiom get-account

axiom get-account [username]

Shows the account data for a user. This includes information like their account balance and how much total storage they are using.

axiom get-bucket

axiom get-bucket [name]

Shows information about a bucket. In particular this tells you the magnet URI you need to access the bucket's content, the owner of the bucket, and which providers are responsible for the bucket.

axiom get-buckets

axiom get-buckets [owner=<id>] [provider=<id>]

Shows which buckets match a query. You can either find buckets owned by a particular user, or buckets that are being hosted by a particular provider.

If you don't provide any arguments, this command will show you all buckets that you own.

axiom get-private-key

axiom get-private-key

Prints out your private key. The CLI stores login data in ~/.axiom/config.json, so this could already be accessed there. This CLI command just makes it a bit more convenient.

axiom get-provider

axiom get-provider [id]

Shows information about a particular provider. In particular this tells you the owner of the provider, and which buckets this provider is hosting.

axiom get-providers

axiom get-providers [owner=<user>] [bucket=<name>] [available=<amount>] [id=<id>]

Shows which providers match a query. You can find buckets owned by a particular user, which providers are hosting a particular bucket, or providers with a certain amount of available space.

axiom login

axiom login

Asks you for a passphrase and tells you your corresponding public key.

Most commands, if you aren't already logged in, will just ask you to log in. So you usually don't need to run this explicitly.

There is no associated "username" with your passphrase. The passphrase is all you need to gain access to the user account. The string username in the Axiom system is just the public key associated with your keypair. So your passphrase by itself should be a very unique phrase.

The CLI stores its configuration information in ~/.axiom/config.json. The login command will populate that file, and subsequent commands will use the information in that file. You should keep this file secure, just like you would with your SSH keys.

If you regret logging in, you can use axiom logout to log back out.

axiom logout

axiom logout

Logs you out. After you log out, none of your keypair information is left on the local machine.

Once you log out, you might want to use axiom login to log back in.

axiom send

axiom send [recipient] [amount]

Sends currency to another user.

The recipient here is the public key that is provided when you initially generate an account, or that is included on bucket and provider information. Public keys start with 0x.

Be careful when you use this, because when you send currency, there is no way to undo the transaction.

axiom set-magnet

axiom set-magnet [bucketName] [magnet]

Updates the magnet URI stored for a particular bucket.

The file hosting software also runs WebTorrent trackers which will create magnet URIs for bucket contents. So normally you wouldn't want to set a magnet directly; you would just use the axiom upload command which does this for you.

This is useful if you have created a magnet URI in some other way and want your bucket to use it instead. Like if you have a WebTorrent tracker with some extra functionality that you want. But these are somewhat obscure cases, so it's rare you would want to do this.

axiom signup

axiom signup

During the developer beta, we are giving away currency so that people can build applications on the system. This command is how you collect. First, sign up for the newsletter. Then, run this command. You will have to enter a token that gets emailed to you, and then you will have an account set up with enough currency to build an application.

Maybe it's a little tacky to make you sign up for the newsletter to try this out. Sorry! At least it makes it a little harder for spammers to take up all the capacity in the system.

Speaking of spammers... when we launch the main net, we plan to keep running applications operational and transfer them from the testnet to the main net. But we don't plan to keep account balances in place. So there's no point in spamming this system to get hundreds of developer accounts. The only thing this currency is getting you is capacity on the development system.

axiom upload

axiom upload [directory] [bucketName]

Uploads the contents of a local directory to a decentralized bucket. The bucket must already have been created, and you must own it.

axiom version

axiom version

Prints out which version of the Axiom CLI you are using.

If you are debugging an Axiom CLI installation issue, you might also find axiom which to be useful.

axiom which

axiom which

This command just tells you where the file is that is running the CLI itself. It is useful if you are trying to debug a problem about how exactly your CLI is installed.