# !!!
# WARNING: This file is autogenerated
# Only modify code within MANUAL() sections
# or your changes may be overwritten later!
# !!!

from typing import Any, Dict, Optional

from stytch.core.api_base import ApiBase
from stytch.core.http.client import AsyncClient, SyncClient
from stytch.models.crypto_wallets import AuthenticateResponse, AuthenticateStartResponse


class CryptoWallets:
    def __init__(
        self,
        api_base: ApiBase,
        sync_client: SyncClient,
        async_client: AsyncClient,
    ) -> None:
        self.api_base = api_base
        self.sync_client = sync_client
        self.async_client = async_client

    @property
    def sub_url(self) -> str:
        return "crypto_wallets"

    def authenticate_start(
        self,
        crypto_wallet_address: str,
        crypto_wallet_type: str,
        user_id: Optional[str] = None,
        session_token: Optional[str] = None,
        session_jwt: Optional[str] = None,
    ) -> AuthenticateStartResponse:
        """[Stytch docs](https://stytch.com/docs/api/crypto-wallet-authenticate-start)

        Initiate the authentication of a crypto wallet. After calling this endpoint, the user will need to sign a message containing only the returned `challenge` field.

        Parameters:

        - `crypto_wallet_type`: The type of wallet to authenticate. Currently `ethereum` and `solana` are supported. Wallets for any EVM-compatible chains (such as Polygon or BSC) are also supported and are grouped under the `ethereum` type.

        - `crypto_wallet_address`: The address to authenticate.

        - `user_id`: The `user_id` belonging to the user you wish to associate the address with. If no form of user association is provided and the address is not associated with an existing Stytch user in your Project, a new user will be created.

        - `session_token`: The `session_token` belonging to the user you wish to associate the address with. If no form of user association is provided and the address is not associated with an existing Stytch user in your Project, a new user will be created.

        - `session_jwt`: The `session_jwt` belonging to the user you wish to associate the address with. If no form of user association is provided and the address is not associated with an existing Stytch user in your Project, a new user will be created.
        """  # noqa

        payload: Dict[str, Any] = {
            "crypto_wallet_address": crypto_wallet_address,
            "crypto_wallet_type": crypto_wallet_type,
        }

        if user_id is not None:
            payload["user_id"] = user_id
        if session_token is not None:
            payload["session_token"] = session_token
        if session_jwt is not None:
            payload["session_jwt"] = session_jwt

        url = self.api_base.route_with_sub_url(self.sub_url, "authenticate/start")

        res = self.sync_client.post(url, json=payload)
        return AuthenticateStartResponse.from_json(res.response.status_code, res.json)

    async def authenticate_start_async(
        self,
        crypto_wallet_address: str,
        crypto_wallet_type: str,
        user_id: Optional[str] = None,
        session_token: Optional[str] = None,
        session_jwt: Optional[str] = None,
    ) -> AuthenticateStartResponse:
        """[Stytch docs](https://stytch.com/docs/api/crypto-wallet-authenticate-start)

        Initiate the authentication of a crypto wallet. After calling this endpoint, the user will need to sign a message containing only the returned `challenge` field.

        Parameters:

        - `crypto_wallet_type`: The type of wallet to authenticate. Currently `ethereum` and `solana` are supported. Wallets for any EVM-compatible chains (such as Polygon or BSC) are also supported and are grouped under the `ethereum` type.

        - `crypto_wallet_address`: The address to authenticate.

        - `user_id`: The `user_id` belonging to the user you wish to associate the address with. If no form of user association is provided and the address is not associated with an existing Stytch user in your Project, a new user will be created.

        - `session_token`: The `session_token` belonging to the user you wish to associate the address with. If no form of user association is provided and the address is not associated with an existing Stytch user in your Project, a new user will be created.

        - `session_jwt`: The `session_jwt` belonging to the user you wish to associate the address with. If no form of user association is provided and the address is not associated with an existing Stytch user in your Project, a new user will be created.
        """  # noqa

        payload: Dict[str, Any] = {
            "crypto_wallet_address": crypto_wallet_address,
            "crypto_wallet_type": crypto_wallet_type,
        }

        if user_id is not None:
            payload["user_id"] = user_id
        if session_token is not None:
            payload["session_token"] = session_token
        if session_jwt is not None:
            payload["session_jwt"] = session_jwt

        url = self.api_base.route_with_sub_url(self.sub_url, "authenticate/start")

        res = await self.async_client.post(url, json=payload)
        return AuthenticateStartResponse.from_json(res.response.status, res.json)

    def authenticate(
        self,
        crypto_wallet_address: str,
        crypto_wallet_type: str,
        signature: str,
        session_token: Optional[str] = None,
        session_jwt: Optional[str] = None,
        session_duration_minutes: Optional[int] = None,
        session_custom_claims: Optional[Dict[str, Any]] = None,
    ) -> AuthenticateResponse:
        """[Stytch docs](https://stytch.com/docs/api/crypto-wallet-authenticate)

        Complete the authentication of a crypto wallet by passing the signature.

        Parameters:

        - `crypto_wallet_type`: The type of wallet to authenticate. Currently `ethereum` and `solana` are supported.

        - `crypto_wallet_address`: The address to authenticate.

        - `signature`: The signature from the message.

        - `session_custom_claims`: Add a custom claims map to the session being authenticated. Claims are only created if a session is initialized by providing a value in `session duration minutes`. Claims will be included on the session object and in the JWT. To update a key in an existing session, supply a new value. To delete a key, supply a null value

          Custom claims made with reserved claims ("iss", "sub", "aud", "exp", "nbf", "iat", "jti") will be ignored. Total custom claims size cannot exceed four kilobytes

        - `session_duration_minutes`: Set the session lifetime to be this many minutes from now. This will start a new session if one doesn't already exist, returning both an opaque `session_token` and `session_jwt` for this session. Remember that the `session_jwt` will have a fixed lifetime of five minutes regardless of the underlying session duration, and will need to be refreshed over time.

          This value must be a minimum of 5 and a maximum of 129600 minutes (90 days).

          If a `session_token` or `session_jwt` is provided then a successful authentication will continue to extend the session this many minutes.

          If the `session_duration_minutes` parameter is not specified, a Stytch session will not be created.

        - `session_jwt`: Reuse an existing session instead of creating a new one. If you provide us with a `session_jwt`, then we'll update the session represented by this JWT with this crypto wallet factor. If this `session_jwt` belongs to a different user than the one tied to the address, the `session_jwt` will be ignored. This endpoint will error if both `session_token` and `session_jwt` are provided.

        - `session_token`: Reuse an existing session instead of creating a new one. If you provide us with a `session_token`, then we'll update the session represented by this session token with this crypto wallet factor. If this `session_token` belongs to a different user than the one tied to the address, the `session_token` will be ignored. This endpoint will error if both session_token and `session_jwt` are provided.
        """  # noqa

        payload: Dict[str, Any] = {
            "crypto_wallet_address": crypto_wallet_address,
            "crypto_wallet_type": crypto_wallet_type,
            "signature": signature,
        }

        if session_token is not None:
            payload["session_token"] = session_token
        if session_jwt is not None:
            payload["session_jwt"] = session_jwt
        if session_duration_minutes is not None:
            payload["session_duration_minutes"] = session_duration_minutes
        if session_custom_claims is not None:
            payload["session_custom_claims"] = session_custom_claims

        url = self.api_base.route_with_sub_url(self.sub_url, "authenticate")

        res = self.sync_client.post(url, json=payload)
        return AuthenticateResponse.from_json(res.response.status_code, res.json)

    async def authenticate_async(
        self,
        crypto_wallet_address: str,
        crypto_wallet_type: str,
        signature: str,
        session_token: Optional[str] = None,
        session_jwt: Optional[str] = None,
        session_duration_minutes: Optional[int] = None,
        session_custom_claims: Optional[Dict[str, Any]] = None,
    ) -> AuthenticateResponse:
        """[Stytch docs](https://stytch.com/docs/api/crypto-wallet-authenticate)

        Complete the authentication of a crypto wallet by passing the signature.

        Parameters:

        - `crypto_wallet_type`: The type of wallet to authenticate. Currently `ethereum` and `solana` are supported.

        - `crypto_wallet_address`: The address to authenticate.

        - `signature`: The signature from the message.

        - `session_custom_claims`: Add a custom claims map to the session being authenticated. Claims are only created if a session is initialized by providing a value in `session duration minutes`. Claims will be included on the session object and in the JWT. To update a key in an existing session, supply a new value. To delete a key, supply a null value

          Custom claims made with reserved claims ("iss", "sub", "aud", "exp", "nbf", "iat", "jti") will be ignored. Total custom claims size cannot exceed four kilobytes

        - `session_duration_minutes`: Set the session lifetime to be this many minutes from now. This will start a new session if one doesn't already exist, returning both an opaque `session_token` and `session_jwt` for this session. Remember that the `session_jwt` will have a fixed lifetime of five minutes regardless of the underlying session duration, and will need to be refreshed over time.

          This value must be a minimum of 5 and a maximum of 129600 minutes (90 days).

          If a `session_token` or `session_jwt` is provided then a successful authentication will continue to extend the session this many minutes.

          If the `session_duration_minutes` parameter is not specified, a Stytch session will not be created.

        - `session_jwt`: Reuse an existing session instead of creating a new one. If you provide us with a `session_jwt`, then we'll update the session represented by this JWT with this crypto wallet factor. If this `session_jwt` belongs to a different user than the one tied to the address, the `session_jwt` will be ignored. This endpoint will error if both `session_token` and `session_jwt` are provided.

        - `session_token`: Reuse an existing session instead of creating a new one. If you provide us with a `session_token`, then we'll update the session represented by this session token with this crypto wallet factor. If this `session_token` belongs to a different user than the one tied to the address, the `session_token` will be ignored. This endpoint will error if both session_token and `session_jwt` are provided.
        """  # noqa

        payload: Dict[str, Any] = {
            "crypto_wallet_address": crypto_wallet_address,
            "crypto_wallet_type": crypto_wallet_type,
            "signature": signature,
        }

        if session_token is not None:
            payload["session_token"] = session_token
        if session_jwt is not None:
            payload["session_jwt"] = session_jwt
        if session_duration_minutes is not None:
            payload["session_duration_minutes"] = session_duration_minutes
        if session_custom_claims is not None:
            payload["session_custom_claims"] = session_custom_claims

        url = self.api_base.route_with_sub_url(self.sub_url, "authenticate")

        res = await self.async_client.post(url, json=payload)
        return AuthenticateResponse.from_json(res.response.status, res.json)
