Browse Source

integration-tests: memberships

Mokhtar Naamani 4 years ago
parent
commit
f00b0f6916

+ 3 - 2
tests/network-tests/package.json

@@ -12,6 +12,7 @@
     "format": "prettier ./ --write "
   },
   "dependencies": {
+    "@apollo/client": "^3.2.5",
     "@joystream/types": "^0.15.0",
     "@polkadot/api": "^2.4.1",
     "@polkadot/keyring": "^3.6.1",
@@ -20,10 +21,10 @@
     "@types/lowdb": "^1.0.9",
     "async-lock": "^1.2.0",
     "bn.js": "^4.11.8",
+    "cross-fetch": "^3.0.6",
     "dotenv": "^8.2.0",
     "fs": "^0.0.1-security",
-    "uuid": "^7.0.3",
-    "@apollo/client": "^3.2.5"
+    "uuid": "^7.0.3"
   },
   "devDependencies": {
     "@polkadot/ts": "^0.3.14",

+ 2 - 2
tests/network-tests/run-test-scenario.sh

@@ -6,8 +6,8 @@ cd $SCRIPT_PATH
 
 # pass the scenario name without .ts extension
 SCENARIO=$1
-# fallback to full.ts scenario if not specified
-SCENARIO=${SCENARIO:=full}
+# fallback if scenario if not specified
+SCENARIO=${SCENARIO:=olympia}
 
 # Execute the tests
 time DEBUG=* yarn workspace network-tests node-ts-strict src/scenarios/${SCENARIO}.ts

+ 6 - 7
tests/network-tests/run-tests.sh

@@ -29,13 +29,13 @@ echo "{
 # Make Alice a member
 echo '
   [{
-    "member_id":0,
-    "root_account":"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
-    "controller_account":"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
+    "member_id": 0,
+    "root_account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
+    "controller_account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
     "handle":"alice",
     "avatar_uri":"https://alice.com/avatar.png",
     "about":"Alice",
-    "registered_at_time":0
+    "name": "Alice"
   }]
 ' > ${DATA_PATH}/initial-members.json
 
@@ -83,6 +83,7 @@ else
   docker rm $id
 
   # Display runtime version before runtime upgrade
+  sleep 5
   yarn workspace api-scripts tsnode-strict src/status.ts | grep Runtime
 
   echo "Performing runtime upgrade."
@@ -93,9 +94,7 @@ else
 fi
 
 # Display runtime version
+sleep 5
 yarn workspace api-scripts tsnode-strict src/status.ts | grep Runtime
 
-echo "Waiting for chain to startup..."
-sleep 10
-
 ./run-test-scenario.sh $1

File diff suppressed because it is too large
+ 315 - 497
tests/network-tests/src/Api.ts


+ 4 - 2
tests/network-tests/src/Scenario.ts

@@ -2,12 +2,13 @@ import { WsProvider } from '@polkadot/api'
 import { ApiFactory } from './Api'
 import { QueryNodeApi } from './QueryNodeApi'
 import { config } from 'dotenv'
-import { ApolloClient, InMemoryCache } from '@apollo/client'
+import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'
 import Debugger from 'debug'
 import { Flow } from './Flow'
 import { Job } from './Job'
 import { JobManager } from './JobManager'
 import { ResourceManager } from './Resources'
+import fetch from 'cross-fetch'
 
 export type ScenarioProps = {
   env: NodeJS.ProcessEnv
@@ -33,7 +34,8 @@ export async function scenario(scene: (props: ScenarioProps) => Promise<void>):
   const queryNodeUrl: string = env.QUERY_NODE_URL || 'http://127.0.0.1:8081/graphql'
 
   const queryNodeProvider = new ApolloClient({
-    uri: queryNodeUrl,
+    link: new HttpLink({ uri: queryNodeUrl, fetch }),
+    // uri: queryNodeUrl,
     cache: new InMemoryCache(),
     defaultOptions: { query: { fetchPolicy: 'no-cache', errorPolicy: 'all' } },
   })

+ 55 - 30
tests/network-tests/src/fixtures/membershipModule.ts

@@ -2,19 +2,22 @@ import { Api } from '../Api'
 import BN from 'bn.js'
 import { assert } from 'chai'
 import { BaseFixture } from '../Fixture'
-import { PaidTermId, MemberId } from '@joystream/types/members'
+import { MemberId } from '@joystream/types/common'
 import Debugger from 'debug'
+import { ISubmittableResult } from '@polkadot/types/types'
+
+function generateHandleFromAccountId(accountId: string): string {
+  return `handle${accountId.substring(0, 14)}`
+}
 
 export class BuyMembershipHappyCaseFixture extends BaseFixture {
   private accounts: string[]
-  private paidTerms: PaidTermId
   private debug: Debugger.Debugger
   private memberIds: MemberId[] = []
 
-  public constructor(api: Api, accounts: string[], paidTerms: PaidTermId) {
+  public constructor(api: Api, accounts: string[]) {
     super(api)
     this.accounts = accounts
-    this.paidTerms = paidTerms
     this.debug = Debugger('fixture:BuyMembershipHappyCaseFixture')
   }
 
@@ -22,55 +25,74 @@ export class BuyMembershipHappyCaseFixture extends BaseFixture {
     return this.memberIds.slice()
   }
 
+  // TODO: Factor our this method using mixin pattern https://www.typescriptlang.org/docs/handbook/mixins.html
+  // Buy a membership, setting root and controller accounts to be the same as the origin/sender account id
+  // and handle generated from account id.
+  private async buyMembership(account: string): Promise<ISubmittableResult> {
+    const handle = generateHandleFromAccountId(account)
+    return this.api.signAndSend(
+      this.api.tx.members.buyMembership({
+        root_account: account,
+        controller_account: account,
+        handle,
+      }),
+      account
+    )
+  }
+
   async execute(): Promise<void> {
     // Fee estimation and transfer
-    const membershipFee: BN = await this.api.getMembershipFee(this.paidTerms)
-    const membershipTransactionFee: BN = this.api.estimateBuyMembershipFee(
-      this.accounts[0],
-      this.paidTerms,
-      'member_name_which_is_longer_than_expected'
-    )
+    const membershipFee: BN = await this.api.getMembershipFee()
+    const membershipTransactionFee: BN = this.api.estimateBuyMembershipFee(this.accounts[0], 'handle')
+    const estimatedFee = membershipTransactionFee.add(new BN(membershipFee))
 
-    this.api.treasuryTransferBalanceToAccounts(this.accounts, membershipTransactionFee.add(new BN(membershipFee)))
+    this.api.treasuryTransferBalanceToAccounts(this.accounts, estimatedFee)
 
-    this.memberIds = (
-      await Promise.all(
-        this.accounts.map((account) =>
-          this.api.buyMembership(account, this.paidTerms, `member${account.substring(0, 14)}`)
-        )
-      )
-    )
+    this.memberIds = (await Promise.all(this.accounts.map((account) => this.buyMembership(account))))
       .map(({ events }) => this.api.findMemberRegisteredEvent(events))
       .filter((id) => id !== undefined) as MemberId[]
 
     this.debug(`Registered ${this.memberIds.length} new members`)
 
     assert.equal(this.memberIds.length, this.accounts.length)
+
+    // Assert that created members have expected handle and root and controller accounts
   }
 }
 
 export class BuyMembershipWithInsufficienFundsFixture extends BaseFixture {
   private account: string
-  private paidTerms: PaidTermId
 
-  public constructor(api: Api, account: string, paidTerms: PaidTermId) {
+  public constructor(api: Api, account: string) {
     super(api)
     this.account = account
-    this.paidTerms = paidTerms
   }
 
-  async execute(): Promise<void> {
-    // Assertions
-    const membership = await this.api.getMemberIds(this.account)
+  // Buy a membership, setting root and controller accounts to be the same as the origin/sender account id
+  // and handle generated from account id.
+  private async buyMembership(account: string): Promise<ISubmittableResult> {
+    const handle = generateHandleFromAccountId(account)
+    return this.api.signAndSend(
+      this.api.tx.members.buyMembership({
+        root_account: account,
+        controller_account: account,
+        handle,
+      }),
+      account
+    )
+  }
 
-    assert(membership.length === 0, 'Account must not be associated with a member')
+  async execute(): Promise<void> {
+    // It is acceptable for same account to register a new member account
+    // So no need to assert
+    // const membership = await this.api.getMemberIds(this.account)
+    // assert(membership.length === 0, 'Account must not be associated with a member')
 
     // Fee estimation and transfer
-    const membershipFee: BN = await this.api.getMembershipFee(this.paidTerms)
+    const membershipFee: BN = await this.api.getMembershipFee()
     const membershipTransactionFee: BN = this.api.estimateBuyMembershipFee(
       this.account,
-      this.paidTerms,
-      'member_name_which_is_longer_than_expected'
+      generateHandleFromAccountId(this.account)
     )
 
     // Only provide enough funds for transaction fee but not enough to cover the membership fee
@@ -83,9 +105,12 @@ export class BuyMembershipWithInsufficienFundsFixture extends BaseFixture {
       'Account already has sufficient balance to purchase membership'
     )
 
-    this.expectDispatchError(
-      await this.api.buyMembership(this.account, this.paidTerms, `late_member_${this.account.substring(0, 8)}`),
+    const result = this.expectDispatchError(
+      await this.buyMembership(this.account),
       'Buying membership with insufficient funds should fail.'
     )
+
+    // Assert that failure is because of lack of balance
+    assert.equal(this.api.getErrorNameFromExtrinsicFailedRecord(result), 'NotEnoughBalanceToBuyMembership')
   }
 }

+ 1 - 5
tests/network-tests/src/fixtures/sudoHireLead.ts

@@ -7,14 +7,12 @@ import {
 } from './workingGroupModule'
 import { BuyMembershipHappyCaseFixture } from './membershipModule'
 import { Api, WorkingGroups } from '../Api'
-import { OpeningId } from '@joystream/types/hiring'
-import { PaidTermId } from '@joystream/types/members'
+import { OpeningId } from '@joystream/types/working-group'
 import BN from 'bn.js'
 import { assert } from 'chai'
 
 export class SudoHireLeadFixture extends BaseFixture {
   private leadAccount: string
-  private paidTerms: PaidTermId
   private applicationStake: BN
   private roleStake: BN
   private openingActivationDelay: BN
@@ -26,7 +24,6 @@ export class SudoHireLeadFixture extends BaseFixture {
   constructor(
     api: Api,
     leadAccount: string,
-    paidTerms: PaidTermId,
     applicationStake: BN,
     roleStake: BN,
     openingActivationDelay: BN,
@@ -37,7 +34,6 @@ export class SudoHireLeadFixture extends BaseFixture {
   ) {
     super(api)
     this.leadAccount = leadAccount
-    this.paidTerms = paidTerms
     this.applicationStake = applicationStake
     this.roleStake = roleStake
     this.openingActivationDelay = openingActivationDelay

+ 6 - 8
tests/network-tests/src/flows/membership/creatingMemberships.ts

@@ -3,8 +3,7 @@ import {
   BuyMembershipHappyCaseFixture,
   BuyMembershipWithInsufficienFundsFixture,
 } from '../../fixtures/membershipModule'
-import { PaidTermId } from '@joystream/types/members'
-import BN from 'bn.js'
+
 import Debugger from 'debug'
 import { FixtureRunner } from '../../Fixture'
 import { assert } from 'chai'
@@ -16,20 +15,19 @@ export default async function membershipCreation({ api, env }: FlowProps): Promi
 
   const N: number = +env.MEMBERSHIP_CREATION_N!
   assert(N > 0)
-  const nAccounts = api.createKeyPairs(N).map((key) => key.address)
-  const aAccount = api.createKeyPairs(1)[0].address
-  const paidTerms: PaidTermId = api.createPaidTermId(new BN(+env.MEMBERSHIP_PAID_TERMS!))
 
   // Assert membership can be bought if sufficient funds are available
-  const happyCaseFixture = new BuyMembershipHappyCaseFixture(api, nAccounts, paidTerms)
+  const nAccounts = api.createKeyPairs(N).map((key) => key.address)
+  const happyCaseFixture = new BuyMembershipHappyCaseFixture(api, nAccounts)
   await new FixtureRunner(happyCaseFixture).run()
 
   // Assert account can not buy the membership with insufficient funds
-  const insufficientFundsFixture = new BuyMembershipWithInsufficienFundsFixture(api, aAccount, paidTerms)
+  const aAccount = api.createKeyPairs(1)[0].address
+  const insufficientFundsFixture = new BuyMembershipWithInsufficienFundsFixture(api, aAccount)
   await new FixtureRunner(insufficientFundsFixture).run()
 
   // Assert account was able to buy the membership with sufficient funds
-  const buyMembershipAfterAccountTopUp = new BuyMembershipHappyCaseFixture(api, [aAccount], paidTerms)
+  const buyMembershipAfterAccountTopUp = new BuyMembershipHappyCaseFixture(api, [aAccount])
   await new FixtureRunner(buyMembershipAfterAccountTopUp).run()
 
   debug('Done')

+ 6 - 0
tests/network-tests/src/scenarios/olympia.ts

@@ -0,0 +1,6 @@
+import creatingMemberships from '../flows/membership/creatingMemberships'
+import { scenario } from '../Scenario'
+
+scenario(async ({ job }) => {
+  job('creating members', creatingMemberships)
+})

+ 18 - 6
tests/network-tests/src/sender.ts

@@ -81,10 +81,17 @@ export class Sender {
           } = record
           const err = data[0] as DispatchError
           if (err.isModule) {
-            const { name } = (this.api.registry as TypeRegistry).findMetaError(err.asModule)
-            this.debug('Dispatch Error:', name, sentTx)
+            try {
+              const { name } = this.api.registry.findMetaError(err.asModule)
+              this.debug('Dispatch Error:', name, sentTx)
+            } catch (findmetaerror) {
+              // example Error: findMetaError: Unable to find Error with index 0x1400/[{"index":20,"error":0}]
+              // Happens for dispatchable calls that don't explicitly use `-> DispatchResult` return value even
+              // if they return an error enum variant from the decl_error! macro
+              this.debug('Dispatch Error (error details not found):', err.asModule.toHuman(), sentTx)
+            }
           } else {
-            this.debug('Dispatch Error:', sentTx)
+            this.debug('Dispatch Error:', err.toHuman(), sentTx)
           }
         } else {
           assert(success)
@@ -95,10 +102,15 @@ export class Sender {
             if (dispatchResult.isError) {
               const err = dispatchResult.asError
               if (err.isModule) {
-                const { name } = (this.api.registry as TypeRegistry).findMetaError(err.asModule)
-                this.debug('Sudo Dispatch Failed', name, sentTx)
+                try {
+                  const { name } = this.api.registry.findMetaError(err.asModule)
+                  this.debug('Sudo Dispatch Failed', name, sentTx)
+                } catch (findmetaerror) {
+                  // example Error: findMetaError: Unable to find Error with index 0x1400/[{"index":20,"error":0}]
+                  this.debug('Sudo Dispatch Failed (error details not found)', err.asModule.toHuman(), sentTx)
+                }
               } else {
-                this.debug('Sudo Dispatch Failed', sentTx)
+                this.debug('Sudo Dispatch Failed', err.toHuman(), sentTx)
               }
             }
           }

+ 0 - 5
tests/network-tests/src/utils.ts

@@ -4,7 +4,6 @@ import { blake2AsHex } from '@polkadot/util-crypto'
 import BN from 'bn.js'
 import fs from 'fs'
 import { decodeAddress } from '@polkadot/keyring'
-import { Seat } from '@joystream/types/council'
 
 export class Utils {
   private static LENGTH_ADDRESS = 32 + 1 // publicKey + prefix
@@ -39,10 +38,6 @@ export class Utils {
     return new Promise((resolve) => setTimeout(resolve, ms))
   }
 
-  public static getTotalStake(seat: Seat): BN {
-    return new BN(+seat.stake.toString() + seat.backers.reduce((a, baker) => a + +baker.stake.toString(), 0))
-  }
-
   public static readRuntimeFromFile(path: string): string {
     return '0x' + fs.readFileSync(path).toString('hex')
   }

+ 1 - 0
utils/api-scripts/src/dev-set-runtime-code.ts

@@ -37,6 +37,7 @@ async function main() {
       break
     } catch (err) {
       // failed to connect to node
+      // Exceptions are not being caught!?
     }
 
     if (retry-- === 0) {

+ 1 - 0
utils/api-scripts/src/status.ts

@@ -19,6 +19,7 @@ async function main() {
       await api.isReady
       break
     } catch (err) {
+      // Exceptions are not being caught!?
       // failed to connect to node
     }
 

+ 28 - 13
yarn.lock

@@ -1174,7 +1174,7 @@
     typeorm-model-generator "^0.4.2"
     warthog "https://github.com/metmirr/warthog/releases/download/v2.22.0/warthog-v2.22.0.tgz"
 
-"@dzlzv/hydra-indexer-lib@0.0.18-alpha.2", "@dzlzv/hydra-indexer-lib@^0.0.18-alpha.2":
+"@dzlzv/hydra-indexer-lib@^0.0.18-alpha.2":
   version "0.0.18-alpha.2"
   resolved "https://registry.yarnpkg.com/@dzlzv/hydra-indexer-lib/-/hydra-indexer-lib-0.0.18-alpha.2.tgz#b5f713d4221721c6d2d4c75dbbebbc51a67d3f0c"
   integrity sha512-E3/qJFpmLDWdKFCaHF/li4uXKlJ9s4aE/YK+a3W7uc1I6VTk7qDVDEJlM2p4j95ZNCKUB60qUUWDEf8q7A4ICg==
@@ -2928,7 +2928,7 @@
     is-ipfs "^0.6.0"
     recursive-fs "^1.1.2"
 
-"@polkadot/api-contract@2.4.1", "@polkadot/api-contract@^2.4.1":
+"@polkadot/api-contract@^2.4.1":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-2.4.1.tgz#25654dd6d42bc1ef50915353a37a1b348ecbe645"
   integrity sha512-HvEArtY+/7gSHfgM3coxuBCkKsgWGpP89htWG4djvqh6Ogwr+KrNYDssGl/MqNVqjC9JX2l3RVL4NAGbJwuGng==
@@ -2941,7 +2941,7 @@
     bn.js "^5.1.3"
     rxjs "^6.6.3"
 
-"@polkadot/api-derive@2.4.1", "@polkadot/api-derive@^2.4.1":
+"@polkadot/api-derive@^2.4.1":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-2.4.1.tgz#b5a3ee0910d735722e9836ec9b13df17059ca3e3"
   integrity sha512-xDWQj2UsiMx25IfxtjmEXVFrQh7tZmPsLlDthTqtUC9VxuZoQGg0PuhntLuN90gfBii9to6dkXu8xn3WGlQROg==
@@ -2957,7 +2957,7 @@
     memoizee "^0.4.14"
     rxjs "^6.6.3"
 
-"@polkadot/api@2.4.1", "@polkadot/api@^2.1.1", "@polkadot/api@^2.4.1":
+"@polkadot/api@^2.1.1", "@polkadot/api@^2.4.1":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-2.4.1.tgz#4c7e9b87ee855cc7d273f4a9887d66f50aef7b83"
   integrity sha512-P4/a3fIdhjm6ukpeG2GiXkum5mEsKk4UnHbIi8dTlH8brAgcCM4CsT1ThlIt1ugZbvJ53QoCxCttlfKUIsj8yA==
@@ -3065,7 +3065,7 @@
   dependencies:
     "@babel/runtime" "^7.10.5"
 
-"@polkadot/keyring@3.6.1", "@polkadot/keyring@^3.6.1":
+"@polkadot/keyring@^3.6.1":
   version "3.6.1"
   resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-3.6.1.tgz#51a4a08e650f9717115b4ee6ccf8f6dccd273594"
   integrity sha512-JbW4M5Ct3HaX3vgoa/UWAQVF/0sc1PbbA2D6v0KKaJkXl+EYVP9uyOYAoRCppB6ENZThz7CUJVQp8trs8WTrFQ==
@@ -3074,7 +3074,7 @@
     "@polkadot/util" "3.6.1"
     "@polkadot/util-crypto" "3.6.1"
 
-"@polkadot/metadata@2.4.1", "@polkadot/metadata@^2.4.1":
+"@polkadot/metadata@^2.4.1":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/metadata/-/metadata-2.4.1.tgz#6530302e5ee4e21a07205b9e329318ae831600f1"
   integrity sha512-QIhppVkyRheLi/VU9qu5Xnc+HYKmNaGZonbgt6W49S6UXAIwEnhHLry8tnC/LC2MlN+tKEyWOyCoyXEXqO6myg==
@@ -3114,7 +3114,7 @@
     qrcode-generator "^1.4.4"
     react-qr-reader "^2.2.1"
 
-"@polkadot/rpc-core@2.4.1", "@polkadot/rpc-core@^2.4.1":
+"@polkadot/rpc-core@^2.4.1":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-2.4.1.tgz#c2f609322678caba738f914c0d0b7bcd6aa2d6a6"
   integrity sha512-41YGmmVHAXuhZMsNWhMTORC6Hmhu3PXCXRf74HzEkmr6YWaHF4LP3cCCdMpFwsyIy87kyU2q7s9v6JVSEIKIIQ==
@@ -3127,7 +3127,7 @@
     memoizee "^0.4.14"
     rxjs "^6.6.3"
 
-"@polkadot/rpc-provider@2.4.1", "@polkadot/rpc-provider@^2.4.1":
+"@polkadot/rpc-provider@^2.4.1":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-2.4.1.tgz#841cc272ad4a7ac9ce268d056a8409bf6df85f76"
   integrity sha512-hK1rd1LL04dnFF+SqbTeNSRzzG3NJ0PRDic8d584DUKs5GBW39KfYPUcGq4+fbGPLwmKTVQ/iu//LnfYIpF9cw==
@@ -3173,7 +3173,7 @@
     websocket "^1.0.32"
     yargs "^16.1.0"
 
-"@polkadot/types-known@2.4.1", "@polkadot/types-known@^2.4.1":
+"@polkadot/types-known@^2.4.1":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-2.4.1.tgz#3f82a67903fd12a5eca6910af7230757a282dcf2"
   integrity sha512-lOa0qWHq0kRYpiOAqlLXQrrwLRBw/ZJGqh097PDmxuG1QdZHzTxj5RBPxwS19m3Qdy6v9kwduVhpBYZuKXdkxg==
@@ -3183,7 +3183,7 @@
     "@polkadot/util" "^3.6.1"
     bn.js "^5.1.3"
 
-"@polkadot/types@2.4.1", "@polkadot/types@^2.4.1":
+"@polkadot/types@^2.4.1":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-2.4.1.tgz#8f47dc92a25a7ddb6378c5bee004a5a6590483da"
   integrity sha512-LB26a7ptBxW2FX7WIpbbDa1CAqAb3Twe3wEu+pGX8V5cPY2Qa+70rfAhLnFui8VbnRDf2e+PY4zgrVcRiC9T4Q==
@@ -3274,7 +3274,7 @@
     chalk "^4.1.0"
     yargs "^15.4.1"
 
-"@polkadot/wasm-crypto@1.4.1", "@polkadot/wasm-crypto@^1.4.1":
+"@polkadot/wasm-crypto@^1.4.1":
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-1.4.1.tgz#0a053d0c2587da30fb5313cef81f8d9a52029c68"
   integrity sha512-GPBCh8YvQmA5bobI4rqRkUhrEHkEWU1+lcJVPbZYsa7jiHFaZpzCLrGQfiqW/vtbU1aBS2wmJ0x1nlt33B9QqQ==
@@ -7379,7 +7379,12 @@ bluebird@^3.1.1, bluebird@^3.3.5, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
   integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
 
-bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.1.3:
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.8, bn.js@^4.4.0:
+  version "4.11.9"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
+  integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
+
+bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.1.3:
   version "5.1.3"
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
   integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
@@ -26425,11 +26430,21 @@ typescript-formatter@^7.2.2:
     commandpost "^1.0.0"
     editorconfig "^0.15.0"
 
-typescript@3.5.2, typescript@^3.0.3, typescript@^3.8.3, typescript@^3.9.5, typescript@^3.9.6, typescript@^3.9.7, typescript@^4.0.3:
+typescript@3.5.2:
+  version "3.5.2"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c"
+  integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==
+
+typescript@^3.0.3, typescript@^3.8.3, typescript@^3.9.5, typescript@^3.9.6, typescript@^3.9.7:
   version "3.9.7"
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
   integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
 
+typescript@^4.0.3:
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
+  integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
+
 ua-parser-js@^0.7.18:
   version "0.7.23"
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.23.tgz#704d67f951e13195fbcd3d78818577f5bc1d547b"

Some files were not shown because too many files changed in this diff