NAME

App::cryp::Role::Exchange - Role for interacting with an exchange

VERSION

This document describes version 0.012 of App::cryp::Role::Exchange (from Perl distribution App-cryp-exchange), released on 2021-05-26.

DESCRIPTION

This role describes the common API for interacting with an exchange that all App::cryp::Exchange::* modules follow.

ENVELOPED RESULT

All methods, unless specified otherwise, must return enveloped result:

[$status, $reason, $payload, \%extra]

This result is analogous to an HTTP response; in fact $status mostly uses HTTP response codes. $reason is analogous to HTTP status message. $payload is the actual content (optional if $status is error status). %extra is optional and analogous to HTTP response headers to specify flags or attributes or other metadata.

Some examples of enveloped result:

[200, "OK", ["BTC/USD", "ETH/BTC"]]
[404, "Not found"]

For more details about enveloped result, see Rinci::function.

PROVIDED METHODS

to_canonical_currency

Usage:

$xchg->to_canonical_currency($cur) => str

Convert native currency code to canonical/standardized currency code. Canonical codes are listed in CryptoCurrency::Catalog.

to_native_currency

Usage:

$xchg->to_native_currency($cur) => str

Convert canonical/standardized currency code to exchange-native currency code. Canonical codes are listed in CryptoCurrency::Catalog.

to_canonical_pair

Usage:

$xchg->to_canonical_pair($pair) => str

to_native_pair

Usage:

$xchg->to_native_pair($pair) => str

REQUIRED METHODS

cancel_order

Usage:

$xchg->cancel_order(%args) => [$status, $reason, $payload, \%resmeta]

Cancel an open order.

Known arguments (* marks required arguments):

  • type*

  • pair*

  • order_id*

create_limit_order

Usage:

$xchg->create_limit_order(%args) => [$status, $reason, $payload, \%resmeta]

Create a buy/sell order at a specified price.

Specifying size (amount). When creating a buy order, some exchanges require specifying size (amount) in quote currency, e.g. in BTC/USD pair when buying USD we specify how much in USD we want to buy bitcoin. Some other exchanges require specifying size in base currency, i.e. how many bitcoins we want to buy. Similarly, when creating a sell order, some exchanges require specifying base currency while others want size in quote currency. For flexibility, this role method requires drivers to accept either base_size or quote_size.

Minimum_size. Exchanges have a minimum order size (amount) either in the quote currency or base currency or both. Check the min_base_size and min_quote_size field returned by "list_pairs". The API server typically will reject order when size is less than the minimum.

Maximum precision. Exchanges also have restriction on the maximum precision of price (see the quote_increment field returned by "list_pairs". For example, if quote_increment for BTC/USD pair is 0.01 then the price 7000.51 is okay but 7000.526 is too precise. Some exchanges will reject overprecise price, but some exchanges will simply round the price to the nearest precision (e.g. 7000.524 to 7000.52) and some exchanges might round up or down or truncate etc. For more consistent behavior, this role method requires drivers to round down the overprecise price to the nearest quote increment.

Known arguments (* marks required arguments):

  • pair*

    String. Pair.

  • type*

    String. Either "buy" or "sell".

  • price*

    Number. Price in the quote currency. If price is too precise, will be rounded down to the nearest precision (see method description above for details).

  • base_size

    Specify amount to buy/sell in base currency. For example, in BTC/USD pair, we specify how many bitcoins to buy or sell.

    You have to specify one of base_size or quote_size, but not both.

  • quote_size

    Specify amount to buy/sell in quote currency. For example, in BTC/USD pair, we specify how many USD to buy or sell bitcoins.

    You have to specify one of base_size or quote_size, but not both.

Some specific exchanges might require more credentials or arguments (e.g. api_passphrase on Coinbase Pro); please check with the specific drivers.

When successful, payload in response must be a hashref which contains at least these keys: type ("buy" or "sell"), pair, order_id (str, usually a number, can also be a UUID, etc), price (number, actual price of the order), base_size (actual size of the order, specified in base currency), quote_size (actual size of the order, specified in quote currency), status (current status of the order).

get_ticker

Usage:

$xchg->get_ticker(%args) => [$status, $reason, $payload, \%resmeta]

Get a pair's last 24h price and volume information.

Known arguments (* marks required arguments):

  • pair*

When successful, payload in response must be a hashref which contains at least these keys: high (last 24h highest price), low (last 24h lowest price), last (last trade's price), volume (last 24h volume, in base currency), buy (last buy price), sell (last sell price). Optional keys: open (last 24h opening/first price), , quote_volume (last 24h volume in quote currency). Hash may contain additional keys. All prices are in quote currency, all volumes (except C>quote_volume>) are in base currency.

data_canonical_currencies

Should return a hashref, a mapping between exchange-native currency codes to canonical/standardized currency codes. All codes must be in uppercase. Used to convert native pair/currency to canonical or vice versa. See also: "data_reverse_canonical_currencies".

data_native_pair_is_uppercase

Should return an integer value, 1 if native pair is in uppercase, 0 if native pair is in lowercase. Used to convert native pair/currency to canonical or vice versa.

data_native_pair_separator

Should return a single-character string. Used to convert native pair/currency to canonical or vice versa.

data_reverse_canonical_currencies

Returns hashref, a mapping of canonical/standardized currency codes to exchange native codes. All codes must be in uppercase. Used to convert native pair/currency to canonical or vice versa.

This role already provides an implementation, which calculates the hashref by reversing the hash returned by /"data_canonical_currencies" and caching the result in the instance's _reverse_canonical_currencies key. Driver can provide its own implementation.

See also: "data_canonical_currencies".

get_order

Usage:

$xchg->get_order(%args) => [$status, $reason, $payload, \%resmeta]

Get information about a specific order.

Note that some exchanges do not allow getting information on order that is already cancelled or fulfilled.

Identifying order. Some exchanges provide UUID to uniquely identify an order, while some others provide a regular integer and you must also specify pair and type to uniquely identify a particular order. For consistency, this rule method requires driver to ask for all of type, pair, and order_id.

Known arguments (* marks required arguments):

  • type*

  • pair*

  • order_id*

Payload must be a hashref with at least these keys:

  • type

  • pair

  • order_id

  • create_time

    Float. Unix epoch.

  • status

    Str. E.g.: open, cancelled, done. TODO: standardize status across exchanges.

  • base_size

  • quote_size

  • filled_base_size

    Number.

  • filled_quote_size

    Number.

get_order_book

Usage:

$xchg->get_order_book(%args) => [$status, $reason, $payload, \%resmeta]

Method should return this payload:

{
    buy => [
        [100, 10 ] , # price, amount
        [ 99,  4.1], # price, amount
        ...
    ],
    sell => [
        [101  , 5.5], # price, amount
        [101.5, 3.1], # price, amount
        ...
    ],
}

Buy (bid, purchase) records must be sorted from highest price to lowest price. Sell (ask, offer) records must be sorted from lowest price to highest.

Known arguments (* marks required arguments):

  • pair*

    String. Pair.

list_balances

Usage:

$xchg->list_balances(%args) => [$status, $reason, $payload, \%resmeta]

List account balances.

Method must return enveloped result. Payload must be an array of hashrefs. Each hashref must contain at least these keys:

  • currency

    fiat_or_crpytocurrency.

  • available

    num, balance available for trading i.e. buying.

  • hold

    num, balance that is currently held so not available for trading, e.g. balance currently tied on open buy orders.

  • total

    num, usually available + hold but can also be available + hold + pending_withdraw. Generally not very useful.

Hashref may also contain these keys: pending_withdraw (balance that is in the process of withdrawn to another exchange, etc), unconfirmed (balance that has recently been deposited but unconfirmed e.g. has not reached the minimum number of confirmations).

Hashref may contain additional keys.

list_open_orders

Usage:

$xchg->list_open_orders(%args) => [$status, $reason, $payload, \%resmeta]

List all open orders.

Known arguments (* marks required arguments):

  • pair

    Only list orders for a specific pair. It's a good idea to include this argument if you only need a specific pair's orders because in some exchanges you need a separate API call for each pair.

When successful, the payload in response is an array of orders. Each order information is a hashref, with the following required keys (see "get_order" for more details on each key):

  • type

  • pair

  • order_id

  • price

  • create_time

  • status

  • base_size

  • filled_base_size

  • filled_quote_size

Note: the role does not require the orders to be returned in a specific sorting order.

list_pairs

Usage:

$xchg->list_pairs(%args) => [$status, $reason, $payload, \%resmeta]

List all pairs available for trading.

Method must return enveloped result. Payload must be an array containing pair names (except when detail argument is set to true, in which case method must return array of records/hashrefs (see the detail option for more details).

Pair names must be in the form of <currency1>/<currency2> where currency1 is the base currency and must be a cryptocurrency code while <currency2> is the quote currency and can be a fiat or cryptocurrency code. Some example pair names: BTC/USD, ETH/BTC.

Known arguments (* marks required arguments):

  • native

    Boolean. Default 0. If set to 1, method must return pair codes and currency codes in native exchange form instead of canonical/standardized form.

  • detail

    Boolean. Default 0. If set to 1, method must return array of records/hashrefs instead of just array of strings (pair names).

    Record must contain these keys:

    • name

      str, pair name. Affected by the "native" option.

    • base_currency

      str. Affected by the "native" option.

    • quote_currency

      str. Affected by the "native" option.

    • min_base_size

      Num, minimum order amount in the base currency.

    • min_quote_size

      Num, minimum order amount in the quote currency.

    • quote_increment

      Num, minimum increment in the quote currency.

    Record can contain additional keys.

new

Usage:

new(%args) => obj

Constructor. Known arguments (* marks required arguments):

  • api_key

    String. Required.

  • api_secret

    String. Required.

Some specific exchanges might require more credentials or arguments (e.g. api_passphrase on GDAX); please check with the specific drivers.

Method must return object.

HOMEPAGE

Please visit the project's homepage at https://metacpan.org/release/App-cryp-exchange.

SOURCE

Source repository is at https://github.com/perlancar/perl-App-cryp-exchange.

BUGS

Please report any bugs or feature requests on the bugtracker website https://github.com/perlancar/perl-App-cryp-exchange/issues

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

SEE ALSO

AUTHOR

perlancar <perlancar@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2021, 2018 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.