next.js Runtime.callFunctionOn抛出异常:错误:LavaMoat -global的属性“Proxy”在scuttling模式下无法访问

a9wyjsp7  于 2023-05-17  发布在  其他
关注(0)|答案(1)|浏览(562)

我正在开发一个Next.js应用程序,当我开始用selenium-webdriver做一些测试时,我开始遇到一些问题。我的Web应用使用Metamask钱包进行身份验证。问题是当试图在一个测试窗口上导入一个钱包时, selenium 能够在我的网络应用程序中登录。我尝试了很多方法来做到这一点:

  • JavaScript测试尝试下载metamask或尝试打开安装了metamask的新chromewindow
  • Python使用auto-metamask进行测试,尝试在新窗口中导入metamask...

Ubuntu 22.04 Chrome版本为113.0.5672.92,chromedriver版本为113.0.5672.63,selenium-webdriver版本为4.9.1,python3版本为3.10.6。

代码如下:

import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

def test_login_button():
    EXTENSION_PATH = '/nkbihfbeogaeaoehlefnkodbefgpgknn-10.30.1-www.Crx4Chrome.com.crx' # Path from the crx downloaded file in my pc (I have tried a bunch of them downloaded from different sites)
    SECRET_RECOVERY_PHRASE = "my seed phrase"
    NEW_PASSWORD = "password"

    opt = webdriver.ChromeOptions()
    opt.add_extension(EXTENSION_PATH)
    #opt.add_argument("--disable-extensions-except=nkbihfbeogaeaoehlefnkodbefgpgknn") (this approach does not work, I tried to disable all extensions except metamask but it does not work when executing the code because it does not find the extension)
    #opt.add_argument("--user-data-dir=./path/to/google-chrome/Profile 1") (this approach did not work when trying to open an existing profile)

    driver = webdriver.Chrome(options=opt)
    time.sleep(3)

    driver.switch_to.window(driver.window_handles[1])
    time.sleep(3)

    wait = WebDriverWait(driver, 30)
    element = wait.until(EC.presence_of_element_located((By.XPATH, '//button[text()="Importar una cartera existente"]'))) # This is the line which gives an error
    element.click()
    #driver.find_element(By.XPATH, '//*[text()="Importar una cartera existente"]').click()

    # Rest of the code

获取错误:

>       element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[text()="Importar una cartera existente"]')))

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7fcb4e1556f0>
response = {'status': 500, 'value': '{"value":{"error":"unknown error","message":"unknown error: Runtime.callFunctionOn threw exc...\\n#19 0x55775845dc97 \\u003Cunknown>\\n#20 0x55775846e113 \\u003Cunknown>\\n#21 0x7fdaf2c94b43 \\u003Cunknown>\\n"}}'}

selenium.common.exceptions.WebDriverException: Message: unknown error: Runtime.callFunctionOn threw exception: Error: LavaMoat - property "Proxy" of globalThis is inaccessible under scuttling mode. To learn more visit https://github.com/LavaMoat/LavaMoat/pull/360.
E         at get (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/runtime-lavamoat.js:11200:17)
E         at serializationGuard (<anonymous>:198:67)
E         at buildError (<anonymous>:319:27)
E         (Session info: chrome=113.0.5672.92)`

我已经遵循了不同的教程:

我只是想能够进行一些测试,以便与metamask钱包进行交互,以便我的应用程序能够登录它,然后与提供逻辑的智能合约进行交互。

wnrlj8wa

wnrlj8wa1#

重要提示:此解决方案在2023/05/15起作用,这很重要,因为两年前这个问题没有发生,因为这个安全实现没有上传到MetaMask扩展。在未来,此功能可能会发生变化,因此此方法可能不会有用

  • MetaMask的一位开发人员写信给我,分享了一个问题的链接,他在那里指定了问题的解决方案。请参见:https://github.com/LavaMoat/LavaMoat/pull/360#issuecomment-1547726986
    • 帖子评论摘要 *:看起来LavaMoat是一个沙箱,它“ Package ”了JavaScript代码,这样它就不能访问一些它不应该访问的API,而且可能会导致安全问题。因此,当使用外部webdriver时,我们会看到这个错误。他的话是:“这是我们目前感觉良好的权衡”,因为他们更喜欢添加额外的安全层,而不是让代码访问API。

溶液

  • 开发人员告诉我,我可以建立自己的MetaMask版本与此安全功能禁用。这降低了安全性,但在我的情况下没有问题,因为我想在开发环境中实现它,以测试我的Next.js应用程序与selenium-webdriver。

步骤

1.转到metamask-extension GitHub repo并将其克隆到您的计算机中:https://github.com/MetaMask/metamask-extension。您可以阅读README.md文件以查找更多信息。
1.在克隆的文件夹中,转到index.js文件,将第92行(scuttleGlobalThis: applyLavaMoat && shouldScuttle)替换为scuttleGlobalThis: false
1.在项目的根文件夹中,运行cp .metamaskcr.dist .metamaskcr

  • 打开.metamaskcr文件并更改以下数据:
  • INFURA_PROJECT_ID='replace with your infura project id',请参阅https://docs.infura.io/infura/,如果您没有Infura帐户,请创建一个Infura帐户并创建一个项目https://www.infura.io/
  • PASSWORD='replace with a password';这样你就不必每次都介绍它了。
  • SEGMENT_WRITE_KEY='replace with your segment write key',请参阅https://segment.com/docs/connections/find-writekey/,如果您没有Segment帐户,请创建一个Segment帐户,并创建一个项目https://segment.com/docs/connections/find-writekey/
  • 在此之后,从项目的根文件夹运行yarn installyarn dist。这将生成一个/dist文件夹,其中包含/chrome/firefox/sourcemaps文件夹。python代码中的新EXTENSION_PATH应该是项目中/chrome文件夹的路径(如果使用firefox,则是/firefox)。
  • 所以最终的测试代码是:
def test_login_button():
      EXTENSION_PATH = '/home/adrib/Universidad/4o/TFG/Proyecto/metamask-extension/dist/chrome'

      opt = Options()
      opt.add_argument(f'--load-extension={EXTENSION_PATH}')

      driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=opt)
      time.sleep(3)
      driver.switch_to.window(driver.window_handles[1])
      original_window = driver.current_window_handle

      time.sleep(3)

      time.sleep(3)
      WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, "/html/body/div[1]/div/div[2]/div/div/div/ul/li[1]/div/input"))).click()

      WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div/div[2]/div/div/div/ul/li[3]/button"))).click()

      WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, "//*[@id='app-content']/div/div[2]/div/div/div[2]/div/div[2]/div[1]/button"))).click()

      WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, "//*[@id='app-content']/div/div[2]/div/div/div/div[5]/div[1]/footer/button[1]"))).click()

特别感谢MetaMask的开发人员,他回复得非常快,并提供了来自GitHub的线程,我从中得到了这个问题的答案,@weizman。

相关问题