import vegaapiclient as vac

# Vega gRPC clients for reading/writing data
data_client = vac.VegaTradingDataClient(node_url_grpc)
# :import_client__

#####################################################################################
#                           W A L L E T   S E R V I C E                             #
#####################################################################################

print(f"Logging into wallet: {wallet_name}")

# Log in to an existing wallet
req = {"wallet": wallet_name, "passphrase": wallet_passphrase}
response = requests.post(f"{wallet_server_url}/api/v1/auth/token", json=req)
helpers.check_response(response)
token = response.json()["token"]

assert token != ""
print("Logged in to wallet successfully")

# List key pairs and select public key to use
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(f"{wallet_server_url}/api/v1/keys", headers=headers)
helpers.check_response(response)
keys = response.json()["keys"]
pubkey = keys[0]["pub"]

assert pubkey != ""
print("Selected pubkey for signing")
def main():
    node_url_rest = os.getenv("NODE_URL_REST")
    if not helpers.check_url(node_url_rest):
        print("Error: Invalid or missing NODE_URL_REST environment variable.")
        sys.exit(1)

    wallet_server_url = os.getenv("WALLETSERVER_URL")

    wallet_name = os.getenv("WALLET_NAME")
    if not helpers.check_var(wallet_name):
        print("Error: Invalid or missing WALLET_NAME environment variable.")
        sys.exit(1)

    wallet_passphrase = os.getenv("WALLET_PASSPHRASE")
    if not helpers.check_var(wallet_passphrase):
        print(
            "Error: Invalid or missing WALLET_PASSPHRASE environment variable."
        )
        sys.exit(1)

    # Help guide users against including api version suffix on url
    wallet_server_url = helpers.check_wallet_url(wallet_server_url)

    #####################################################################################
    #                           W A L L E T   S E R V I C E                             #
    #####################################################################################

    print(f"Logging into wallet: {wallet_name}")

    # __login_wallet:
    # Log in to an existing wallet
    req = {"wallet": wallet_name, "passphrase": wallet_passphrase}
    response = requests.post(f"{wallet_server_url}/api/v1/auth/token",
                             json=req)
    helpers.check_response(response)
    token = response.json()["token"]
    # :login_wallet__

    assert token != ""
    print("Logged in to wallet successfully")

    # __get_pubkey:
    # List key pairs and select public key to use
    headers = {"Authorization": f"Bearer {token}"}
    response = requests.get(f"{wallet_server_url}/api/v1/keys",
                            headers=headers)
    helpers.check_response(response)
    keys = response.json()["keys"]
    pubkey = keys[0]["pub"]
    # :get_pubkey__

    assert pubkey
    print("Selected pubkey for signing")

    #####################################################################################
    #                           F I N D   P R O P O S A L S                             #
    #####################################################################################

    # __get_proposals_for_party:
    # Request a list of proposals available for party/pubkey
    url = f"{node_url_rest}/parties/{pubkey}/proposals"
    response = requests.get(url)
    helpers.check_response(response)
    # :get_proposals_for_party__

    # Debugging
    # print(response.json())

    print(f"Listing proposals for pubkey {pubkey}:")

    freeform_total = 0

    proposals = response.json()["data"]
    for proposal in proposals:
        proposal_id = proposal["proposal"]["id"]
        proposal_state = proposal["proposal"]["state"]
        proposal_ref = proposal["proposal"]["reference"]
        proposal_terms = proposal["proposal"]["terms"]
        print(
            f"\nid: {proposal_id} - state: {proposal_state} - ref: {proposal_ref}"
        )
        print(f"{proposal_terms}")
        if "newFreeform" in proposal_terms:
            freeform_total = freeform_total + 1
            print("^^ freeform governance proposal found ^^")

    print(f"\nTotal proposals found: {len(proposals)}")
    print(f" - of which freeform proposals found: {freeform_total}")
def main():
    node_url_rest = os.getenv("NODE_URL_REST")
    if not helpers.check_url(node_url_rest):
        print("Error: Invalid or missing NODE_URL_REST environment variable.")
        sys.exit(1)

    wallet_server_url = os.getenv("WALLETSERVER_URL")

    wallet_name = os.getenv("WALLET_NAME")
    if not helpers.check_var(wallet_name):
        print("Error: Invalid or missing WALLET_NAME environment variable.")
        sys.exit(1)

    wallet_passphrase = os.getenv("WALLET_PASSPHRASE")
    if not helpers.check_var(wallet_passphrase):
        print("Error: Invalid or missing WALLET_PASSPHRASE environment variable.")
        sys.exit(1)

    # Help guide users against including api version suffix on url
    wallet_server_url = helpers.check_wallet_url(wallet_server_url)

    #####################################################################################
    #                           W A L L E T   S E R V I C E                             #
    #####################################################################################

    print(f"Logging into wallet: {wallet_name}")

    # __login_wallet:
    # Log in to an existing wallet
    req = {"wallet": wallet_name, "passphrase": wallet_passphrase}
    response = requests.post(f"{wallet_server_url}/api/v1/auth/token", json=req)
    helpers.check_response(response)
    token = response.json()["token"]
    # :login_wallet__

    assert token != ""
    print("Logged in to wallet successfully")

    # __get_pubkey:
    # List key pairs and select public key to use
    headers = {"Authorization": f"Bearer {token}"}
    response = requests.get(f"{wallet_server_url}/api/v1/keys", headers=headers)
    helpers.check_response(response)
    keys = response.json()["keys"]
    pubkey = keys[0]["pub"]
    # :get_pubkey__

    assert pubkey
    print("Selected pubkey for signing")

    #####################################################################################
    #                              F I N D   A S S E T S                                #
    #####################################################################################


    # __get_assets:
    # Request a list of assets available on a Vega network
    url = f"{node_url_rest}/assets"
    response = requests.get(url)
    helpers.check_response(response)
    # :get_assets__

    # Debugging
    # print("Assets:\n{}".format(
    #    json.dumps(response.json(), indent=2, sort_keys=True)))

    #####################################################################################
    #                   G O V E R N A N C E   T O K E N   C H E C K                     #
    #####################################################################################

    # Get the identifier of the governance asset on the Vega network
    assets = response.json()["assets"]
    vote_asset_id = next((x["id"] for x in assets if x["details"]["symbol"] == "VEGA"), None)
    if vote_asset_id is None:
        print("VEGA asset not found on specified Vega network, please symbol name check and try again")
        sys.exit(1)

    # Request accounts for party and check governance asset balance
    url = f"{node_url_rest}/parties/{pubkey}/accounts"
    response = requests.get(url)
    helpers.check_response(response)

    # Debugging
    # print("Accounts:\n{}".format(
    #    json.dumps(response.json(), indent=2, sort_keys=True)))

    voting_balance = 0
    accounts = response.json()["accounts"]
    for account in accounts:
        if account["asset"] == vote_asset_id:
            print("Found governance asset account")
            print(account)
            voting_balance = account["balance"]
            break

    if voting_balance == 0:
        print(f"Please deposit VEGA asset to public key {pubkey} and try again")
        sys.exit(1)

    #####################################################################################
    #                          B L O C K C H A I N   T I M E                            #
    #####################################################################################

    # __get_time:
    # Request the current blockchain time, and convert to time in seconds
    response = requests.get(f"{node_url_rest}/time")
    helpers.check_response(response)
    blockchain_time = int(response.json()["timestamp"])
    blockchain_time_seconds = int(blockchain_time / 1e9)  # Seconds precision
    # :get_time__

    assert blockchain_time > 0
    assert blockchain_time_seconds > 0
    print(f"Blockchain time: {blockchain_time} ({blockchain_time_seconds} seconds past epoch)")

    #####################################################################################
    #                               F R E E F O R M                                     #
    #####################################################################################

    # Step 1 propose a freeform proposal

    # __prepare_propose_newFreeform:
    # Compose a freeform governance proposal 
    proposal_ref = f"{pubkey}-{helpers.generate_id(30)}"

    # Set closing/enactment and validation timestamps to valid time offsets
    # from the current Vega blockchain time
    closing_time = blockchain_time_seconds + 172900
    validation_time = blockchain_time_seconds + 1

    new_freeform = {
        "proposalSubmission": {
            "reference": proposal_ref,
            "rationale": {
                "url": "www.example.com/full-proposal.md",
                "description": "A short description of the proposals",
                "hash": "1869c3081c5a294269070aa496a4d80d1b0824c239af02625b2e304f011bb190"
            },
            "terms": {
                "closingTimestamp": closing_time,
                "validationTimestamp": validation_time,
                "newFreeform": {},
            }
        },
        "pubKey": pubkey,
        "propagate": True
    }

    # __sign_tx_proposal:
    # Sign the proposal transaction
    # Note: Setting propagate to true will also submit to a Vega node
    url = f"{wallet_server_url}/api/v1/command/sync"
    response = requests.post(url, headers=headers, json=new_freeform)
    helpers.check_response(response)
    # :sign_tx_proposal__

    print("Signed proposal and sent to Vega")

    # Debugging
    # print("Signed transaction:\n", response.json(), "\n")

    # Wait for proposal to be included in a block and to be accepted by Vega network
    print("Waiting for blockchain...", end="", flush=True)
    proposal_id = ""
    done = False
    while not done:
        time.sleep(0.5)
        print(".", end="", flush=True)
        my_proposals = requests.get(node_url_rest + "/parties/" + pubkey + "/proposals")
        if my_proposals.status_code != 200:
            continue

        for n in my_proposals.json()["data"]:
            if n["proposal"]["reference"] == proposal_ref:
                proposal_id = n["proposal"]["id"]
                print()
                if (n["proposal"]['state'] == 'STATE_REJECTED') or (n["proposal"]['state'] == 'STATE_DECLINED') or (
                        n["proposal"]['state'] == 'STATE_FAILED'):
                    print("Your proposal has been " + n["proposal"]['state'] + "!")
                    print("Due to: " + n["proposal"]["reason"])
                    if ((n["proposal"]["errorDetails"]) != ''): print("Further details: " + n["proposal"]["errorDetails"])
                    exit()
                else:
                    print("Your proposal has been accepted by the network!")
                    print(n)
                done = True
                break

    assert proposal_id != ""

    #####################################################################################
    #                         V O T E   O N   P A R A M E T E R                         #
    #####################################################################################

    # STEP 2 - Let's vote on the proposal

    # IMPORTANT: When voting for a proposal on the Vega Testnet, typically a single
    # YES vote from the proposer will not be enough to vote the proposal into existence.
    # This is because of the network minimum threshold for voting on proposals.
    # A proposer should enlist the help/YES votes from other community members, ideally on the
    # Community forums (https://community.vega.xyz/c/testnet) or Discord (https://vega.xyz/discord)

    # Further documentation on proposal voting and review here: https://docs.testnet.vega.xyz/docs/api-howtos/proposals/

    # __prepare_vote:
    # Prepare a vote for the proposal
    vote = {
        "voteSubmission": {
            "value": "VALUE_YES",  # Can be either VALUE_YES or VALUE_NO
            "proposalId": proposal_id,
        },
        "pubKey": pubkey,
        "propagate": True
    }
    # :prepare_vote__

    # Debugging
    # print("Prepared vote:\n", prepared_vote, "\n")

    # __sign_tx_vote:
    # Sign the vote transaction
    # Note: Setting propagate to true will also submit to a Vega node
    url = f"{wallet_server_url}/api/v1/command/sync"
    response = requests.post(url, headers=headers, json=vote)
    helpers.check_response(response)
    # :sign_tx_vote__

    print("Signed vote on proposal and sent to Vega")

    # Debugging
    print("Signed transaction:\n", response.json(), "\n")
# Help guide users against including api version suffix on url
walletserver_url = helpers.check_wallet_url(walletserver_url)

# __create_wallet:
# Vega node: Create client for accessing public data
datacli = vac.VegaTradingDataClient(node_url_grpc)

# Vega node: Create client for trading (e.g. submitting orders)
tradingcli = vac.VegaTradingClient(node_url_grpc)

# Wallet server: Create a walletclient (see above for details)
walletclient = vac.WalletClient(walletserver_url)
login_response = walletclient.login(wallet_name, wallet_passphrase)
# :create_wallet__
helpers.check_response(login_response)

# __get_market:
# Get a list of markets
markets = datacli.Markets(vac.api.trading.MarketsRequest()).markets
marketID = markets[0].id
# :get_market__

# __generate_keypair:
GENERATE_NEW_KEYPAIR = False
if GENERATE_NEW_KEYPAIR:
    # If you don't already have a keypair, generate one.
    response = walletclient.generatekey(wallet_passphrase, [])
    helpers.check_response(response)
    pubKey = response.json()["key"]["pub"]
else: