generate static method

String generate({
  1. required String chainId,
  2. required List<String> accounts,
  3. required bool isConnected,
  4. required EIP6963ProviderInfo providerInfo,
})

Implementation

static String generate({
  required String chainId,
  required List<String> accounts,
  required bool isConnected,
  required EIP6963ProviderInfo providerInfo,
}) {
  return '''
  (function() {
    class EthereumProvider extends EventTarget {
      constructor() {
        super();
        this._isConnected = ${isConnected};
        this._chainId = '${chainId}';
        this._accounts = ${jsonEncode(accounts)};
        this._initialized = false;

        // Standard properties
        this.isWallet = true;
        this._networkVersion = parseInt(this._chainId, 16).toString();

        // Initialize
        this._initialize();
      }

      async _initialize() {
        try {
          this._initialized = true;
          if (this._isConnected) {
            this._emit('connect', { chainId: this._chainId });
            if (this._accounts.length > 0) {
              this._emit('accountsChanged', this._accounts);
            }
          }
        } catch (error) {
          console.error('Failed to initialize provider:', error);
        }
      }

      async request(args) {
        if (!args || typeof args !== 'object' || !args.method) {
          throw new Error('Invalid request args');
        }

        const { method, params = [] } = args;

        if (params && !Array.isArray(params)) {
          throw new Error('Invalid params');
        }

        try {
          const result = await window.flutter_inappwebview.callHandler(
            'ethereumRequest',
            {
              method,
              params,
              chainId: this._chainId
            }
          );

          if (method === 'eth_requestAccounts') {
            this._handleAccountsChanged(result);
          }

          return result;
        } catch (error) {
          throw this._processError(error);
        }
      }

      on(eventName, listener) {
        this.addEventListener(eventName, (event) => {
          listener(event.detail);
        });
      }

      once(eventName, listener) {
        const handler = (event) => {
          this.removeEventListener(eventName, handler);
          listener(event.detail);
        };
        this.addEventListener(eventName, handler);
      }

      removeListener(eventName, listener) {
        this.removeEventListener(eventName, listener);
      }

      _emit(eventName, data) {
        const event = new CustomEvent(eventName, { detail: data });
        this.dispatchEvent(event);
      }

      _handleAccountsChanged(accounts) {
        if (Array.isArray(accounts)) {
          const changed = !this._arrayEquals(this._accounts, accounts);
          if (changed) {
            this._accounts = accounts;
            this._emit('accountsChanged', accounts);
          }
        }
      }

      async _handleChainChanged(chainId) {
        if (this._chainId !== chainId) {
          this._chainId = chainId;
          this._networkVersion = parseInt(chainId, 16).toString();
          this._emit('chainChanged', chainId);
        }
      }

      _arrayEquals(a, b) {
        return Array.isArray(a) && Array.isArray(b) &&
               a.length === b.length &&
               a.every((val, index) => val === b[index]);
      }

      _processError(error) {
        if (typeof error === 'string') {
          return new Error(error);
        }
        return error;
      }

      get isConnected() {
        return this._isConnected;
      }

      disconnect() {
        this._isConnected = false;
        this._accounts = [];
        this._emit('disconnect', {});
        this._emit('accountsChanged', []);
      }

      enable() {
        console.warn('ethereum.enable() is deprecated, use ethereum.request({method: "eth_requestAccounts"}) instead.');
        return this.request({ method: 'eth_requestAccounts' });
      }

      get selectedAddress() {
        return this._isConnected ? (this._accounts[0] || null) : null;
      }

      get chainId() {
        return this._chainId;
      }

      get networkVersion() {
        return this._networkVersion;
      }

      // ✅ BỔ SUNG CÁC METHODS THIẾU
      async send(method, params) {
        return this.request({ method, params });
      }

      async sendAsync(payload, callback) {
        try {
          const result = await this.request(payload);
          callback(null, { id: payload.id, result });
        } catch (error) {
          callback(error, { id: payload.id, error: { message: error.message, code: -32000 } });
        }
      }

      // ✅ SUPPORT CHO WEB3.JS LEGACY
      get currentProvider() {
        return this;
      }

      // ✅ SUPPORT CHO EIP-1193 EVENTS (alias cho addEventListener)
      addListener(eventName, listener) {
        this.addEventListener(eventName, (event) => {
          listener(event.detail);
        });
      }

      // ✅ SUPPORT CHO METAMASK COMPATIBILITY
      get isMetaMask() {
        return true;
      }

      // ✅ SUPPORT CHO PERSONAL METHODS
      async personalSign(message, address) {
        return this.request({ method: 'personal_sign', params: [message, address] });
      }

      async signTypedData(typedData, address) {
        return this.request({ method: 'eth_signTypedData_v4', params: [address, typedData] });
      }

      // ✅ SUPPORT CHO WALLET METHODS
      async requestPermissions() {
        return this.request({ method: 'wallet_requestPermissions', params: [{ eth_accounts: {} }] });
      }

      async getPermissions() {
        return this.request({ method: 'wallet_getPermissions' });
      }

      // ✅ SUPPORT CHO NETWORK METHODS
      async switchChain(chainId) {
        return this.request({ method: 'wallet_switchEthereumChain', params: [{ chainId }] });
      }

      async addChain(chainParams) {
        return this.request({ method: 'wallet_addEthereumChain', params: [chainParams] });
      }

      // ✅ SUPPORT CHO ACCOUNT METHODS
      async getAccounts() {
        return this.request({ method: 'eth_accounts' });
      }

      async getBalance(address, blockNumber = 'latest') {
        return this.request({ method: 'eth_getBalance', params: [address, blockNumber] });
      }

      // ✅ SUPPORT CHO TRANSACTION METHODS
      async sendTransaction(transaction) {
        return this.request({ method: 'eth_sendTransaction', params: [transaction] });
      }

      async signTransaction(transaction) {
        return this.request({ method: 'eth_signTransaction', params: [transaction] });
      }

      // ✅ SUPPORT CHO BLOCK METHODS
      async getBlockNumber() {
        return this.request({ method: 'eth_blockNumber' });
      }

      async getBlock(blockHashOrNumber, returnTransactionObjects = false) {
        return this.request({ method: 'eth_getBlockByHash', params: [blockHashOrNumber, returnTransactionObjects] });
      }

      // ✅ SUPPORT CHO CONTRACT METHODS
      async call(transaction, blockNumber = 'latest') {
        return this.request({ method: 'eth_call', params: [transaction, blockNumber] });
      }

      async estimateGas(transaction) {
        return this.request({ method: 'eth_estimateGas', params: [transaction] });
      }

      // ✅ SUPPORT CHO UTILITY METHODS
      async getGasPrice() {
        return this.request({ method: 'eth_gasPrice' });
      }

      async getTransactionCount(address, blockNumber = 'latest') {
        return this.request({ method: 'eth_getTransactionCount', params: [address, blockNumber] });
      }

      // ✅ SUPPORT CHO FILTER METHODS
      async newFilter(filterOptions) {
        return this.request({ method: 'eth_newFilter', params: [filterOptions] });
      }

      async getFilterChanges(filterId) {
        return this.request({ method: 'eth_getFilterChanges', params: [filterId] });
      }

      async uninstallFilter(filterId) {
        return this.request({ method: 'eth_uninstallFilter', params: [filterId] });
      }

      // ✅ SUPPORT CHO SUBSCRIPTION METHODS
      async subscribe(subscriptionType, params) {
        return this.request({ method: 'eth_subscribe', params: [subscriptionType, ...params] });
      }

      async unsubscribe(subscriptionId) {
        return this.request({ method: 'eth_unsubscribe', params: [subscriptionId] });
      }
    }

    if (typeof window.ethereum === 'undefined') {
      const provider = new EthereumProvider();
      window.ethereum = provider;

      if (typeof window.web3 === 'undefined') {
        window.web3 = {
          currentProvider: provider
        };
      }

      const walletInfo = {
          uuid: "${providerInfo.uuid}",
          name: "${providerInfo.name}",
          icon: "${providerInfo.icon}",
          rdns: "${providerInfo.rdns}",
      };

      const announcement = {
          info: walletInfo,
          provider: provider
      };

      window.addEventListener('eip6963:requestProvider', (event) => {
          window.dispatchEvent(new CustomEvent('eip6963:announceProvider', {
              detail: announcement
          }));
      });

      console.log('EIP-6963 wallet provider injected');
    }
  })();
  ''';
}