예제 #1
0
 def test_get_stats(self):
     public = Client(API_HOST).public
     json = public.get_stats(
         MARKET_BTC_USD,
         MARKET_STATISTIC_DAY_ONE,
     )
     assert json != {}
예제 #2
0
    def test_private_without_stark_private_key(self):
        # Generate STARK keys and Ethhereum account.
        api_private_key = generate_private_key_hex_unsafe()
        stark_private_key = generate_private_key_hex_unsafe()
        eth_account = Web3(None).eth.account.create()

        # Get public keys.
        api_public_key = private_key_to_public_hex(api_private_key)
        stark_public_key = private_key_to_public_hex(stark_private_key)

        # Onboard the user.
        Client(
            host=API_HOST,
            eth_private_key=eth_account.key,
        ).onboarding.create_user(
            api_public_key=api_public_key,
            stark_public_key=stark_public_key,
        )

        # Create a second client WITHOUT eth_private_key or stark_private_key.
        client = Client(
            host=API_HOST,
            api_private_key=api_private_key,
        )

        # Create a test deposit.
        client.private.create_test_deposit(
            from_address=eth_account.address,
            credit_amount='200',
        )

        # Get the primary account.
        get_account_result = client.private.get_account(
            ethereum_address=eth_account.address, )
        account = get_account_result['account']

        # Sign a withdrawal.
        client_id = random_client_id()
        expiration = epoch_seconds_to_iso(time.time() + 60)
        signable_withdrawal = SignableWithdrawal(
            position_id=account['positionId'],
            client_id=client_id,
            human_amount='1',
            expiration_epoch_seconds=iso_to_epoch_seconds(expiration),
        )
        signature = signable_withdrawal.sign(stark_private_key)

        # Initiate a withdrawal.
        client.private.create_withdrawal(
            position_id=account['positionId'],
            amount='1',
            asset=constants.ASSET_USDC,
            to_address=eth_account.address,
            expiration=expiration,
            client_id=client_id,
            signature=signature,
        )
예제 #3
0
    def test_private_with_private_keys(self):
        # Generate STARK keys and Ethhereum account.
        stark_private_key = generate_private_key_hex_unsafe()
        eth_account = Web3(None).eth.account.create()

        # Get public key.
        stark_public_key, stark_public_key_y_coordinate = (
            private_key_to_public_key_pair_hex(stark_private_key))

        # Onboard the user.
        Client(
            host=HOST,
            network_id=NETWORK_ID,
            eth_private_key=eth_account.key,
        ).onboarding.create_user(
            stark_public_key=stark_public_key,
            stark_public_key_y_coordinate=stark_public_key_y_coordinate,
        )

        # Create a second client WITHOUT eth_private_key.
        client = Client(
            host=HOST,
            network_id=NETWORK_ID,
            stark_private_key=stark_private_key,
        )

        # Get the primary account.
        get_account_result = client.private.get_account(
            ethereum_address=eth_account.address, )
        account = get_account_result['account']

        # Initiate a regular (slow) withdrawal.
        #
        # Expect signature validation to pass, although the collateralization
        # check will fail.
        expected_error = (
            'Withdrawal would put account under collateralization minumum')
        expiration_epoch_seconds = time.time() + SEVEN_DAYS_S + 60
        try:
            client.private.create_withdrawal(
                position_id=account['positionId'],
                amount='1',
                asset=constants.ASSET_USDC,
                to_address=eth_account.address,
                expiration_epoch_seconds=expiration_epoch_seconds,
            )
        except DydxApiError as e:
            if expected_error not in str(e):
                raise
예제 #4
0
    def test_onboard_with_web3_default_account(self):
        # Generate private key.
        stark_private_key = generate_private_key_hex_unsafe()

        # Get public key.
        stark_public_key, stark_public_key_y_coordinate = (
            private_key_to_public_key_pair_hex(stark_private_key))

        # Connect to local Ethereum node.
        web3 = Web3()
        web3.eth.defaultAccount = web3.eth.accounts[1]

        # Create client WITHOUT any private keys.
        client = Client(
            host=HOST,
            network_id=NETWORK_ID,
            web3=web3,
        )

        # Onboard the user.
        try:
            client.onboarding.create_user(
                stark_public_key=stark_public_key,
                stark_public_key_y_coordinate=stark_public_key_y_coordinate,
            )

        # If the Ethereum address was already onboarded, ignore the error.
        except DydxApiError:
            pass

        # Register and then revoke a second API key.
        client.api_keys.create_api_key()
        client.private.get_api_keys()
        client.api_keys.delete_api_key(
            api_key=client.api_key_credentials['key'], )
예제 #5
0
 async def get_last_traded_price(cls,
                                 trading_pair: str,
                                 domain=None) -> float:
     BASE_URL = TESTNET_BASE_URL if domain == "dydx_perpetual_testnet" else PERPETUAL_BASE_URL
     public_client = Client(host=BASE_URL, )
     resp = public_client.public.get_stats(market=trading_pair, days=1)
     return float(resp["markets"][trading_pair]['close'])
예제 #6
0
 def get_mid_price(trading_pair: str, domain=None) -> Optional[Decimal]:
     BASE_URL = TESTNET_BASE_URL if domain == "dydx_perpetual_testnet" else PERPETUAL_BASE_URL
     public_client = Client(host=BASE_URL, )
     resp = public_client.public.get_orderbook(market=trading_pair)
     bidPrice = resp['bids'][0]['price']
     askPrice = resp['asks'][0]['price']
     result = (Decimal(bidPrice) + Decimal(askPrice)) / Decimal(2)
     return result
예제 #7
0
 def test_derive_stark_key_on_ropsten_from_priv(self):
     client = Client(
         host=DEFAULT_HOST,
         network_id=NETWORK_ID_ROPSTEN,
         eth_private_key=GANACHE_PRIVATE_KEY,
     )
     signer_address = client.default_address
     stark_private_key = client.onboarding.derive_stark_key(signer_address)
     assert stark_private_key == EXPECTED_STARK_PRIVATE_KEY_ROPSTEN
 def __init__(self, api_key, api_secret, passphrase, account_number, stark_private_key, ethereum_address):
     self._api_credentials = {'key': api_key,
                              'secret': api_secret,
                              'passphrase': passphrase}
     self.client = Client(host = BASE_URL,
                          api_key_credentials = self._api_credentials,
                          stark_private_key = stark_private_key)
     self._loop = asyncio.get_event_loop()
     self._ethereum_address = ethereum_address
     self._account_number = account_number
예제 #9
0
 async def fetch_trading_pairs(domain=None) -> List[str]:
     try:
         BASE_URL = TESTNET_BASE_URL if domain == "dydx_perpetual_testnet" else PERPETUAL_BASE_URL
         public_client = Client(host=BASE_URL, )
         resp = public_client.public.get_markets()
         trading_pairs = [key for key in resp['markets']]
         return trading_pairs
     except Exception:
         pass
     return []
예제 #10
0
 def test_derive_stark_key_on_ropsten_from_web3(self):
     web3 = Web3()  # Connect to a local Ethereum node.
     client = Client(
         host=DEFAULT_HOST,
         network_id=NETWORK_ID_ROPSTEN,
         web3=web3,
     )
     signer_address = web3.eth.accounts[0]
     stark_private_key = client.onboarding.derive_stark_key(signer_address)
     assert stark_private_key == EXPECTED_STARK_PRIVATE_KEY_ROPSTEN
예제 #11
0
 def test_derive_stark_key_on_mainnet_from_priv(self):
     client = Client(
         host=DEFAULT_HOST,
         network_id=NETWORK_ID_MAINNET,
         eth_private_key=GANACHE_PRIVATE_KEY,
         api_key_credentials={'key': 'value'},
     )
     signer_address = client.default_address
     stark_private_key = client.onboarding.derive_stark_key(signer_address)
     assert stark_private_key == EXPECTED_STARK_PRIVATE_KEY_MAINNET
예제 #12
0
 def test_recover_default_api_key_credentials_on_mainnet_from_priv(self):
     client = Client(
         host=DEFAULT_HOST,
         network_id=NETWORK_ID_MAINNET,
         eth_private_key=GANACHE_PRIVATE_KEY,
     )
     signer_address = client.default_address
     api_key_credentials = (
         client.onboarding.recover_default_api_key_credentials(
             signer_address,
         )
     )
     assert api_key_credentials == EXPECTED_API_KEY_CREDENTIALS_MAINNET
예제 #13
0
 def test_recover_default_api_key_credentials_on_ropsten_from_web3(self):
     web3 = Web3()  # Connect to a local Ethereum node.
     client = Client(
         host=DEFAULT_HOST,
         network_id=NETWORK_ID_ROPSTEN,
         web3=web3,
     )
     signer_address = web3.eth.accounts[0]
     api_key_credentials = (
         client.onboarding.recover_default_api_key_credentials(
             signer_address,
         )
     )
     assert api_key_credentials == EXPECTED_API_KEY_CREDENTIALS_ROPSTEN
    async def log_user_stream(self, output: asyncio.Queue):
        while True:
            try:
                print(self._wss_stream_url)
                async with websockets.connect(self._wss_stream_url) as ws:
                    ws: websockets.WebSocketClientProtocol = ws
                    client = Client(
                        network_id=self._network_id,
                        host=self._http_stream_url,
                        default_ethereum_address=self._eth_address,
                        api_key_credentials=self._api_key_credentials,
                    )
                    now_iso_string = generate_now_iso()
                    signature = client.private.sign(
                        request_path='/ws/accounts',
                        method='GET',
                        iso_timestamp=now_iso_string,
                        data={},
                    )
                    req = {
                        'type': 'subscribe',
                        'channel': 'v3_accounts',
                        'accountNumber': '0',
                        'apiKey': self._api_key_credentials['key'],
                        'passphrase': self._api_key_credentials['passphrase'],
                        'timestamp': now_iso_string,
                        'signature': signature,
                    }

                    # Send subscription message to websocket channel
                    try:
                        req = json.dumps(req)
                        await ws.send(req)
                    except Exception as e:
                        print(e)

                    async for raw_msg in self.ws_messages(ws):
                        msg_json: Dict[str, any] = ujson.loads(raw_msg)
                        output.put_nowait(msg_json)
            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().error(
                    "Unexpected error. Retrying after 5 seconds... ",
                    exc_info=True)
                await asyncio.sleep(5)
예제 #15
0
    async def get_snapshot(client: aiohttp.ClientSession,
                           trading_pair: str,
                           limit: int = 1000,
                           domain=None) -> Dict[str, Any]:
        try:

            BASE_URL = TESTNET_BASE_URL if domain == "dydx_perpetual_testnet" else PERPETUAL_BASE_URL
            public_client = Client(host=BASE_URL, )
            resp = public_client.public.get_orderbook(market=trading_pair, )
            snapshot = {
                'lastUpdateId': 0,
                'bids': [[row['price'], row['size']] for row in resp['bids']],
                'asks': [[row['price'], row['size']] for row in resp['asks']],
            }
            return snapshot
        except Exception:
            pass
        return {'lastUpdateId': 0, 'bids': [], 'asks': []}
예제 #16
0
    def test_onboard_with_private_keys(self):
        # Generate keys.
        stark_private_key = generate_private_key_hex_unsafe()
        eth_private_key = Web3(None).eth.account.create().key

        # Create client WITH private keys.
        client = Client(
            host=HOST,
            network_id=NETWORK_ID,
            stark_private_key=stark_private_key,
            eth_private_key=eth_private_key,
        )

        # Onboard the user.
        client.onboarding.create_user()

        # Register and then revoke a second API key.
        client.api_keys.create_api_key()
        client.private.get_api_keys()
예제 #17
0
    def test_onboard_with_web3_provider(self):
        # Generate private keys.
        api_private_key = generate_private_key_hex_unsafe()
        stark_private_key = generate_private_key_hex_unsafe()

        # Get public keys.
        api_public_key = private_key_to_public_hex(api_private_key)
        stark_public_key = private_key_to_public_hex(stark_private_key)

        # Get account address from local Ethereum node.
        ethereum_address = Web3().eth.accounts[0]

        # Create client WITHOUT any private keys.
        client = Client(
            host=API_HOST,
            web3_provider=Web3.HTTPProvider('http://localhost:8545'),
        )

        # Onboard the user.
        try:
            client.onboarding.create_user(
                ethereum_address=ethereum_address,
                stark_public_key=stark_public_key,
                api_public_key=api_public_key,
            )

        # If the Ethereum address was already onboarded, ignore the error.
        except DydxApiError:
            pass

        # Register and then revoke a second API key.
        api_private_key_2 = generate_private_key_hex_unsafe()
        api_public_key_2 = private_key_to_public_hex(api_private_key_2)
        client.api_keys.register_api_key(
            api_public_key=api_public_key_2,
            ethereum_address=ethereum_address,
        )
        client.api_keys.get_api_keys(ethereum_address=ethereum_address, )
        client.api_keys.delete_api_key(
            api_public_key=api_public_key_2,
            ethereum_address=ethereum_address,
        )
예제 #18
0
    def test_onboard_with_private_keys(self):
        # Generate keys.
        api_private_key = generate_private_key_hex_unsafe()
        stark_private_key = generate_private_key_hex_unsafe()
        eth_private_key = Web3(None).eth.account.create().key

        # Create client WITH private keys.
        client = Client(
            host=API_HOST,
            api_private_key=api_private_key,
            stark_private_key=stark_private_key,
            eth_private_key=eth_private_key,
        )

        # Onboard the user.
        client.onboarding.create_user()

        # Register and then revoke a second API key.
        api_private_key_2 = generate_private_key_hex_unsafe()
        api_public_key_2 = private_key_to_public_hex(api_private_key_2)
        client.api_keys.register_api_key(api_public_key_2)
        client.api_keys.get_api_keys()
        client.api_keys.delete_api_key(api_public_key_2)
예제 #19
0
    def test_onboard_with_web3_provider(self):
        # Generate private key.
        stark_private_key = generate_private_key_hex_unsafe()

        # Get public key.
        stark_public_key, stark_public_key_y_coordinate = (
            private_key_to_public_key_pair_hex(stark_private_key))

        # Get account address from local Ethereum node.
        ethereum_address = Web3().eth.accounts[0]

        # Create client WITHOUT any private keys.
        client = Client(
            host=HOST,
            network_id=NETWORK_ID,
            web3_provider=Web3.HTTPProvider('http://localhost:8545'),
        )

        # Onboard the user.
        try:
            client.onboarding.create_user(
                ethereum_address=ethereum_address,
                stark_public_key=stark_public_key,
                stark_public_key_y_coordinate=stark_public_key_y_coordinate,
            )

        # If the Ethereum address was already onboarded, ignore the error.
        except DydxApiError:
            pass

        # Register and then revoke a second API key.
        client.api_keys.create_api_key(ethereum_address=ethereum_address, )
        client.private.get_api_keys()
        client.api_keys.delete_api_key(
            api_key=client.api_key_credentials['key'],
            ethereum_address=ethereum_address,
        )
예제 #20
0
    def test_onboard_with_web3_default_account(self):
        # Generate private keys.
        api_private_key = generate_private_key_hex_unsafe()
        stark_private_key = generate_private_key_hex_unsafe()

        # Get public keys.
        api_public_key = private_key_to_public_hex(api_private_key)
        stark_public_key = private_key_to_public_hex(stark_private_key)

        # Connect to local Ethereum node.
        web3 = Web3()
        web3.eth.defaultAccount = web3.eth.accounts[1]

        # Create client WITHOUT any private keys.
        client = Client(
            host=API_HOST,
            web3=web3,
        )

        # Onboard the user.
        try:
            client.onboarding.create_user(
                stark_public_key=stark_public_key,
                api_public_key=api_public_key,
            )

        # If the Ethereum address was already onboarded, ignore the error.
        except DydxApiError:
            pass

        # Register and then revoke a second API key.
        api_private_key_2 = generate_private_key_hex_unsafe()
        api_public_key_2 = private_key_to_public_hex(api_private_key_2)
        client.api_keys.register_api_key(api_public_key_2)
        client.api_keys.get_api_keys()
        client.api_keys.delete_api_key(api_public_key_2)
예제 #21
0
 def test_get_historical_funding(self):
     public = Client(API_HOST).public
     json = public.get_historical_funding(MARKET_BTC_USD)
     assert json != {}
예제 #22
0
from web3 import Web3
from dydx3 import Client
import os

api_cred = {
    'secret': os.environ['DYDX_SECRET'],
    'key': os.environ['DYDX_KEY'],
    'passphrase': os.environ['DYDX_PASSPHRASE']
}

client = Client(
    host='https://api.dydx.exchange',
    web3=Web3(
        Web3.HTTPProvider('https://mainnet.infura.io/v3/' +
                          os.environ['INFURA_API_KEY'])),
    #stark_private_key=os.environ['STARK_PRIVATE_KEY'],
    stark_public_key=os.environ['STARK_PUBLIC_KEY'],
    api_key_credentials=api_cred,
    eth_private_key=os.environ['ETHEREUM_PRIVATE_KEY'],
    default_ethereum_address=os.environ['ETHEREUM_ADDRESS'])
예제 #23
0
 def test_public(self):
     client = Client(
         host=HOST,
         network_id=NETWORK_ID,
     )
     client.public.get_markets()
예제 #24
0
 def test_get_markets(self):
     public = Client(API_HOST).public
     json = public.get_markets()
     assert json != {}
예제 #25
0
 def test_get_orderbook(self):
     public = Client(API_HOST).public
     json = public.get_orderbook(MARKET_BTC_USD)
     assert json != {}
예제 #26
0
    def test_integration(self):
        source_private_key = os.environ.get('TEST_SOURCE_PRIVATE_KEY')
        if source_private_key is None:
            raise ValueError('TEST_SOURCE_PRIVATE_KEY must be set')

        web3_provider = os.environ.get('TEST_WEB3_PROVIDER_URL')
        if web3_provider is None:
            raise ValueError('TEST_WEB3_PROVIDER_URL must be set')

        # Create client that will be used to fund the new user.
        source_client = Client(
            host='',
            eth_private_key=source_private_key,
            web3_provider=web3_provider,
        )

        # Create an Ethereum account and STARK keys for the new user.
        web3_account = Web3(None).eth.account.create()
        ethereum_address = web3_account.address
        eth_private_key = web3_account.key
        stark_private_key = generate_private_key_hex_unsafe()

        # Fund the new user with ETH and USDC.
        fund_eth_hash = source_client.eth.transfer_eth(
            to_address=ethereum_address,
            human_amount=0.001,
        )
        fund_usdc_hash = source_client.eth.transfer_token(
            to_address=ethereum_address,
            human_amount=2,
        )
        print('Waiting for funds...')
        source_client.eth.wait_for_tx(fund_eth_hash)
        source_client.eth.wait_for_tx(fund_usdc_hash)
        print('...done.')

        # Create client for the new user.
        client = Client(
            host=HOST,
            network_id=NETWORK_ID,
            stark_private_key=stark_private_key,
            eth_private_key=eth_private_key,
            web3_provider=web3_provider,
        )

        # Onboard the user.
        res = client.onboarding.create_user()
        api_key_credentials = res['apiKey']

        print('eth_private_key', eth_private_key)
        print('stark_private_key', stark_private_key)
        print('client.api_key_credentials', client.api_key_credentials)

        # Get the user.
        get_user_result = client.private.get_user()
        assert get_user_result['user'] == {
            'ethereumAddress': ethereum_address.lower(),
            'isRegistered': False,
            'email': None,
            'username': None,
            'userData': {},
            'makerFeeRate': '0.0005',
            'takerFeeRate': '0.0015',
            'makerVolume30D': '0',
            'takerVolume30D': '0',
            'fees30D': '0',
        }

        # Get the registration signature.
        registration_result = client.private.get_registration()
        signature = registration_result['signature']
        assert re.match('0x[0-9a-f]{130}$', signature) is not None, (
            'Invalid registration result: {}'.format(registration_result))

        # Register the user on-chain.
        registration_tx_hash = client.eth.register_user(signature)
        print('Waiting for registration...')
        client.eth.wait_for_tx(registration_tx_hash)
        print('...done.')

        # Set the user's username.
        username = '******'.format(int(time.time()))
        client.private.update_user(username=username)

        # Create a second account under the same user.
        #
        # NOTE: Support for multiple accounts under the same user is limited.
        # The frontend does not currently support mutiple accounts per user.
        stark_private_key_2 = generate_private_key_hex_unsafe()
        stark_public_key_2, stark_public_key_y_coordinate_2 = (
            private_key_to_public_key_pair_hex(stark_private_key_2))

        client.private.create_account(
            stark_public_key=stark_public_key_2,
            stark_public_key_y_coordinate=stark_public_key_y_coordinate_2,
        )

        # Get the primary account.
        get_account_result = client.private.get_account(
            ethereum_address=ethereum_address, )
        account = get_account_result['account']
        assert int(account['starkKey'], 16) == int(client.stark_public_key, 16)

        # Get all accounts.
        get_all_accounts_result = client.private.get_accounts()
        get_all_accounts_public_keys = [
            a['starkKey'] for a in get_all_accounts_result['accounts']
        ]
        assert int(client.stark_public_key,
                   16) in [int(k, 16) for k in get_all_accounts_public_keys]

        # TODO: Fix.
        # assert int(stark_public_key_2, 16) in [
        #     int(k, 16) for k in get_all_accounts_public_keys
        # ]

        # Get positions.
        get_positions_result = client.private.get_positions(market='BTC-USD')
        assert get_positions_result == {'positions': []}

        # Set allowance on the Starkware perpetual contract, for the deposit.
        approve_tx_hash = client.eth.set_token_max_allowance(
            client.eth.get_exchange_contract().address, )
        print('Waiting for allowance...')
        client.eth.wait_for_tx(approve_tx_hash)
        print('...done.')

        # Send an on-chain deposit.
        deposit_tx_hash = client.eth.deposit_to_exchange(
            account['positionId'],
            3,
        )
        print('Waiting for deposit...')
        client.eth.wait_for_tx(deposit_tx_hash)
        print('...done.')

        # Wait for the deposit to be processed.
        print('Waiting for deposit to be processed on dYdX...')
        wait_for_condition(
            lambda: len(client.private.get_transfers()['transfers']) > 0,
            True,
            60,
        )
        print('...transfer was recorded, waiting for confirmation...')
        wait_for_condition(
            lambda: client.private.get_account()['account']['quoteBalance'],
            '2',
            180,
        )
        print('...done.')

        # Post an order.
        one_minute_from_now_iso = epoch_seconds_to_iso(time.time() + 60)
        create_order_result = client.private.create_order(
            position_id=account['positionId'],
            market=constants.MARKET_BTC_USD,
            side=constants.ORDER_SIDE_BUY,
            order_type=constants.ORDER_TYPE_LIMIT,
            post_only=False,
            size='10',
            price='1000',
            limit_fee='0.1',
            expiration=one_minute_from_now_iso,
        )

        # Get the order.
        order_id = create_order_result['order']['id']
        get_order_result = client.private.get_order_by_id(order_id)
        assert get_order_result['order']['market'] == constants.MARKET_BTC_USD

        # Cancel the order.
        client.private.cancel_order(order_id)

        # Cancel all orders.
        client.private.cancel_all_orders()

        # Get open orders.
        get_orders_result = client.private.get_orders(
            market=constants.MARKET_BTC_USD,
            status=constants.POSITION_STATUS_OPEN,
        )
        assert get_orders_result == {'orders': []}

        # Get fills.
        client.private.get_fills(market=constants.MARKET_BTC_USD, )

        # Initiate a regular (slow) withdrawal.
        expiration_epoch_seconds = time.time() + SEVEN_DAYS_S + 60
        client.private.create_withdrawal(
            position_id=account['positionId'],
            amount='1',
            asset=constants.ASSET_USDC,
            to_address=ethereum_address,
            expiration_epoch_seconds=expiration_epoch_seconds,
        )

        # Get deposits.
        deposits_result = client.private.get_transfers(
            transfer_type=constants.ACCOUNT_ACTION_DEPOSIT, )
        assert len(deposits_result['transfers']) == 1

        # Get withdrawals.
        withdrawals_result = client.private.get_transfers(
            transfer_type=constants.ACCOUNT_ACTION_WITHDRAWAL, )
        assert len(withdrawals_result['transfers']) == 1

        # Get funding payments.
        client.private.get_funding_payments(market=constants.MARKET_BTC_USD, )

        # Register a new API key.
        create_api_key_result = client.api_keys.create_api_key()
        new_api_key_credentials = create_api_key_result['apiKey']

        # Get all API keys.
        get_api_keys_result = client.private.get_api_keys()
        api_keys_public_keys = [
            a['key'] for a in get_api_keys_result['apiKeys']
        ]
        assert api_key_credentials['key'] in api_keys_public_keys

        # Delete an API key.
        client.api_keys.delete_api_key(
            api_key=new_api_key_credentials['key'],
            ethereum_address=ethereum_address,
        )

        # Get all API keys after the deletion.
        get_api_keys_result_after = client.private.get_api_keys()
        assert len(get_api_keys_result_after['apiKeys']) == 1

        # Initiate a fast withdrawal of USDC.
        expiration_epoch_seconds = time.time() + SEVEN_DAYS_S + 60
        client.private.create_fast_withdrawal(
            position_id=account['positionId'],
            credit_asset='USDC',
            credit_amount='1',
            debit_amount='2',
            to_address=ethereum_address,
            lp_position_id=LP_POSITION_ID,
            lp_stark_public_key=LP_PUBLIC_KEY,
            client_id='mock-client-id',
            expiration_epoch_seconds=expiration_epoch_seconds,
        )
예제 #27
0
    def test_integration(self):
        # Create an Ethereum account.
        web3 = Web3(None)
        web3_account = web3.eth.account.create()
        ethereum_address = web3_account.address

        # Generate STARK keys.
        api_private_key = generate_private_key_hex_unsafe()
        stark_private_key = generate_private_key_hex_unsafe()

        # Create client.
        client = Client(
            host=os.environ.get('V3_API_HOST', DEFAULT_HOST),
            api_private_key=api_private_key,
            stark_private_key=stark_private_key,
            web3_account=web3_account,
        )

        # Onboard user.
        client.onboarding.create_user(ethereum_address=ethereum_address, )

        # Get the user.
        get_user_result = client.private.get_user()
        assert get_user_result == {
            'user': {
                'ethereumAddress': ethereum_address.lower(),
                'isRegistered': False,
                'email': None,
                'username': None,
                'userData': {},
                'makerFeeRate': '0.05',
                'takerFeeRate': '0.04',
                'makerVolume30D': '0',
                'takerVolume30D': '0',
                'fees30D': '0',
            },
        }

        # Get the registration signature.
        get_registration_result = client.private.get_registration()
        assert re.match(
            '0x[0-9a-f]{130}$',
            get_registration_result['signature'],
        ) is not None, (
            'Invalid registration result: {}'.format(get_registration_result))

        # Set the user's username.
        username = '******'.format(int(time.time()))
        client.private.update_user(username=username)

        # Create a second account under the same user.
        #
        # NOTE: Support for multiple accounts under the same user is limited.
        # The frontend does not currently support mutiple accounts per user.
        stark_private_key_2 = generate_private_key_hex_unsafe()
        stark_public_key_2 = private_key_to_public_hex(stark_private_key_2)
        client.private.create_account(stark_public_key=stark_public_key_2, )

        # Get the primary account.
        get_account_result = client.private.get_account(
            ethereum_address=ethereum_address, )
        account = get_account_result['account']
        assert account['starkKey'] == client.stark_public_key

        # Get all accounts.
        get_all_accounts_result = client.private.get_accounts()
        get_all_accounts_public_keys = [
            a['starkKey'] for a in get_all_accounts_result['accounts']
        ]
        assert client.stark_public_key in get_all_accounts_public_keys
        assert stark_public_key_2 in get_all_accounts_public_keys

        # Get postiions.
        get_positions_result = client.private.get_positions(market='BTC-USD')
        assert get_positions_result == {'positions': []}

        # Create a test deposit.
        client.private.create_test_deposit(
            from_address=ethereum_address,
            credit_amount='200',
        )

        # Post an order.
        one_minute_from_now_iso = epoch_seconds_to_iso(time.time() + 60)
        create_order_result = client.private.create_order(
            position_id=account['positionId'],
            market=constants.MARKET_BTC_USD,
            side=constants.ORDER_SIDE_BUY,
            order_type=constants.ORDER_TYPE_LIMIT,
            post_only=False,
            size='10',
            price='1000',
            limit_fee='0.1',
            expiration=one_minute_from_now_iso,
        )

        # Get the order.
        order_id = create_order_result['order']['id']
        get_order_result = client.private.get_order_by_id(order_id)
        assert get_order_result['order']['market'] == constants.MARKET_BTC_USD

        # Cancel the order.
        client.private.cancel_order(order_id)

        # Cancel all orders.
        client.private.cancel_all_orders()

        # Get open orders.
        get_orders_result = client.private.get_orders(
            market=constants.MARKET_BTC_USD,
            status=constants.POSITION_STATUS_OPEN,
        )
        assert get_orders_result == {'orders': []}

        # Get fills.
        client.private.get_fills(market=constants.MARKET_BTC_USD, )

        # Initiate a regular (slow) withdrawal.
        one_minute_from_now_iso = epoch_seconds_to_iso(time.time() + 60)
        client.private.create_withdrawal(
            position_id=account['positionId'],
            amount='1',
            asset=constants.ASSET_USDC,
            to_address=ethereum_address,
            expiration=one_minute_from_now_iso,
        )

        # Get deposits.
        deposits_result = client.private.get_transfers(
            transfer_type=constants.ACCOUNT_ACTION_DEPOSIT, )
        assert len(deposits_result['transfers']) == 1

        # Get withdrawals.
        withdrawals_result = client.private.get_transfers(
            transfer_type=constants.ACCOUNT_ACTION_WITHDRAWAL, )
        assert len(withdrawals_result['transfers']) == 1

        # Get funding payments.
        client.private.get_funding_payments(market=constants.MARKET_BTC_USD, )

        # Register a new API key.
        api_private_key_2 = generate_private_key_hex_unsafe()
        api_public_key_2 = private_key_to_public_hex(api_private_key_2)
        client.api_keys.register_api_key(
            ethereum_address=ethereum_address,
            api_public_key=api_public_key_2,
        )

        # Get all API keys.
        api_keys_result = client.api_keys.get_api_keys(
            ethereum_address=ethereum_address, )
        api_keys_public_keys = [
            a['apiKey'] for a in api_keys_result['apiKeys']
        ]
        assert client.api_public_key in api_keys_public_keys
        assert api_public_key_2 in api_keys_public_keys

        # Delete an API key.
        client.api_keys.delete_api_key(
            ethereum_address=ethereum_address,
            api_public_key=api_public_key_2,
        )

        # Get all API keys after the deletion.
        api_keys_result_after = client.api_keys.get_api_keys(
            ethereum_address=ethereum_address, )
        assert len(api_keys_result_after['apiKeys']) == 1
예제 #28
0
 def test_get_candles(self):
     public = Client(API_HOST).public
     json = public.get_candles(MARKET_BTC_USD)
     assert json != {}
예제 #29
0
    def test_integration_without_funds(self):
        # Create an Ethereum account and STARK keys for the new user.
        web3_account = Web3(None).eth.account.create()
        ethereum_address = web3_account.address
        stark_private_key = generate_private_key_hex_unsafe()

        # Create client for the new user.
        client = Client(
            host=HOST,
            network_id=NETWORK_ID,
            stark_private_key=stark_private_key,
            web3_account=web3_account,
        )

        # Onboard the user.
        client.onboarding.create_user()

        # Register a new API key.
        client.api_keys.create_api_key()

        # Get the primary account.
        get_account_result = client.private.get_account(
            ethereum_address=ethereum_address, )
        account = get_account_result['account']
        assert int(account['starkKey'], 16) == int(client.stark_public_key, 16)

        # Initiate a regular (slow) withdrawal.
        #
        # Expect signature validation to pass, although the collateralization
        # check will fail.
        expected_error = (
            'Withdrawal would put account under collateralization minumum')
        expiration_epoch_seconds = time.time() + SEVEN_DAYS_S + 60
        try:
            client.private.create_withdrawal(
                position_id=account['positionId'],
                amount='1',
                asset=constants.ASSET_USDC,
                to_address=ethereum_address,
                expiration_epoch_seconds=expiration_epoch_seconds,
            )
        except DydxApiError as e:
            if expected_error not in str(e):
                raise

        # Post an order.
        #
        # Expect signature validation to pass, although the collateralization
        # check will fail.
        one_minute_from_now_iso = epoch_seconds_to_iso(time.time() + 60)
        try:
            client.private.create_order(
                position_id=account['positionId'],
                market=constants.MARKET_BTC_USD,
                side=constants.ORDER_SIDE_BUY,
                order_type=constants.ORDER_TYPE_LIMIT,
                post_only=False,
                size='10',
                price='1000',
                limit_fee='0.1',
                expiration=one_minute_from_now_iso,
            )
        except DydxApiError as e:
            if expected_error not in str(e):
                raise
예제 #30
0
 def test_get_fast_withdrawal(self):
     public = Client(API_HOST).public
     json = public.get_fast_withdrawal()
     assert json != {}