diff options
-rw-r--r-- | .circleci/config.yml | 22 | ||||
-rw-r--r-- | package-lock.json | 152 | ||||
-rw-r--r-- | package.json | 6 | ||||
-rw-r--r-- | test/screens/func.js | 18 | ||||
-rw-r--r-- | test/screens/new-ui.js | 260 |
5 files changed, 17 insertions, 441 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 8144aac61..a3cb6cd71 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -55,16 +55,10 @@ workflows: # - test-e2e-beta-drizzle - test-integration-flat-chrome - test-integration-flat-firefox - - job-screens: - requires: - - prep-deps-npm - - prep-build - - all-tests-pass - job-publish-prerelease: requires: - prep-deps-npm - prep-build - - job-screens - all-tests-pass - job-publish-release: filters: @@ -74,7 +68,6 @@ workflows: - prep-deps-npm - prep-build # - prep-docs - - job-screens - all-tests-pass jobs: @@ -213,21 +206,6 @@ jobs: path: test-artifacts destination: test-artifacts - job-screens: - docker: - - image: circleci/node:10.16-browsers - steps: - - checkout - - attach_workspace: - at: . - - run: - name: Test - command: npm run test:screens - - persist_to_workspace: - root: . - paths: - - test-artifacts - job-publish-prerelease: docker: - image: circleci/node:10.16-browsers diff --git a/package-lock.json b/package-lock.json index cb7f91b06..fe569a640 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6252,6 +6252,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "dev": true, "requires": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" @@ -7692,12 +7693,6 @@ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, - "arch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.0.tgz", - "integrity": "sha1-NhOqRhSQZLPB8GB5Gb8dR4boKIk=", - "dev": true - }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -9988,6 +9983,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "dev": true, "requires": { "readable-stream": "^2.0.5" } @@ -11737,33 +11733,6 @@ "tiny-emitter": "^2.0.0" } }, - "clipboardy": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.3.tgz", - "integrity": "sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA==", - "dev": true, - "requires": { - "arch": "^2.1.0", - "execa": "^0.8.0" - }, - "dependencies": { - "execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - } - } - }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -12261,7 +12230,8 @@ "convert-source-map": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true }, "cookie": { "version": "0.3.1", @@ -32766,12 +32736,6 @@ } } }, - "gifencoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gifencoder/-/gifencoder-1.1.0.tgz", - "integrity": "sha512-MVh++nximxsp8NaNRfS1+MmCviZ4wi7HhuvX8eHrfNn//1mqi8Eb03tKs6Z+lIIcSEySJ6PmS1VPZ+HdtEMlfg==", - "dev": true - }, "git-up": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.1.tgz", @@ -35903,12 +35867,6 @@ "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, - "image-size": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.2.tgz", - "integrity": "sha512-pH3vDzpczdsKHdZ9xxR3O46unSjisgVx0IImay7Zz2EdhRVbCkj+nthx9OuuWEhakx9FAO+fNVGrF0rZ2oMOvw==", - "dev": true - }, "immediate": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", @@ -37536,7 +37494,8 @@ "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true }, "jsonpointer": { "version": "4.0.1", @@ -38784,21 +38743,6 @@ "pify": "^3.0.0" } }, - "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", - "dev": true - }, - "make-error-cause": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", - "dev": true, - "requires": { - "make-error": "^1.2.0" - } - }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -42455,7 +42399,8 @@ "opener": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", - "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=" + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", + "dev": true }, "opn": { "version": "5.2.0", @@ -42470,6 +42415,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, "requires": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" @@ -42478,7 +42424,8 @@ "minimist": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true } } }, @@ -43275,74 +43222,6 @@ "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", "dev": true }, - "png-file-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/png-file-stream/-/png-file-stream-1.1.0.tgz", - "integrity": "sha512-uZuSd4yuLXik2H/XqR+7hcGU30nCeBHhPsejR8JA91oKom57aeL379hO5ZJ4SS1Nujk/hDUN0VE8UiT+FuwNZg==", - "dev": true, - "requires": { - "glob-stream": "^6.1.0", - "png-js": "~0.1.1", - "through2": "~0.2.3" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "0.2.3", - "resolved": "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - } - }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "requires": { - "object-keys": "~0.4.0" - } - } - } - }, - "png-js": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/png-js/-/png-js-0.1.1.tgz", - "integrity": "sha1-HMfCEjA6yr50Jj7DrHgAlYAkLZM=", - "dev": true - }, "po2json": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/po2json/-/po2json-0.4.5.tgz", @@ -51900,7 +51779,8 @@ "umd": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", - "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=" + "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "dev": true }, "unc-path-regex": { "version": "0.1.2", @@ -52012,7 +51892,8 @@ "uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true }, "unique-filename": { "version": "1.1.1", @@ -53907,7 +53788,8 @@ "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true }, "worker-farm": { "version": "1.7.0", diff --git a/package.json b/package.json index d59b3b92e..59abcfe2c 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,6 @@ "test:web3:chrome": "SELENIUM_BROWSER=chrome test/e2e/run-web3.sh", "test:web3:firefox": "SELENIUM_BROWSER=firefox test/e2e/run-web3.sh", "test:e2e:firefox": "SELENIUM_BROWSER=firefox test/e2e/run-all.sh", - "test:screens": "shell-parallel -s 'npm run ganache:start' -x 'sleep 3 && npm run test:screens:run'", - "test:screens:run": "node test/screens/new-ui.js", "test:coverage": "nyc --reporter=text --reporter=html npm run test:unit && npm run test:coveralls-upload", "test:coveralls-upload": "if [ $COVERALLS_REPO_TOKEN ]; then nyc report --reporter=text-lcov | coveralls; fi", "test:flat": "npm run test:flat:build && karma start test/flat.conf.js", @@ -187,7 +185,6 @@ "browserify": "^16.2.3", "chai": "^4.1.0", "chromedriver": "^2.41.0", - "clipboardy": "^1.2.3", "coveralls": "^3.0.0", "cross-env": "^5.1.4", "css-loader": "^2.1.1", @@ -209,7 +206,6 @@ "ganache-core": "^2.5.5", "geckodriver": "^1.16.2", "gh-pages": "^1.2.0", - "gifencoder": "^1.1.0", "gulp": "^4.0.0", "gulp-autoprefixer": "^5.0.0", "gulp-babel": "^7.0.0", @@ -228,7 +224,6 @@ "gulp-watch": "^5.0.1", "gulp-zip": "^4.0.0", "http-server": "^0.11.1", - "image-size": "^0.6.2", "isomorphic-fetch": "^2.2.1", "jsdoc": "^3.6.2", "jsdom": "^11.2.0", @@ -247,7 +242,6 @@ "node-sass": "^4.12.0", "nyc": "^13.0.0", "path": "^0.12.7", - "png-file-stream": "^1.1.0", "prepend-file": "^1.3.1", "proxyquire": "2.0.1", "qs": "^6.2.0", diff --git a/test/screens/func.js b/test/screens/func.js deleted file mode 100644 index 733225565..000000000 --- a/test/screens/func.js +++ /dev/null @@ -1,18 +0,0 @@ -require('chromedriver') -const webdriver = require('selenium-webdriver') - -exports.delay = function delay (time) { - return new Promise(resolve => setTimeout(resolve, time)) -} - - -exports.buildWebDriver = function buildWebDriver (extPath) { - return new webdriver.Builder() - .withCapabilities({ - chromeOptions: { - args: [`load-extension=${extPath}`], - }, - }) - .forBrowser('chrome') - .build() -} diff --git a/test/screens/new-ui.js b/test/screens/new-ui.js deleted file mode 100644 index 92d1b8378..000000000 --- a/test/screens/new-ui.js +++ /dev/null @@ -1,260 +0,0 @@ -const path = require('path') -const fs = require('fs') -const pify = require('pify') -const mkdirp = require('mkdirp') -const rimraf = require('rimraf') -const webdriver = require('selenium-webdriver') -const endOfStream = require('end-of-stream') -const clipboardy = require('clipboardy') -const Ethjs = require('ethjs') -const GIFEncoder = require('gifencoder') -const pngFileStream = require('png-file-stream') -const sizeOfPng = require('image-size/lib/types/png') -const By = webdriver.By -const localesIndex = require('../../app/_locales/index.json') -const { delay, buildChromeWebDriver, getExtensionIdChrome } = require('../e2e/func') - -const eth = new Ethjs(new Ethjs.HttpProvider('http://localhost:8545')) - -let driver -let screenshotCount = 0 - -captureAllScreens() -.then(async () => { - // build screenshots into gif - console.log('building gif...') - await generateGif() - - await driver.quit() - process.exit() -}) -.catch(async (err) => { - try { - console.error(err) - verboseReportOnFailure({ title: 'something broke' }) - } catch (err) { - console.error(err) - } - - await driver.quit() - process.exit(1) -}) - - -async function captureAllScreens () { - // common names - let tabs - - await cleanScreenShotDir() - - const extPath = path.resolve('dist/chrome') - driver = buildChromeWebDriver(extPath) - const extensionId = await getExtensionIdChrome(driver) - - await driver.get(`chrome-extension://${extensionId}/home.html`) - await delay(500) - tabs = await driver.getAllWindowHandles() - await driver.switchTo().window(tabs[0]) - await delay(1000) - await setProviderType('localhost') - await delay(300) - - // click try new ui - await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-row.flex-center.flex-grow > p')).click() - await delay(300) - - // close metamask homepage and extra home.html - tabs = await driver.getAllWindowHandles() - // metamask homepage is opened on prod, not dev - if (tabs.length > 2) { - await driver.switchTo().window(tabs[2]) - driver.close() - } - await driver.switchTo().window(tabs[1]) - driver.close() - await driver.switchTo().window(tabs[0]) - await delay(300) - await captureLanguageScreenShots('welcome-new-ui') - - // setup account - await delay(1000) - await driver.findElement(By.css('body')).click() - await delay(300) - await captureLanguageScreenShots('welcome') - - await driver.findElement(By.css('button')).click() - await captureLanguageScreenShots('create password') - - const password = '123456789' - const passwordBox = await driver.findElement(By.css('input#create-password')) - const passwordBoxConfirm = await driver.findElement(By.css('input#confirm-password')) - passwordBox.sendKeys(password) - passwordBoxConfirm.sendKeys(password) - await delay(500) - await captureLanguageScreenShots('choose-password-filled') - - await driver.findElement(By.css('button')).click() - await delay(500) - await captureLanguageScreenShots('unique account image') - - await driver.findElement(By.css('button')).click() - await delay(500) - await captureLanguageScreenShots('privacy note') - - await driver.findElement(By.css('button')).click() - await delay(300) - await captureLanguageScreenShots('terms') - - await delay(300) - const element = driver.findElement(By.linkText('Attributions')) - await driver.executeScript('arguments[0].scrollIntoView(true)', element) - await delay(300) - await captureLanguageScreenShots('terms-scrolled') - - await driver.findElement(By.css('button')).click() - await delay(300) - await captureLanguageScreenShots('secret backup phrase') - - await driver.findElement(By.css('button')).click() - await delay(300) - await captureLanguageScreenShots('secret backup phrase') - - await driver.findElement(By.css('.backup-phrase__reveal-button')).click() - await delay(300) - await captureLanguageScreenShots('secret backup phrase - reveal') - - const seedPhrase = await driver.findElement(By.css('.backup-phrase__secret-words')).getText() - const seedPhraseWords = seedPhrase.split(' ') - await driver.findElement(By.css('button')).click() - await delay(300) - await captureLanguageScreenShots('confirm secret backup phrase') - - // enter seed phrase - const seedPhraseButtons = await driver.findElements(By.css('.backup-phrase__confirm-seed-options > button')) - const seedPhraseButtonWords = await Promise.all(seedPhraseButtons.map(button => button.getText())) - for (const targetWord of seedPhraseWords) { - const wordIndex = seedPhraseButtonWords.indexOf(targetWord) - if (wordIndex === -1) throw new Error(`Captured seed phrase word "${targetWord}" not in found seed phrase button options ${seedPhraseButtonWords.join(' ')}`) - await driver.findElement(By.css(`.backup-phrase__confirm-seed-options > button:nth-child(${wordIndex + 1})`)).click() - await delay(100) - } - await captureLanguageScreenShots('confirm secret backup phrase - words selected correctly') - - await driver.findElement(By.css('.backup-phrase__content-wrapper .first-time-flow__button')).click() - await delay(300) - await captureLanguageScreenShots('metamask post-initialize greeter screen deposit ether') - - await driver.findElement(By.css('.page-container__header-close')).click() - await delay(300) - await captureLanguageScreenShots('metamask account main screen') - - // account details + export private key - await driver.findElement(By.css('.wallet-view__name-container > .wallet-view__details-button')).click() - await delay(300) - await captureLanguageScreenShots('metamask account detail screen') - - await driver.findElement(By.css('.account-modal__button:nth-of-type(2)')).click() - await delay(300) - await captureLanguageScreenShots('metamask account detail export private key screen - initial') - - await driver.findElement(By.css('.private-key-password > input')).sendKeys(password) - await delay(300) - await captureLanguageScreenShots('metamask account detail export private key screen - password entered') - - await driver.findElement(By.css('.btn-primary.btn--large.export-private-key__button')).click() - await delay(300) - await captureLanguageScreenShots('metamask account detail export private key screen - reveal key') - - await driver.findElement(By.css('.export-private-key__button')).click() - await delay(300) - await captureLanguageScreenShots('metamask account detail export private key screen - done') - - // get eth from Ganache - // const viewAddressButton = await driver.findElement(By.css('.wallet-view__address')) - // await driver.actions({ bridge: true }).move({ origin: viewAddressButton }).perform() - // console.log('driver.actions', driver.actions({ bridge: true })) - // await delay(300) - // await captureLanguageScreenShots('metamask home - hover copy address') - - await driver.findElement(By.css('.wallet-view__address')).click() - await delay(100) - await captureLanguageScreenShots('metamask home - hover copy address') - - const primaryAddress = clipboardy.readSync() - await requestEther(primaryAddress) - // wait for block polling - await delay(10000) - await captureLanguageScreenShots('metamask home - has ether') - -} - - -async function captureLanguageScreenShots (label) { - const nonEnglishLocales = localesIndex.filter(localeMeta => localeMeta.code !== 'en') - // take english shot - await captureScreenShot(`${label} (en)`) - for (const localeMeta of nonEnglishLocales) { - // set locale and take shot - await setLocale(localeMeta.code) - await delay(300) - await captureScreenShot(`${label} (${localeMeta.code})`) - } - // return locale to english - await setLocale('en') - await delay(300) -} - -async function setLocale (code) { - await driver.executeScript('window.metamask.updateCurrentLocale(arguments[0])', code) -} - -async function setProviderType (type) { - await driver.executeScript('window.metamask.setProviderType(arguments[0])', type) -} - -async function cleanScreenShotDir () { - await pify(rimraf)(`./test-artifacts/screens/`) -} - -async function captureScreenShot (label) { - const shotIndex = screenshotCount.toString().padStart(4, '0') - screenshotCount++ - const artifactDir = `./test-artifacts/screens/` - await pify(mkdirp)(artifactDir) - // capture screenshot - const screenshot = await driver.takeScreenshot() - await pify(fs.writeFile)(`${artifactDir}/${shotIndex} - ${label}.png`, screenshot, { encoding: 'base64' }) -} - -async function generateGif () { - // calculate screenshot size - const screenshot = await driver.takeScreenshot() - const pngBuffer = Buffer.from(screenshot, 'base64') - const size = sizeOfPng.calculate(pngBuffer) - - // read only the english pngs into gif - const encoder = new GIFEncoder(size.width, size.height) - const stream = pngFileStream('./test-artifacts/screens/* (en).png') - .pipe(encoder.createWriteStream({ repeat: 0, delay: 1000, quality: 10 })) - .pipe(fs.createWriteStream('./test-artifacts/screens/walkthrough (en).gif')) - - // wait for end - await pify(endOfStream)(stream) -} - -async function verboseReportOnFailure (test) { - const artifactDir = `./test-artifacts/${test.title}` - const filepathBase = `${artifactDir}/test-failure` - await pify(mkdirp)(artifactDir) - // capture screenshot - const screenshot = await driver.takeScreenshot() - await pify(fs.writeFile)(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) - // capture dom source - const htmlSource = await driver.getPageSource() - await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource) -} - -async function requestEther (address) { - const accounts = await eth.accounts() - await eth.sendTransaction({ from: accounts[0], to: address, value: 1 * 1e18, data: '0x0' }) -} |