Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CCXT v1.17 – The Ocean DEX integration! #3476

Closed
kroitor opened this issue Jul 24, 2018 · 10 comments
Closed

CCXT v1.17 – The Ocean DEX integration! #3476

kroitor opened this issue Jul 24, 2018 · 10 comments

Comments

@kroitor
Copy link
Member

kroitor commented Jul 24, 2018

Hi, everyone!

We have integrated The Ocean – the first Decentralized Exchange supported in CCXT!
Please, welcome! )

The Ocean is a 0x-based DEX. You can find more info about the preflight test that is going on here:

The Ocean will be opening doors to worldwide trading on August 15, 2018!

We invite everyone to test it and report whatever issues and bugs you may find. The CCXT Dev Team is here to assist if you have difficulties with it. Also all feedback from our community as well as your proposals, feature requests and considerations would be very much appreciated!

This change is a significant addition to the codebase, therefore we are bumping up our minor version number as well. Support for The Ocean is added in CCXT version 1.17 or higher.

Key Notes

The 0x and DEX trading flow differs from archaic centralized exchanges, here's the list of key things:

  • Instantiation is done in a usual way:
import ccxt
theocean = ccxt.theocean()  # for public requests only
import ccxt

# for public requests and private history

theocean = ccxt.theocean({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_SECRET',
})  
  • The fetchBalance() call requires a list of currency codes to query the balance as well as the walletAddress to query for a particular wallet.
import ccxt

# for public requests, private history and balance

theocean = ccxt.theocean({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_SECRET',
    'walletAddress': '0xa5ADFC364f66065416025199b7C3d8E2162aF5cd', # "0x"-prefixed hexstring
})

balance = theocean.fetch_balance({'codes': ['WETH', 'ZRX', 'REP']})
  • The createOrder() call requires a walletAddress and a privateKey as well to place orders on behalf of the wallet.
import ccxt

# for public requests, private history, balance and for creating orders
# walletAddress and privateKey are both "0x"-prefixed hexstrings

theocean = ccxt.theocean({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_SECRET',
    'walletAddress': '0xa5ADFC364f66065416025199b7C3d8E2162aF5cd',  
    'privateKey': '0xe4f40d465efa94c98aec1a51f574329344c772c1bce33be07fa20a56795fdd09',
})

balance = theocean.fetch_balance({'codes': ['ZRX', 'WETH']})
marketOrderReply = theocean.createOrder('ZRX/WETH', 'market', 'buy', 1.0)
  • The 0x relayer protocol imposes a new flow and requires a couple of newly introduced exceptions from createOrder() call.

Depending on the type of the order and depending on market conditions (current state of the orderbook), a request for a limit order can result in one or two orders being placed. The first order will represent the part that can be filled immediately (taken) from the orderbook. The second order will represent the remaining amount that cannot be filled from the orderbook right away and thus makes it to the orderbook and stays there as a maker.

  • A limit order request can result in:

    • just one maker order being filled (taken by you from the orderbook, where you are the taker, taking or filling someones' maker order)
    • just one maker order being placed (made to the orderbook, where you are the maker, when the order is not immediately fillable)
    • two orders being executed, one is your immediately-fillable taker, the other is your not-immediately-fillable maker

  • createOrder() can accept an optional makerOrTaker parameter that can be used to enforce maker-only or taker-only orders. If the makerOrTaker is not set, the createOrder call will return both parts in the following structure:
{
    'info': info,  # the request-response sequence with the exchange, as is
    'taker': takerOrder,  # an order structure for the filled taker order, if any
    'maker': makerOrder,  # an order structure for the placed maker order, if any
}
  • If the makerOrTaker parameter is set, the createOrder will return a standard order response (one order).
# will run as a normal marketprice taker order
marketOrderReply = theocean.createOrder('ZRX/WETH', 'market', 'buy', 1.0, undefined, { 'makerOrTaker': 'taker' })

# will throw InvalidOrder
marketOrderReply = theocean.createOrder('ZRX/WETH', 'market', 'buy', 1.0, undefined, { 'makerOrTaker': 'maker' })  

# will throw OrderImmediatelyFillable if the order is completely fillable from the opposite side of the orderbook
limitOrderReply = theocean.createOrder('ZRX/WETH', 'limit', 'buy', 1.0, 0.0025, { 'makerOrTaker': 'maker' })  

# will throw OrderNotFillable if the order is not fillable from the opposite side of the orderbook
limitOrderReply = theocean.createOrder('ZRX/WETH', 'limit', 'buy', 1.0, 0.0025, { 'makerOrTaker': 'taker' })  
  • Python 2 is now deprecated and we will drop support for it soon, because of this: https://pythonclock.org/

  • All of the above will soon be added to the Manual and thoroughly documented.

We will be happy to answer all your questions regarding the technical side of the integration and usage of The Ocean with CCXT.

Thank you!

@viktorius007
Copy link

Thank you kroitor for the development.

What are the security implications of using a private key in this manner and could you offer some guidelines on best practices for protecting the key. Is the key encrypted in transit?

@kroitor
Copy link
Member Author

kroitor commented Jul 25, 2018

@viktorius007 it is not sent towards the exchange or anywhere, it is used to sign orders asymmetrically with elliptic curve cryptographic functions and therefore the privateKey always stays on your side and is not transmitted anywhere. So this is as safe as your host system is. We will also add deferred/delegated signing for unlocked accounts, to be used with ethnode-services, JSONRPC and remote signing providers.

@viktorius007
Copy link

thank you, that's very reassuring

@frosty00
Copy link
Member

frosty00 commented Jul 25, 2018

Is it possible to just sign an order (smart contract method call) or other transaction and publish it as an ethereum transaction to another server like etherscan or etherchain instead of interacting with the the ocean's ethereum node, in true decentralised fashion? That way if theocean wanted to maliciously block a transaction they would be unable to do so.

I propose we write a module to encode and publish ethereum transactions. There are already many libraries to work with hex and rlp transactions. I.E. https://github.com/ethereumjs/ethereumjs-tx

@kroitor
Copy link
Member Author

kroitor commented Jul 25, 2018

Is it possible to just sign an order (smart contract method call) or other transaction and publish it as an ethereum transaction to another server like etherscan or etherchain instead of interacting with the the ocean's ethereum node, in true decentralised fashion? That way if theocean wanted to maliciously block a transaction they would be unable to do so.

With some relayers – yes, however, The Ocean uses a matching strategy, as described in 0x docs, here: https://0xproject.com/wiki#Matching. So, all orders have taker: 0x123abc.. and this is an address controlled by The Ocean.

I propose we write a module to encode and publish ethereum transactions. There are already many libraries to work with hex and rlp transactions. I.E. https://github.com/ethereumjs/ethereumjs-tx

Yep, we are working on a portable wrapper for that. Will upload once we have something substantial. ) This covers not only pure ETH transactions, but also contract calls and ERC20 transfers.

@mkutny
Copy link
Contributor

mkutny commented Jul 27, 2018

A less technical description of why one would want to push orders to The Ocean instead of directly into a blockchain: https://medium.com/the-ocean-trade/0x-the-0cean-and-the-high-performance-funnel-80f0eb459f46

Basically, if you push your taker order into a blockchain you'll need to spend some gas even if it don't get fulfilled. But if you decide The Ocean to be a taker then you can push it to them off-chain and spend gas only if it gets filled.

@mkutny
Copy link
Contributor

mkutny commented Aug 5, 2018

just one maker order being filled (taken by you from the orderbook, where you are the taker, taking or filling someones' maker order)

Here, you probably meant "just one market order being filled", not "just one maker order being filled".

@kroitor
Copy link
Member Author

kroitor commented Aug 5, 2018

Here, you probably meant "just one market order being filled", not "just one maker order being filled".

Nope, that means "one maker that was already there in the orderbook, before the incoming order" – because it was there already, it was a maker for sure ) But yeah, I'll add a clarification on that, or will rephrase it for less confusion. Thx for pointing that out!

@benspring
Copy link

benspring commented May 25, 2019

Is this different from the other API calls? I normally use create_limit_buy_order, do I have to specifically use createOrder instead?

Same goes for fetchBalance() and fetch_balance()

@kroitor
Copy link
Member Author

kroitor commented Jun 2, 2019

@benspring in this case, yes, it requires a bit of special handling, because it's a DEX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants
@kroitor @mkutny @frosty00 @benspring @viktorius007 and others