'use strict';

var swapModule_entry = require('./swap-module-BZ0C_ywD.js');

class ReownAuthenticationMessenger {
    constructor(params) {
        this.getNonce = params.getNonce;
    }
    async createMessage(input) {
        const params = {
            accountAddress: input.accountAddress,
            chainId: input.chainId,
            version: '1',
            domain: typeof document === 'undefined' ? 'Unknown Domain' : document.location.host,
            uri: typeof document === 'undefined' ? 'Unknown URI' : document.location.href,
            resources: this.resources,
            nonce: await this.getNonce(input),
            issuedAt: this.stringifyDate(new Date()),
            statement: undefined,
            expirationTime: undefined,
            notBefore: undefined
        };
        const methods = {
            toString: () => this.stringify(params)
        };
        return Object.assign(params, methods);
    }
    stringify(params) {
        const networkName = this.getNetworkName(params.chainId);
        return [
            `${params.domain} wants you to sign in with your ${networkName} account:`,
            params.accountAddress,
            params.statement ? `\n${params.statement}\n` : '',
            `URI: ${params.uri}`,
            `Version: ${params.version}`,
            `Chain ID: ${params.chainId}`,
            `Nonce: ${params.nonce}`,
            params.issuedAt && `Issued At: ${params.issuedAt}`,
            params.expirationTime && `Expiration Time: ${params.expirationTime}`,
            params.notBefore && `Not Before: ${params.notBefore}`,
            params.requestId && `Request ID: ${params.requestId}`,
            params.resources?.length &&
                params.resources.reduce((acc, resource) => `${acc}\n- ${resource}`, 'Resources:')
        ]
            .filter(line => typeof line === 'string')
            .join('\n')
            .trim();
    }
    getNetworkName(chainId) {
        const requestedNetworks = swapModule_entry.ChainController.getAllRequestedCaipNetworks();
        return swapModule_entry.NetworkUtil.getNetworkNameByCaipNetworkId(requestedNetworks, chainId);
    }
    stringifyDate(date) {
        return date.toISOString();
    }
}

//
/**
 * This is the configuration for using SIWX with Reown Authentication service.
 * It allows you to authenticate and capture user sessions through the Cloud Dashboard.
 */
class ReownAuthentication {
    constructor(params = {}) {
        this.otpUuid = null;
        this.listeners = {
            sessionChanged: []
        };
        this.localAuthStorageKey =
            params.localAuthStorageKey ||
                swapModule_entry.SafeLocalStorageKeys.SIWX_AUTH_TOKEN;
        this.localNonceStorageKey =
            params.localNonceStorageKey ||
                swapModule_entry.SafeLocalStorageKeys.SIWX_NONCE_TOKEN;
        this.required = params.required ?? true;
        this.messenger = new ReownAuthenticationMessenger({
            getNonce: this.getNonce.bind(this)
        });
    }
    async createMessage(input) {
        return this.messenger.createMessage(input);
    }
    async addSession(session) {
        const response = await this.request({
            method: 'POST',
            key: 'authenticate',
            body: {
                data: session.data,
                message: session.message,
                signature: session.signature,
                clientId: this.getClientId(),
                walletInfo: this.getWalletInfo()
            },
            headers: ['nonce', 'otp']
        });
        this.setStorageToken(response.token, this.localAuthStorageKey);
        this.emit('sessionChanged', session);
        this.setAppKitAccountUser(jwtDecode(response.token));
        this.otpUuid = null;
    }
    async getSessions(chainId, address) {
        try {
            if (!this.getStorageToken(this.localAuthStorageKey)) {
                return [];
            }
            const account = await this.request({
                method: 'GET',
                key: 'me',
                query: {},
                headers: ['auth']
            });
            if (!account) {
                return [];
            }
            const isSameAddress = account.address.toLowerCase() === address.toLowerCase();
            const isSameNetwork = account.caip2Network === chainId;
            if (!isSameAddress || !isSameNetwork) {
                return [];
            }
            const session = {
                data: {
                    accountAddress: account.address,
                    chainId: account.caip2Network
                },
                message: '',
                signature: ''
            };
            this.emit('sessionChanged', session);
            this.setAppKitAccountUser(account);
            return [session];
        }
        catch {
            return [];
        }
    }
    async revokeSession(_chainId, _address) {
        return Promise.resolve(this.clearStorageTokens());
    }
    async setSessions(sessions) {
        if (sessions.length === 0) {
            this.clearStorageTokens();
        }
        else {
            const session = (sessions.find(s => s.data.chainId === swapModule_entry.getActiveCaipNetwork()?.caipNetworkId) || sessions[0]);
            await this.addSession(session);
        }
    }
    getRequired() {
        return this.required;
    }
    async getSessionAccount() {
        if (!this.getStorageToken(this.localAuthStorageKey)) {
            throw new Error('Not authenticated');
        }
        return this.request({
            method: 'GET',
            key: 'me',
            body: undefined,
            query: {
                includeAppKitAccount: true
            },
            headers: ['auth']
        });
    }
    async setSessionAccountMetadata(metadata = null) {
        if (!this.getStorageToken(this.localAuthStorageKey)) {
            throw new Error('Not authenticated');
        }
        return this.request({
            method: 'PUT',
            key: 'account-metadata',
            body: { metadata },
            headers: ['auth']
        });
    }
    on(event, callback) {
        this.listeners[event].push(callback);
        return () => {
            this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
        };
    }
    removeAllListeners() {
        const keys = Object.keys(this.listeners);
        keys.forEach(key => {
            this.listeners[key] = [];
        });
    }
    async requestEmailOtp({ email, account }) {
        const otp = await this.request({
            method: 'POST',
            key: 'otp',
            body: { email, account }
        });
        this.otpUuid = otp.uuid;
        this.messenger.resources = [`email:${email}`];
        return otp;
    }
    confirmEmailOtp({ code }) {
        return this.request({
            method: 'PUT',
            key: 'otp',
            body: { code },
            headers: ['otp']
        });
    }
    async request({ method, key, query, body, headers }) {
        const { projectId, st, sv } = this.getSDKProperties();
        const url = new URL(`${swapModule_entry.ConstantsUtil$1.W3M_API_URL}/auth/v1/${String(key)}`);
        url.searchParams.set('projectId', projectId);
        url.searchParams.set('st', st);
        url.searchParams.set('sv', sv);
        if (query) {
            Object.entries(query).forEach(([queryKey, queryValue]) => url.searchParams.set(queryKey, String(queryValue)));
        }
        const response = await fetch(url, {
            method,
            body: body ? JSON.stringify(body) : undefined,
            headers: Array.isArray(headers)
                ? headers.reduce((acc, header) => {
                    switch (header) {
                        case 'nonce':
                            acc['x-nonce-jwt'] = `Bearer ${this.getStorageToken(this.localNonceStorageKey)}`;
                            break;
                        case 'auth':
                            acc['Authorization'] = `Bearer ${this.getStorageToken(this.localAuthStorageKey)}`;
                            break;
                        case 'otp':
                            if (this.otpUuid) {
                                acc['x-otp'] = this.otpUuid;
                            }
                            break;
                    }
                    return acc;
                }, {})
                : undefined
        });
        if (!response.ok) {
            throw new Error(await response.text());
        }
        if (response.headers.get('content-type')?.includes('application/json')) {
            return response.json();
        }
        return null;
    }
    getStorageToken(key) {
        return swapModule_entry.SafeLocalStorage.getItem(key);
    }
    setStorageToken(token, key) {
        swapModule_entry.SafeLocalStorage.setItem(key, token);
    }
    clearStorageTokens() {
        this.otpUuid = null;
        swapModule_entry.SafeLocalStorage.removeItem(this.localAuthStorageKey);
        swapModule_entry.SafeLocalStorage.removeItem(this.localNonceStorageKey);
        this.emit('sessionChanged', undefined);
    }
    async getNonce() {
        const { nonce, token } = await this.request({
            method: 'GET',
            key: 'nonce'
        });
        this.setStorageToken(token, this.localNonceStorageKey);
        return nonce;
    }
    getClientId() {
        return swapModule_entry.BlockchainApiController.state.clientId;
    }
    getWalletInfo() {
        const walletInfo = swapModule_entry.ChainController.getAccountData()?.connectedWalletInfo;
        if (!walletInfo) {
            return undefined;
        }
        if ('social' in walletInfo && 'identifier' in walletInfo) {
            const social = walletInfo['social'];
            const identifier = walletInfo['identifier'];
            return { type: 'social', social, identifier };
        }
        const { name, icon } = walletInfo;
        let type = 'unknown';
        switch (walletInfo.type) {
            case 'EXTERNAL':
            case 'INJECTED':
            case 'ANNOUNCED':
                type = 'extension';
                break;
            case 'WALLET_CONNECT':
                type = 'walletconnect';
                break;
            default:
                type = 'unknown';
        }
        return {
            type,
            name,
            icon
        };
    }
    getSDKProperties() {
        return swapModule_entry.ApiController._getSdkProperties();
    }
    emit(event, data) {
        this.listeners[event].forEach(listener => listener(data));
    }
    setAppKitAccountUser(session) {
        const { email } = session;
        if (email) {
            Object.values(swapModule_entry.ConstantsUtil$1.CHAIN).forEach(chainNamespace => {
                swapModule_entry.ChainController.setAccountProp('user', { email }, chainNamespace);
            });
        }
    }
}
/**
 * Decodes a JWT token and returns its payload
 * @param token - The JWT token to decode
 * @returns The decoded payload or null if invalid
 */
function jwtDecode(token) {
    // Split the token into parts
    const parts = token.split('.');
    // Check if the token has the correct format (header.payload.signature)
    if (parts.length !== 3) {
        throw new Error('Invalid token');
    }
    // Decode the payload (second part)
    const payload = parts[1];
    if (typeof payload !== 'string') {
        throw new Error('Invalid token');
    }
    // Convert base64url to base64
    const base64 = payload.replace(/-/gu, '+').replace(/_/gu, '/');
    // Add padding if needed
    const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');
    // Decode and parse the JSON
    const decoded = JSON.parse(atob(padded));
    return decoded;
}

exports.ReownAuthentication = ReownAuthentication;
exports.ReownAuthenticationMessenger = ReownAuthenticationMessenger;
//# sourceMappingURL=ReownAuthentication-DBC81XXk.js.map

//# sourceMappingURL=ReownAuthentication-DBC81XXk.js.map