zksync-sdk / zksync-python

Python 3.8 SDK for zkSync
MIT License
116 stars 64 forks source link

'<' not supported between instances of 'NoneType' and 'int' on wallet.set_signing_key #31

Open robtrip opened 2 years ago

robtrip commented 2 years ago

Hey team really struggling to get the python sdk working. The snippets are a bit helpful but figuring out the whole async stuff works has been a nightmare, also had some weird issue loading the dylib. If you could just include a fully working code example it would be a lot easier!

Anyways I'm now stuck on 2 points:

1) on calling deposit, I see a transaction go out but no ERC20 tokens leave my wallet which I believe is incorrect? I would have expected to see the USDT leave my wallet with the deposit? https://ropsten.etherscan.io/tx/0x00a13d37504616c4095a88854dff0f812ac73bf101a80c37c0f1bc334e10d796

--> follow up: this seems to be linked to the fact that USDT contract returned by the resolve_token function (0x3b00ef435fa4fcff5c209a37d1f3dcff37c705ad) has been self-destructed. I guess this is because you're all working off of v2 so testnet v1 is basically deprecated? I couldn't see how to manually load a token in from the code.

2) once await wallet.set_signing_key("ETH", eth_auth_data=ChangePubKeyEcdsa()) is hit I get the following error.

Thanks so much in advance

Traceback (most recent call last):
  File "v1-zk.py", line 110, in <module>
    main()
  File "v1-zk.py", line 86, in main
    loop.run_until_complete(task)
  File "/usr/local/opt/python@3.8/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "v1-zk.py", line 82, in unlock_wallet
    await wallet.set_signing_key("ETH", eth_auth_data=ChangePubKeyEcdsa())
  File "/Users/o/private/dropster/venv/lib/python3.8/site-packages/zksync_sdk/wallet.py", line 91, in set_signing_key
    change_pub_key, eth_signature = await self.build_change_pub_key(fee_token_obj,
  File "/Users/o/private/dropster/venv/lib/python3.8/site-packages/zksync_sdk/wallet.py", line 126, in build_change_pub_key
    eth_signature = self.eth_signer.sign(change_pub_key.get_eth_tx_bytes())
  File "/Users/o/private/dropster/venv/lib/python3.8/site-packages/zksync_sdk/types/transactions.py", line 198, in get_eth_tx_bytes
    serialize_account_id(self.account_id),
  File "/Users/o/private/dropster/venv/lib/python3.8/site-packages/zksync_sdk/serializers.py", line 192, in serialize_account_id
    if account_id < 0:
TypeError: '<' not supported between instances of 'NoneType' and 'int'

My code below:

from decimal import *
from web3 import Web3, HTTPProvider, Account
from zksync_sdk import ZkSyncProviderV01, HttpJsonRPCTransport, network, ZkSync, EthereumProvider, Wallet, ZkSyncSigner, EthereumSignerWeb3, ZkSyncLibrary
import asyncio
from zksync_sdk.types import (ChangePubKeyCREATE2, ChangePubKeyEcdsa)

library = ZkSyncLibrary(library_path="../../../zksync-crypto-c/zks-crypto-macos-x64.dylib")
provider = ZkSyncProviderV01(provider=HttpJsonRPCTransport(network=network.rinkeby))
# Ethereum signer
account = Account.from_key(PRIVATE_KEY)
ethereum_signer = EthereumSignerWeb3(account=account)

# Initialization from ethereum private key
signer_v1 = ZkSyncSigner.from_account(account, library, network.rinkeby.chain_id)

def main():
    async def get_contract_address():
        contracts = await provider.get_contract_address()
        return contracts

    loop = asyncio.get_event_loop()

    task = loop.create_task(get_contract_address())
    loop.run_until_complete(task)
    contracts = task.result()

    # Setup web3
    w3 = Web3(HTTPProvider(endpoint_uri="https://ropsten.infura.io/v3/INFURA_PROJECT_ID" ))
    # Setup zksync contract interactor
    zksync = ZkSync(account=account, web3=w3,
                    zksync_contract_address=contracts.main_contract)
    # Create ethereum provider for interacting with ethereum node
    ethereum_provider = EthereumProvider(w3, zksync)

    # Initialize zksync signer, all creating options were described earlier
    signer = ZkSyncSigner.from_account(account, library, network.rinkeby.chain_id)
    # Initialize Wallet
    wallet = Wallet(ethereum_provider=ethereum_provider, zk_signer=signer,
                    eth_signer=ethereum_signer, provider=provider)

    # Find token for depositing
    async def resolve_token(wallet, token):
        token = await wallet.resolve_token(token)
        return token

    task = loop.create_task(resolve_token(wallet, "USDT"))
    loop.run_until_complete(task)
    token = task.result()
    print('TOKEN')
    print(token)
    print('\n')

    # Approve Enough deposit using token contract
    async def approve_deposit(token, decimal, wallet):
        res = await wallet.ethereum_provider.approve_deposit(token, decimal)
        return res

    task = loop.create_task(approve_deposit(token, Decimal(10), wallet))
    loop.run_until_complete(task)
    result = task.result()
    print('APPROVE')
    print(result)
    print('\n')

    async def deposit(token, decimal, address, wallet):
        res = await wallet.ethereum_provider.deposit(token, decimal, address)
        return res

    task = loop.create_task(deposit(token, Decimal(10), account.address, wallet))
    loop.run_until_complete(task)
    result = task.result()
    print('DEPOSIT')
    print(result)
    print('\n')

    # Unlocking zkSync account
    async def unlock_wallet(wallet):
        if not await wallet.is_signing_key_set():
            print('NOT SET')
            await wallet.set_signing_key("ETH", eth_auth_data=ChangePubKeyEcdsa())
        return

    task = loop.create_task(unlock_wallet(wallet))
    loop.run_until_complete(task)
    result = task.result()
    print('UNLOCK WALLET')
    print(result)
    print('\n')

    ## checking balance
    # Committed state is not final yet
    async def get_balance(token):
        committedBalance = await wallet.get_balance(token, "committed")
        return committedBalance
    balance = get_balance(wallet)

    task = loop.create_task(get_balance("USDT"))
    loop.run_until_complete(task)
    result = task.result()
    print('USDC balance: ' + result)

if __name__ == "__main__":
    main()
vyastrebovvareger commented 2 years ago

Hello @robtrip. About the 2nd issue. I did the testing on rinkeby env with test account and the following snapshot looks fine:

from decimal import *
from web3 import Web3, HTTPProvider, Account
from zksync_sdk import ZkSyncProviderV01, HttpJsonRPCTransport, network, ZkSync, EthereumProvider, Wallet, ZkSyncSigner, EthereumSignerWeb3, ZkSyncLibrary
import asyncio
from zksync_sdk.types import ChangePubKeyEcdsa

class TestEnv:
    PRIVATE_KEY = "_YOUR_PRIVATE_KEY_"

    def __init__(self):
        self.library = ZkSyncLibrary()
        self.provider = ZkSyncProviderV01(provider=HttpJsonRPCTransport(network=network.YOUR_SERVER))
        self.account = Account.from_key(self.PRIVATE_KEY)
        self.signer = ZkSyncSigner.from_account(self.account, self.library, network.YOUR_SERVER.chain_id)

def main():
    # Here could be your value for testing
    value = Decimal(1)
    env = TestEnv()

    async def get_contract_address():
        contracts = await env.provider.get_contract_address()
        return contracts

    loop = asyncio.get_event_loop()

    task = loop.create_task(get_contract_address())
    loop.run_until_complete(task)
    contracts = task.result()

    # Setup web3
    w3 = Web3(HTTPProvider(endpoint_uri="SERVER_ENDPOINT_URL"))
    # Setup zksync contract interactor
    zksync = ZkSync(account=env.account, web3=w3,
                    zksync_contract_address=contracts.main_contract)
    # Create ethereum provider for interacting with ethereum node
    ethereum_provider = EthereumProvider(w3, zksync)
    ethereum_signer = EthereumSignerWeb3(account=env.account)

    # Initialize zksync signer, all creating options were described earlier
    signer = ZkSyncSigner.from_account(env.account, env.library, network.rinkeby.chain_id)
    # Initialize Wallet
    wallet = Wallet(ethereum_provider=ethereum_provider, zk_signer=signer,
                    eth_signer=ethereum_signer, provider=env.provider)

    # Find token for depositing
    async def resolve_token(wallet, token):
        token = await wallet.resolve_token(token)
        return token

    task = loop.create_task(resolve_token(wallet, "USDT"))
    loop.run_until_complete(task)
    token = task.result()
    print('TOKEN')
    print(token)
    print('\n')

    # Approve Enough deposit using token contract
    async def approve_deposit(token, decimal, wallet):
        res = await wallet.ethereum_provider.approve_deposit(token, decimal)
        return res

    task = loop.create_task(approve_deposit(token, value, wallet))
    loop.run_until_complete(task)
    result = task.result()
    print('APPROVE')
    print(result)
    print('\n')

    async def deposit(token, decimal, address, wallet):
        res = await wallet.ethereum_provider.deposit(token, decimal, address)
        return res

    task = loop.create_task(deposit(token, value, env.account.address, wallet))
    loop.run_until_complete(task)
    result = task.result()
    print('DEPOSIT')
    print(result)
    print('\n')

    # Unlocking zkSync account
    async def unlock_wallet(wallet):
        if not await wallet.is_signing_key_set():
            print('NOT SET')
            await wallet.set_signing_key("ETH", eth_auth_data=ChangePubKeyEcdsa())
        return

    task = loop.create_task(unlock_wallet(wallet))
    loop.run_until_complete(task)
    result = task.result()
    print('UNLOCK WALLET')
    print(result)
    print('\n')

    ## checking balance
    # Committed state is not final yet
    async def get_balance(token):
        committedBalance = await wallet.get_balance(token, "committed")
        return committedBalance

    task = loop.create_task(get_balance("USDT"))
    loop.run_until_complete(task)
    result = task.result()
    print(f"USDC balance: {result}")

if __name__ == "__main__":
    main()

Can you please test it on your side and in the case of fails provide more details like test account settings etc?

About 1st issue described here it needs time for detailed investigation.

Giulio2002 commented 1 year ago

the documentation is broken with this error